diff --git a/doc/indevs.texi b/doc/indevs.texi index 5be647f70a..9d8020311a 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -625,6 +625,12 @@ 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. +@item use_video_device_timestamps +If set to @option{false}, the timestamp for video frames will be +derived from the wallclock instead of the timestamp provided by +the capture device. This allows working around devices that +provide unreliable timestamps. + @end table @subsection Examples diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index cc0bef0474..5e6eb9c85d 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1310,6 +1310,7 @@ static const AVOption options[] = { { "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 }, + { "use_video_device_timestamps", "use device instead of wallclock timestamps for video frames", OFFSET(use_video_device_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 06ded2ba96..5a2691518c 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -312,6 +312,7 @@ struct dshow_ctx { char *audio_filter_save_file; char *video_filter_load_file; char *video_filter_save_file; + int use_video_device_timestamps; IBaseFilter *device_filter[2]; IPin *device_pin[2]; diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 3dae405e65..8e56dccbfe 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -309,10 +309,14 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) if (!sample) return E_POINTER; + priv_data = pin->filter->priv_data; + s = priv_data; + ctx = s->priv_data; + IMediaSample_GetTime(sample, &orig_curtime, &dummy); orig_curtime += pin->filter->start_time; IReferenceClock_GetTime(clock, &graphtime); - if (devtype == VideoDevice) { + if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ IReferenceClock_GetTime(clock, &curtime); } else { @@ -322,7 +326,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) like 437650244077016960 which FFmpeg doesn't like. TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, - "dshow dropping initial (or ending) audio frame with odd PTS too high %"PRId64"\n", curtime); + "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", curtime); return S_OK; } curtime += pin->filter->start_time; @@ -330,9 +334,6 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) buf_size = IMediaSample_GetActualDataLength(sample); IMediaSample_GetPointer(sample, &buf); - priv_data = pin->filter->priv_data; - s = priv_data; - ctx = s->priv_data; index = pin->filter->stream_index; av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d "