|
|
@ -190,7 +190,8 @@ extern "C" { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
#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 |
|
|
|
#ifdef WIN32 |
|
|
|
// http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
|
|
|
|
// 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; |
|
|
|
AVInterruptCallbackMetadata* metadata = (AVInterruptCallbackMetadata*)ptr; |
|
|
|
assert(metadata); |
|
|
|
assert(metadata); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (metadata->timeout_after_ms == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return 0; // timeout is disabled
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
timespec now; |
|
|
|
timespec now; |
|
|
|
get_monotonic_time(&now); |
|
|
|
get_monotonic_time(&now); |
|
|
|
|
|
|
|
|
|
|
@ -741,7 +747,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) |
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
/* 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); |
|
|
|
get_monotonic_time(&interrupt_metadata.value); |
|
|
|
|
|
|
|
|
|
|
|
ic = avformat_alloc_context(); |
|
|
|
ic = avformat_alloc_context(); |
|
|
@ -832,6 +838,11 @@ bool CvCapture_FFMPEG::open( const char* _filename ) |
|
|
|
|
|
|
|
|
|
|
|
exit_func: |
|
|
|
exit_func: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
|
|
|
|
// deactivate interrupt callback
|
|
|
|
|
|
|
|
interrupt_metadata.timeout_after_ms = 0; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if( !valid ) |
|
|
|
if( !valid ) |
|
|
|
close(); |
|
|
|
close(); |
|
|
|
|
|
|
|
|
|
|
@ -855,6 +866,12 @@ bool CvCapture_FFMPEG::grabFrame() |
|
|
|
|
|
|
|
|
|
|
|
picture_pts = AV_NOPTS_VALUE_; |
|
|
|
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
|
|
|
|
// get the next frame
|
|
|
|
while (!valid) |
|
|
|
while (!valid) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -903,11 +920,6 @@ bool CvCapture_FFMPEG::grabFrame() |
|
|
|
picture_pts = packet.pts != AV_NOPTS_VALUE_ && packet.pts != 0 ? packet.pts : packet.dts; |
|
|
|
picture_pts = packet.pts != AV_NOPTS_VALUE_ && packet.pts != 0 ? packet.pts : packet.dts; |
|
|
|
frame_number++; |
|
|
|
frame_number++; |
|
|
|
valid = true; |
|
|
|
valid = true; |
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
|
|
|
|
// update interrupt value
|
|
|
|
|
|
|
|
get_monotonic_time(&interrupt_metadata.value); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
@ -920,6 +932,11 @@ bool CvCapture_FFMPEG::grabFrame() |
|
|
|
if( valid && first_frame_number < 0 ) |
|
|
|
if( valid && first_frame_number < 0 ) |
|
|
|
first_frame_number = dts_to_frame_number(picture_pts); |
|
|
|
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 if we have a new picture or not
|
|
|
|
return valid; |
|
|
|
return valid; |
|
|
|
} |
|
|
|
} |
|
|
@ -2382,7 +2399,7 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma |
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
/* 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); |
|
|
|
get_monotonic_time(&interrupt_metadata.value); |
|
|
|
|
|
|
|
|
|
|
|
ctx_ = avformat_alloc_context(); |
|
|
|
ctx_ = avformat_alloc_context(); |
|
|
@ -2478,6 +2495,11 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma |
|
|
|
|
|
|
|
|
|
|
|
av_init_packet(&pkt_); |
|
|
|
av_init_packet(&pkt_); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
|
|
|
|
// deactivate interrupt callback
|
|
|
|
|
|
|
|
interrupt_metadata.timeout_after_ms = 0; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2499,6 +2521,14 @@ void InputMediaStream_FFMPEG::close() |
|
|
|
|
|
|
|
|
|
|
|
bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile) |
|
|
|
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
|
|
|
|
// free last packet if exist
|
|
|
|
if (pkt_.data) |
|
|
|
if (pkt_.data) |
|
|
|
av_free_packet(&pkt_); |
|
|
|
av_free_packet(&pkt_); |
|
|
@ -2518,16 +2548,11 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi |
|
|
|
if (ret == AVERROR(EAGAIN)) |
|
|
|
if (ret == AVERROR(EAGAIN)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
|
|
|
|
// update interrupt value
|
|
|
|
|
|
|
|
get_monotonic_time(&interrupt_metadata.value); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ret < 0) |
|
|
|
if (ret < 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (ret == (int)AVERROR_EOF) |
|
|
|
if (ret == (int)AVERROR_EOF) |
|
|
|
*endOfFile = true; |
|
|
|
*endOfFile = true; |
|
|
|
return false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (pkt_.stream_index != video_stream_id_) |
|
|
|
if (pkt_.stream_index != video_stream_id_) |
|
|
@ -2536,14 +2561,23 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*data = pkt_.data; |
|
|
|
#if USE_AV_INTERRUPT_CALLBACK |
|
|
|
*size = pkt_.size; |
|
|
|
// deactivate interrupt callback
|
|
|
|
*endOfFile = false; |
|
|
|
interrupt_metadata.timeout_after_ms = 0; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*data = pkt_.data; |
|
|
|
|
|
|
|
*size = pkt_.size; |
|
|
|
|
|
|
|
*endOfFile = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height) |
|
|
|
InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height) |
|
|
|