From 6f139b4f8e604237bd4113557830435e540773fd Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 5 Apr 2016 14:18:44 +0300 Subject: [PATCH] ffmpeg: interrupt callback fix backport from master --- modules/highgui/src/cap_ffmpeg_impl.hpp | 70 ++++++++++++++++++------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/modules/highgui/src/cap_ffmpeg_impl.hpp b/modules/highgui/src/cap_ffmpeg_impl.hpp index de8fc4d9e3..dc3e10d490 100644 --- a/modules/highgui/src/cap_ffmpeg_impl.hpp +++ b/modules/highgui/src/cap_ffmpeg_impl.hpp @@ -190,7 +190,8 @@ extern "C" { #endif #if USE_AV_INTERRUPT_CALLBACK -#define LIBAVFORMAT_INTERRUPT_TIMEOUT_MS 30000 +#define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 30000 +#define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 30000 #ifdef WIN32 // http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows @@ -375,6 +376,11 @@ inline int _opencv_ffmpeg_interrupt_callback(void *ptr) AVInterruptCallbackMetadata* metadata = (AVInterruptCallbackMetadata*)ptr; assert(metadata); + if (metadata->timeout_after_ms == 0) + { + return 0; // timeout is disabled + } + timespec now; get_monotonic_time(&now); @@ -741,7 +747,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) #if USE_AV_INTERRUPT_CALLBACK /* interrupt callback */ - interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_TIMEOUT_MS; + interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS; get_monotonic_time(&interrupt_metadata.value); ic = avformat_alloc_context(); @@ -832,6 +838,11 @@ bool CvCapture_FFMPEG::open( const char* _filename ) exit_func: +#if USE_AV_INTERRUPT_CALLBACK + // deactivate interrupt callback + interrupt_metadata.timeout_after_ms = 0; +#endif + if( !valid ) close(); @@ -855,6 +866,12 @@ bool CvCapture_FFMPEG::grabFrame() picture_pts = AV_NOPTS_VALUE_; +#if USE_AV_INTERRUPT_CALLBACK + // activate interrupt callback + get_monotonic_time(&interrupt_metadata.value); + interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS; +#endif + // get the next frame while (!valid) { @@ -903,11 +920,6 @@ bool CvCapture_FFMPEG::grabFrame() picture_pts = packet.pts != AV_NOPTS_VALUE_ && packet.pts != 0 ? packet.pts : packet.dts; frame_number++; valid = true; - -#if USE_AV_INTERRUPT_CALLBACK - // update interrupt value - get_monotonic_time(&interrupt_metadata.value); -#endif } else { @@ -920,6 +932,11 @@ bool CvCapture_FFMPEG::grabFrame() if( valid && first_frame_number < 0 ) first_frame_number = dts_to_frame_number(picture_pts); +#if USE_AV_INTERRUPT_CALLBACK + // deactivate interrupt callback + interrupt_metadata.timeout_after_ms = 0; +#endif + // return if we have a new picture or not return valid; } @@ -2382,7 +2399,7 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma #if USE_AV_INTERRUPT_CALLBACK /* interrupt callback */ - interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_TIMEOUT_MS; + interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS; get_monotonic_time(&interrupt_metadata.value); ctx_ = avformat_alloc_context(); @@ -2478,6 +2495,11 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma av_init_packet(&pkt_); +#if USE_AV_INTERRUPT_CALLBACK + // deactivate interrupt callback + interrupt_metadata.timeout_after_ms = 0; +#endif + return true; } @@ -2499,6 +2521,14 @@ void InputMediaStream_FFMPEG::close() bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile) { + bool result = false; + +#if USE_AV_INTERRUPT_CALLBACK + // activate interrupt callback + get_monotonic_time(&interrupt_metadata.value); + interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS; +#endif + // free last packet if exist if (pkt_.data) av_free_packet(&pkt_); @@ -2518,16 +2548,11 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi if (ret == AVERROR(EAGAIN)) continue; -#if USE_AV_INTERRUPT_CALLBACK - // update interrupt value - get_monotonic_time(&interrupt_metadata.value); -#endif - if (ret < 0) { if (ret == (int)AVERROR_EOF) *endOfFile = true; - return false; + break; } if (pkt_.stream_index != video_stream_id_) @@ -2536,14 +2561,23 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi continue; } + result = true; break; } - *data = pkt_.data; - *size = pkt_.size; - *endOfFile = false; +#if USE_AV_INTERRUPT_CALLBACK + // deactivate interrupt callback + interrupt_metadata.timeout_after_ms = 0; +#endif - return true; + if (result) + { + *data = pkt_.data; + *size = pkt_.size; + *endOfFile = false; + } + + return result; } InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height)