diff options
author | Mate Sebok <smfinc.org@gmail.com> | 2015-04-22 18:38:38 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-04-22 20:12:36 +0200 |
commit | 4d98015dcf6562b5822a96f024ac8c94b95203a6 (patch) | |
tree | ccdf417deec93a4ceff5dda011de923c5b1a69f6 | |
parent | 53ff9a4ec9ce1ab4ff2ab92479b885260ff5cf4c (diff) | |
download | ffmpeg-4d98015dcf6562b5822a96f024ac8c94b95203a6.tar.gz |
dshow: add capture device save and load
Signed-off-by: Mate Sebok <smfinc.org@gmail.com>
Reviewed-by: Roger Pack <rogerdpack2@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | doc/indevs.texi | 24 | ||||
-rw-r--r-- | libavdevice/dshow.c | 97 | ||||
-rw-r--r-- | libavdevice/dshow_capture.h | 4 |
4 files changed, 123 insertions, 4 deletions
@@ -2543,7 +2543,7 @@ decklink_outdev_extralibs="-lstdc++" decklink_indev_deps="decklink pthreads" decklink_indev_extralibs="-lstdc++" dshow_indev_deps="IBaseFilter" -dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid -loleaut32" +dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid -loleaut32 -lshlwapi" dv1394_indev_deps="dv1394" dv1394_indev_select="dv_demuxer" fbdev_indev_deps="linux_fb_h" diff --git a/doc/indevs.texi b/doc/indevs.texi index 9818531e38..d5415bbc7c 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -350,6 +350,30 @@ If set to @option{true}, before capture starts, popup a display dialog to the end user, allowing them to manually modify TV audio (like mono vs. stereo, Language A,B or C). +@item audio_device_load +Load an audio capture filter device from file instead of searching +it by name. It may load additional parameters too, if the filter +supports the serialization of its properties to. +To use this an audio capture source has to be specified, but it can +be anything even fake one. + +@item audio_device_save +Save the currently used audio capture filter device and its +parameters (if the filter supports it) to a file. +If a file with the same name exists it will be overwritten. + +@item video_device_load +Load a video capture filter device from file instead of searching +it by name. It may load additional parameters too, if the filter +supports the serialization of its properties to. +To use this a video capture source has to be specified, but it can +be anything even fake one. + +@item video_device_save +Save the currently used video capture filter device and its +parameters (if the filter supports it) to a file. +If a file with the same name exists it will be overwritten. + @end table @subsection Examples diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index d03670e36f..62249785cb 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -27,6 +27,8 @@ #include "libavformat/riff.h" #include "avdevice.h" #include "libavcodec/raw.h" +#include "objidl.h" +#include "shlwapi.h" static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) @@ -728,12 +730,46 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, ICaptureGraphBuilder2 *graph_builder2 = NULL; int ret = AVERROR(EIO); int r; + IStream *ifile_stream = NULL; + IStream *ofile_stream = NULL; + IPersistStream *pers_stream = NULL; const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" }; - if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter)) < 0) { - ret = r; - goto error; + + if ( ((ctx->audio_filter_load_file) && (strlen(ctx->audio_filter_load_file)>0) && (sourcetype == AudioSourceDevice)) || + ((ctx->video_filter_load_file) && (strlen(ctx->video_filter_load_file)>0) && (sourcetype == VideoSourceDevice)) ) { + HRESULT hr; + char *filename = NULL; + + if (sourcetype == AudioSourceDevice) + filename = ctx->audio_filter_load_file; + else + filename = ctx->video_filter_load_file; + + hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_READ, &ifile_stream); + if (S_OK != hr) { + av_log(avctx, AV_LOG_ERROR, "Could not open capture filter description file.\n"); + goto error; + } + + hr = OleLoadFromStream(ifile_stream, &IID_IBaseFilter, (void **) &device_filter); + if (hr != S_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not load capture filter from file.\n"); + goto error; + } + + if (sourcetype == AudioSourceDevice) + av_log(avctx, AV_LOG_INFO, "Audio-"); + else + av_log(avctx, AV_LOG_INFO, "Video-"); + av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename); + } else { + + if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter)) < 0) { + ret = r; + goto error; + } } ctx->device_filter [devtype] = device_filter; @@ -758,6 +794,48 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, } ctx->capture_filter[devtype] = capture_filter; + if ( ((ctx->audio_filter_save_file) && (strlen(ctx->audio_filter_save_file)>0) && (sourcetype == AudioSourceDevice)) || + ((ctx->video_filter_save_file) && (strlen(ctx->video_filter_save_file)>0) && (sourcetype == VideoSourceDevice)) ) { + + HRESULT hr; + char *filename = NULL; + + if (sourcetype == AudioSourceDevice) + filename = ctx->audio_filter_save_file; + else + filename = ctx->video_filter_save_file; + + hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_CREATE | STGM_READWRITE, &ofile_stream); + if (S_OK != hr) { + av_log(avctx, AV_LOG_ERROR, "Could not create capture filter description file.\n"); + goto error; + } + + hr = IBaseFilter_QueryInterface(device_filter, &IID_IPersistStream, (void **) &pers_stream); + if (hr != S_OK) { + av_log(avctx, AV_LOG_ERROR, "Query for IPersistStream failed.\n"); + goto error; + } + + hr = OleSaveToStream(pers_stream, ofile_stream); + if (hr != S_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not save capture filter \n"); + goto error; + } + + hr = IStream_Commit(ofile_stream, STGC_DEFAULT); + if (S_OK != hr) { + av_log(avctx, AV_LOG_ERROR, "Could not commit capture filter data to file.\n"); + goto error; + } + + if (sourcetype == AudioSourceDevice) + av_log(avctx, AV_LOG_INFO, "Audio-"); + else + av_log(avctx, AV_LOG_INFO, "Video-"); + av_log(avctx, AV_LOG_INFO, "Capture filter saved successfully to file \"%s\".\n", filename); + } + r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter, filter_name[devtype]); if (r != S_OK) { @@ -802,6 +880,15 @@ error: if (graph_builder2 != NULL) ICaptureGraphBuilder2_Release(graph_builder2); + if (pers_stream) + IPersistStream_Release(pers_stream); + + if (ifile_stream) + IStream_Release(ifile_stream); + + if (ofile_stream) + IStream_Release(ofile_stream); + return ret; } @@ -1211,6 +1298,10 @@ static const AVOption options[] = { { "show_analog_tv_tuner_audio_dialog", "display property dialog for analog tuner audio filter", OFFSET(show_analog_tv_tuner_audio_dialog), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC, "show_analog_tv_tuner_dialog" }, { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "show_analog_tv_tuner_audio_dialog" }, { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "show_analog_tv_tuner_audio_dialog" }, + { "audio_device_load", "load audio capture filter device (and properties) from file", OFFSET(audio_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "audio_device_save", "save audio capture filter device (and properties) to file", OFFSET(audio_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "video_device_load", "load video capture filter device (and properties) from file", OFFSET(video_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "video_device_save", "save video capture filter device (and properties) to file", OFFSET(video_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index f258476099..ae2f1d3004 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -307,6 +307,10 @@ struct dshow_ctx { int show_audio_crossbar_connection_dialog; int show_analog_tv_tuner_dialog; int show_analog_tv_tuner_audio_dialog; + char *audio_filter_load_file; + char *audio_filter_save_file; + char *video_filter_load_file; + char *video_filter_save_file; IBaseFilter *device_filter[2]; IPin *device_pin[2]; |