From bc3c49518d89413a6cf3682fd1444c3ee4d90570 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Thu, 26 Apr 2012 07:07:37 +0000 Subject: [PATCH] ok, now positioning seem to work well, at least with ffmpeg 0.10.2 on MacOSX 10.7 --- modules/highgui/src/cap_ffmpeg_impl_v2.hpp | 269 +++++++-------------- modules/highgui/test/test_drawing.cpp | 6 +- modules/highgui/test/test_ffmpeg.cpp | 14 +- modules/highgui/test/test_grfmt.cpp | 6 +- modules/highgui/test/test_positioning.cpp | 34 +-- modules/highgui/test/test_video_io.cpp | 10 +- modules/highgui/test/test_video_pos.cpp | 22 +- 7 files changed, 149 insertions(+), 212 deletions(-) diff --git a/modules/highgui/src/cap_ffmpeg_impl_v2.hpp b/modules/highgui/src/cap_ffmpeg_impl_v2.hpp index 28e35a20a..288a3af06 100755 --- a/modules/highgui/src/cap_ffmpeg_impl_v2.hpp +++ b/modules/highgui/src/cap_ffmpeg_impl_v2.hpp @@ -134,6 +134,12 @@ extern "C" { #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif +#if defined(__APPLE__) +#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL) +#else +#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE) +#endif + int get_number_of_cpus(void) { #if defined WIN32 || defined _WIN32 @@ -148,11 +154,11 @@ int get_number_of_cpus(void) int mib[4]; size_t len = sizeof(numCPU); - /* set the mib for hw.ncpu */ + // set the mib for hw.ncpu mib[0] = CTL_HW; mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU; - /* get the number of CPUs from the system */ + // get the number of CPUs from the system sysctl(mib, 2, &numCPU, &len, NULL, 0); if( numCPU < 1 ) @@ -171,18 +177,6 @@ int get_number_of_cpus(void) } -char * FOURCC2str( int fourcc ) -{ - char * mystr=(char*)malloc(5); - mystr[0]=(char)((fourcc )&255); - mystr[1]=(char)((fourcc>> 8)&255); - mystr[2]=(char)((fourcc>>16)&255); - mystr[3]=(char)((fourcc>>24)&255); - mystr[4]=0; - return mystr; -} - - struct Image_FFMPEG { unsigned char* data; @@ -211,7 +205,6 @@ struct CvCapture_FFMPEG bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn); void init(); - bool reopen(); void seek(int64_t frame_number); void seek(double sec); @@ -238,7 +231,7 @@ struct CvCapture_FFMPEG Image_FFMPEG frame; struct SwsContext *img_convert_ctx; - int64_t frame_number; + int64_t frame_number, first_frame_number; double eps_zero; /* @@ -257,7 +250,8 @@ void CvCapture_FFMPEG::init() video_stream = -1; video_st = 0; picture = 0; - picture_pts = 0; + picture_pts = AV_NOPTS_VALUE_; + first_frame_number = -1; memset( &rgb_picture, 0, sizeof(rgb_picture) ); memset( &frame, 0, sizeof(frame) ); filename = 0; @@ -313,62 +307,13 @@ void CvCapture_FFMPEG::close() // free last packet if exist if (packet.data) { av_free_packet (&packet); + packet.data = NULL; } init(); } -/* - Used to reopen a video if the slower fallback function for seeking is used. -*/ -bool CvCapture_FFMPEG::reopen() -{ - /*if ( filename==NULL ) return false; - - #if LIBAVFORMAT_BUILD > 4628 - avcodec_close( video_st->codec ); - #else - avcodec_close( &video_st->codec ); - #endif - #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2) - av_close_input_file(ic); - av_open_input_file(&ic, filename, ) - #else - avformat_close_input(&ic); - avformat_open_input(&ic, filename, NULL, NULL); - #endif - - #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 3, 0) - avformat_find_stream_info(ic, NULL); - #else - av_find_stream_info(ic); - #endif - #if LIBAVFORMAT_BUILD > 4628 - AVCodecContext *enc = ic->streams[video_stream]->codec; - #else - AVCodecContext *enc = &ic->streams[video_stream]->codec; - #endif - - #ifdef FF_API_THREAD_INIT - avcodec_thread_init(enc, std::min(get_number_of_cpus(), 16)); - #endif - - AVCodec *codec = avcodec_find_decoder(enc->codec_id); - #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0) - avcodec_open2(enc, codec, NULL); - #else - avcodec_open(enc, codec); - #endif - video_st = ic->streams[video_stream]; - - // reset framenumber to zero - frame_number = 0; - picture_pts=0;*/ - - return true; -} - #ifndef AVSEEK_FLAG_FRAME #define AVSEEK_FLAG_FRAME 0 #endif @@ -456,25 +401,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) if(video_stream >= 0) valid = true; - // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...) - /*err = av_seek_frame(ic, video_stream, 10, 0); - if (err < 0) - { - filename=(char*)malloc(strlen(_filename)+1); - strcpy(filename, _filename); - // reopen videofile to 'seek' back to first frame - reopen(); - } - else - { - // seek seems to work, so we don't need the filename, - // but we still need to seek back to filestart - filename=NULL; - int64_t ts = video_st->first_dts; - int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD; - av_seek_frame(ic, video_stream, ts, flags); - }*/ - exit_func: +exit_func: if( !valid ) close(); @@ -486,30 +413,25 @@ bool CvCapture_FFMPEG::open( const char* _filename ) bool CvCapture_FFMPEG::grabFrame() { bool valid = false; - static bool bFirstTime = true; int got_picture; int count_errs = 0; const int max_number_of_attempts = 64; - if (bFirstTime) - { - bFirstTime = false; - packet.data = NULL; - } - if( !ic || !video_st ) return false; if (packet.data != NULL) { av_free_packet (&packet); + packet.data = NULL; } + + picture_pts = AV_NOPTS_VALUE_; // get the next frame while (!valid) { int ret = av_read_frame(ic, &packet); - if (ret == AVERROR(EAGAIN)) continue; /* else if (ret < 0) break; */ @@ -517,9 +439,10 @@ bool CvCapture_FFMPEG::grabFrame() if( packet.stream_index != video_stream ) { av_free_packet (&packet); + packet.data = NULL; count_errs++; - if (count_errs > max_number_of_attempts) break; else - continue; + if (count_errs > max_number_of_attempts) + break; } // Decode video frame @@ -528,8 +451,10 @@ bool CvCapture_FFMPEG::grabFrame() // Did we get a video frame? if(got_picture) { + picture_pts = picture->best_effort_timestamp; + if( picture_pts == AV_NOPTS_VALUE_ ) + picture_pts = packet.pts != AV_NOPTS_VALUE_ ? packet.pts : packet.dts; frame_number++; - picture_pts = packet.pts; valid = true; } else @@ -538,9 +463,11 @@ bool CvCapture_FFMPEG::grabFrame() if (count_errs > max_number_of_attempts) break; } - } + if( valid && first_frame_number < 0 ) + first_frame_number = dts_to_frame_number(picture_pts); + // return if we have a new picture or not return valid; } @@ -587,8 +514,6 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* rgb_picture.linesize ); - frame_number++; - *data = frame.data; *step = frame.step; *width = frame.width; @@ -598,55 +523,39 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* return true; } -#if defined(__APPLE__) -#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL) -#else -#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE) -#endif double CvCapture_FFMPEG::getProperty( int property_id ) { - // if( !capture || !video_st || !picture->data[0] ) return 0; if( !video_st ) return 0; - // double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate); - //int64_t timestamp; - //timestamp = picture_pts; - switch( property_id ) { case CV_FFMPEG_CAP_PROP_POS_MSEC: - return 1000.0*static_cast(frame_number)/static_cast(get_fps()); - break; + return 1000.0*(double)frame_number/get_fps(); case CV_FFMPEG_CAP_PROP_POS_FRAMES: - return (double)static_cast(frame_number); - break; + return (double)frame_number; case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO: return r2d(ic->streams[video_stream]->time_base); - break; case CV_FFMPEG_CAP_PROP_FRAME_COUNT: - return (double)static_cast(get_total_frames()); - break; + return (double)get_total_frames(); case CV_FFMPEG_CAP_PROP_FRAME_WIDTH: return (double)frame.width; - break; case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT: return (double)frame.height; - break; case CV_FFMPEG_CAP_PROP_FPS: #if LIBAVCODEC_BUILD > 4753 - return av_q2d (video_st->r_frame_rate); + return av_q2d(video_st->r_frame_rate); #else return (double)video_st->codec.frame_rate / (double)video_st->codec.frame_rate_base; #endif - break; - case CV_FFMPEG_CAP_PROP_FOURCC: + case CV_FFMPEG_CAP_PROP_FOURCC: #if LIBAVFORMAT_BUILD > 4628 return (double)video_st->codec->codec_tag; #else return (double)video_st->codec.codec_tag; #endif + default: break; } @@ -655,29 +564,21 @@ double CvCapture_FFMPEG::getProperty( int property_id ) double CvCapture_FFMPEG::r2d(AVRational r) { - if (r.num == 0 || r.den == 0) - { - return 0.0; - } - else - { - return static_cast(r.num) / static_cast(r.den); - } + return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den; } double CvCapture_FFMPEG::get_duration_sec() { - double sec = static_cast(ic->duration) / static_cast(AV_TIME_BASE); + double sec = (double)ic->duration / (double)AV_TIME_BASE; if (sec < eps_zero) { - sec = static_cast(ic->streams[video_stream]->duration) * r2d(ic->streams[video_stream]->time_base); + sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base); } if (sec < eps_zero) { - sec = static_cast(static_cast(ic->streams[video_stream]->duration)) * - r2d(ic->streams[video_stream]->time_base); + sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base); } return sec; @@ -719,58 +620,76 @@ int64_t CvCapture_FFMPEG::get_total_frames() int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts) { double sec = dts_to_sec(dts); - return static_cast(get_fps() * sec); + return (int64_t)(get_fps() * sec + 0.5); } double CvCapture_FFMPEG::dts_to_sec(int64_t dts) { - return static_cast(dts - ic->streams[video_stream]->start_time) * + return (double)(dts - ic->streams[video_stream]->start_time) * r2d(ic->streams[video_stream]->time_base); } void CvCapture_FFMPEG::seek(int64_t _frame_number) { - frame_number = std::min(_frame_number, get_total_frames()); - int64_t dts = dts_to_frame_number(ic->streams[video_stream]->cur_dts); - - if (abs(dts - 2 - frame_number) > 16) + _frame_number = std::min(_frame_number, get_total_frames()); + int delta = 2; + + // if we have not grabbed a single frame before first seek, let's read the first frame + // and get some valuable information during the process + if( first_frame_number < 0 ) + grabFrame(); + + for(;;) { - double sec = static_cast(frame_number) / static_cast(get_fps()); + int64_t _frame_number_temp = std::max(_frame_number-delta, (int64_t)0); + double sec = (double)_frame_number_temp / get_fps(); int64_t time_stamp = ic->streams[video_stream]->start_time; double time_base = r2d(ic->streams[video_stream]->time_base); - time_stamp += static_cast(sec / time_base); - av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); - } - - while(dts - 2 < frame_number) - { - /* cv::Mat imag = read(); */ - if (!grabFrame()) break; - - dts = dts_to_frame_number(ic->streams[video_stream]->cur_dts); + time_stamp += (int64_t)(sec / time_base + 0.5); + av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(ic->streams[video_stream]->codec); + if( _frame_number > 0 ) + { + grabFrame(); + + if( _frame_number > 1 ) + { + frame_number = dts_to_frame_number(picture_pts) - first_frame_number; + //printf("_frame_number = %d, frame_number = %d, delta = %d\n", + // (int)_frame_number, (int)frame_number, delta); + + if( frame_number < 0 || frame_number > _frame_number-1 ) + { + if( _frame_number_temp == 0 || delta >= INT_MAX/4 ) + break; + delta = delta < 16 ? delta*2 : delta*3/2; + continue; + } + while( frame_number < _frame_number-1 ) + { + if(!grabFrame()) + break; + } + frame_number++; + break; + } + else + { + frame_number = 1; + break; + } + } + else + { + frame_number = 0; + break; + } } } void CvCapture_FFMPEG::seek(double sec) { - seek(static_cast(sec * get_fps())); -} - -// this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result! -bool CvCapture_FFMPEG::slowSeek( int framenumber ) -{ - if ( framenumber>picture_pts ) - { - while ( picture_ptscodec_type = AVMEDIA_TYPE_VIDEO; /* put sample parameters */ - unsigned long long lbit_rate = static_cast(bitrate); + int64_t lbit_rate = (int64_t)bitrate; lbit_rate += (bitrate / 2); - lbit_rate = std::min(lbit_rate, static_cast(std::numeric_limits::max())); + lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX); c->bit_rate = lbit_rate; // took advice from @@ -1466,11 +1385,11 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, return false; } - unsigned long long lbit_rate = static_cast(c->bit_rate); + int64_t lbit_rate = (int64_t)c->bit_rate; lbit_rate += (bitrate / 2); - lbit_rate = std::min(lbit_rate, static_cast(std::numeric_limits::max())); - c->bit_rate_tolerance = static_cast(lbit_rate); - c->bit_rate = static_cast(lbit_rate); + lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX); + c->bit_rate_tolerance = (int)lbit_rate; + c->bit_rate = (int)lbit_rate; /* open the codec */ if ((err= diff --git a/modules/highgui/test/test_drawing.cpp b/modules/highgui/test/test_drawing.cpp index a4a7269ba..4b45a7b23 100644 --- a/modules/highgui/test/test_drawing.cpp +++ b/modules/highgui/test/test_drawing.cpp @@ -407,8 +407,8 @@ int CV_DrawingTest_C::checkLineIterator( Mat& _img ) } #ifdef HAVE_JPEG -TEST(Highgui_Drawing_CPP, regression) { CV_DrawingTest_CPP test; test.safe_run(); } -TEST(Highgui_Drawing_C, regression) { CV_DrawingTest_C test; test.safe_run(); } +TEST(Highgui_Drawing, cpp_regression) { CV_DrawingTest_CPP test; test.safe_run(); } +TEST(Highgui_Drawing, c_regression) { CV_DrawingTest_C test; test.safe_run(); } #endif class CV_FillConvexPolyTest : public cvtest::BaseTest @@ -443,4 +443,4 @@ protected: } }; -TEST(Highgui_Drawing_FillConvexPoly, clipping) { CV_FillConvexPolyTest test; test.safe_run(); } +TEST(Highgui_Drawing, fillconvexpoly_clipping) { CV_FillConvexPolyTest test; test.safe_run(); } diff --git a/modules/highgui/test/test_ffmpeg.cpp b/modules/highgui/test/test_ffmpeg.cpp index e2eed5ee8..6de296066 100644 --- a/modules/highgui/test/test_ffmpeg.cpp +++ b/modules/highgui/test/test_ffmpeg.cpp @@ -71,19 +71,19 @@ public: if( tag != MKTAG('H', '2', '6', '3') && tag != MKTAG('H', '2', '6', '1') && - tag != MKTAG('D', 'I', 'V', 'X') && + //tag != MKTAG('D', 'I', 'V', 'X') && tag != MKTAG('D', 'X', '5', '0') && tag != MKTAG('X', 'V', 'I', 'D') && tag != MKTAG('m', 'p', '4', 'v') && - tag != MKTAG('D', 'I', 'V', '3') && - tag != MKTAG('W', 'M', 'V', '1') && - tag != MKTAG('W', 'M', 'V', '2') && + //tag != MKTAG('D', 'I', 'V', '3') && + //tag != MKTAG('W', 'M', 'V', '1') && + //tag != MKTAG('W', 'M', 'V', '2') && tag != MKTAG('M', 'P', 'E', 'G') && tag != MKTAG('M', 'J', 'P', 'G') && - tag != MKTAG('j', 'p', 'e', 'g') && + //tag != MKTAG('j', 'p', 'e', 'g') && tag != 0 && tag != MKTAG('I', '4', '2', '0') && - tag != MKTAG('Y', 'U', 'Y', '2') && + //tag != MKTAG('Y', 'U', 'Y', '2') && tag != MKTAG('F', 'L', 'V', '1') ) continue; @@ -142,6 +142,6 @@ public: } }; -TEST(Highgui_FFmpeg_WriteBigVideo, regression) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); } +TEST(Highgui_Video, ffmpeg_writebig) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); } #endif diff --git a/modules/highgui/test/test_grfmt.cpp b/modules/highgui/test/test_grfmt.cpp index c9cc5a68d..5923b628e 100644 --- a/modules/highgui/test/test_grfmt.cpp +++ b/modules/highgui/test/test_grfmt.cpp @@ -202,12 +202,12 @@ public: }; #ifdef HAVE_PNG -TEST(Highgui_Grfmt_WriteBigImage, regression) { CV_GrfmtWriteBigImageTest test; test.safe_run(); } +TEST(Highgui_Image, write_big) { CV_GrfmtWriteBigImageTest test; test.safe_run(); } #endif #if defined(HAVE_PNG) && defined(HAVE_TIFF) && defined(HAVE_JPEG) -TEST(Highgui_Grfmt_WriteSequenceImage, regression) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); } +TEST(Highgui_Image, write_imageseq) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); } #endif -TEST(GrfmtReadBMPRLE8, regression) { CV_GrfmtReadBMPRLE8Test test; test.safe_run(); } +TEST(Highgui_Image, read_bmp_rle8) { CV_GrfmtReadBMPRLE8Test test; test.safe_run(); } diff --git a/modules/highgui/test/test_positioning.cpp b/modules/highgui/test/test_positioning.cpp index c77ee4f63..49b771e4e 100644 --- a/modules/highgui/test/test_positioning.cpp +++ b/modules/highgui/test/test_positioning.cpp @@ -47,11 +47,11 @@ using namespace cv; using namespace std; -enum NAVIGATION_METHOD {PROGRESSIVE, RANDOM}; - class CV_VideoPositioningTest: public cvtest::BaseTest { public: + enum {PROGRESSIVE, RANDOM}; + CV_VideoPositioningTest(); ~CV_VideoPositioningTest(); virtual void run(int) = 0; @@ -122,14 +122,17 @@ void CV_VideoPositioningTest::run_test(int method) ts->printf(cvtest::TS::LOG, "\n\nSource files directory: %s\n", (src_dir+"video/").c_str()); - const string ext[] = {"avi", "mp4", "wmv"}; + const string ext[] = {"avi", "mov", "mp4", "mpg"}; - size_t n = sizeof(ext)/sizeof(ext[0]); + int n = (int)(sizeof(ext)/sizeof(ext[0])); int failed_videos = 0; - for (size_t i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { + // skip random positioning test in plain mpegs + if( method == RANDOM && ext[i] == "mpg" ) + continue; string file_path = src_dir + "video/big_buck_bunny." + ext[i]; printf("\nReading video file in %s...\n", file_path.c_str()); @@ -186,20 +189,17 @@ void CV_VideoPositioningTest::run_test(int method) ts->printf(cvtest::TS::LOG, "Required pos: %d\nReturned pos: %d\n", idx.at(j), val); ts->printf(cvtest::TS::LOG, "Error: required and returned positions are not matched.\n"); ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); - if (!flag) flag = !flag; + flag = true; } - if (flag) failed_iterations++; + if (flag) + { + failed_iterations++; + failed_videos++; + break; + } } - ts->printf(cvtest::TS::LOG, "\nSuccessfull iterations: %d (%d%%)\n", idx.size()-failed_iterations, 100*(idx.size()-failed_iterations)/idx.size()); - ts->printf(cvtest::TS::LOG, "Failed iterations: %d (%d%%)\n", failed_iterations, 100*failed_iterations/idx.size()); - - if (failed_frames||failed_positions) - { - ts->printf(cvtest::TS::LOG, "\nFAILED\n----------\n"); failed_videos++; - } - cvReleaseCapture(&cap); } @@ -218,6 +218,6 @@ void CV_VideoRandomPositioningTest::run(int) } #if BUILD_WITH_VIDEO_INPUT_SUPPORT -TEST (HighguiPositioning, progressive) { CV_VideoProgressivePositioningTest test; test.safe_run(); } -TEST (HighguiPositioning, random) { CV_VideoRandomPositioningTest test; test.safe_run(); } +TEST (Highgui_Video, seek_progressive) { CV_VideoProgressivePositioningTest test; test.safe_run(); } +TEST (Highgui_Video, seek_random) { CV_VideoRandomPositioningTest test; test.safe_run(); } #endif \ No newline at end of file diff --git a/modules/highgui/test/test_video_io.cpp b/modules/highgui/test/test_video_io.cpp index d224fdc7b..46fe8d2c5 100644 --- a/modules/highgui/test/test_video_io.cpp +++ b/modules/highgui/test/test_video_io.cpp @@ -56,10 +56,14 @@ string fourccToString(int fourcc) const VideoFormat g_specific_fmt_list[] = { - VideoFormat("avi", CV_FOURCC('m', 'p', 'e', 'g')), + VideoFormat("avi", CV_FOURCC('X', 'V', 'I', 'D')), + VideoFormat("avi", CV_FOURCC('M', 'P', 'E', 'G')), VideoFormat("avi", CV_FOURCC('M', 'J', 'P', 'G')), VideoFormat("avi", CV_FOURCC('I', 'Y', 'U', 'V')), VideoFormat("mkv", CV_FOURCC('X', 'V', 'I', 'D')), + VideoFormat("mkv", CV_FOURCC('M', 'P', 'E', 'G')), + VideoFormat("mkv", CV_FOURCC('M', 'J', 'P', 'G')), + VideoFormat("mov", CV_FOURCC('m', 'p', '4', 'v')), VideoFormat() }; @@ -516,7 +520,7 @@ TEST(Highgui_Image, regression) { CV_ImageTest test; test.safe_run(); } #if BUILD_WITH_VIDEO_INPUT_SUPPORT && BUILD_WITH_VIDEO_OUTPUT_SUPPORT TEST(Highgui_Video, regression) { CV_VideoTest test; test.safe_run(); } -TEST(Highgui_SpecificVideoFile, regression) { CV_SpecificVideoTest test; test.safe_run(); } +TEST(Highgui_Video, write_read) { CV_SpecificVideoTest test; test.safe_run(); } #endif -TEST(Highgui_SpecificImage, regression) { CV_SpecificImageTest test; test.safe_run(); } +TEST(Highgui_Image, write_read) { CV_SpecificImageTest test; test.safe_run(); } diff --git a/modules/highgui/test/test_video_pos.cpp b/modules/highgui/test/test_video_pos.cpp index b4025bb85..7efaee419 100755 --- a/modules/highgui/test/test_video_pos.cpp +++ b/modules/highgui/test/test_video_pos.cpp @@ -94,7 +94,8 @@ public: if( fmt.empty() ) break; string filename = getFilename(fmt); - ts->printf(ts->LOG, "\n\nFile: %s\n", filename.c_str()); + ts->printf(ts->LOG, "\nFile: %s\n", filename.c_str()); + if( !CreateTestVideo(fmt, n_frames) ) { ts->printf(ts->LOG, "\nError: cannot create video file"); @@ -133,7 +134,21 @@ public: return; } + int idx1 = (int)cap.get(CV_CAP_PROP_POS_FRAMES); + Mat img; cap >> img; + Mat img0 = drawFrame(idx); + + if( idx != idx1 ) + { + ts->printf(ts->LOG, "\nError: the current position (%d) after seek is different from specified (%d)\n", + idx1, idx); + ts->printf(ts->LOG, "Saving both frames ...\n"); + ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT); + imwrite("opencv_test_highgui_postest_actual.png", img); + imwrite("opencv_test_highgui_postest_expected.png", img0); + return; + } if (img.empty()) { @@ -142,10 +157,9 @@ public: return; } - Mat img0 = drawFrame(idx); double err = PSNR(img, img0); - if( err < 20 ) + if( err < 25 ) { ts->printf(ts->LOG, "The frame read after positioning to %d is incorrect (PSNR=%g)\n", idx, err); ts->printf(ts->LOG, "Saving both frames ...\n"); @@ -162,5 +176,5 @@ public: }; #if BUILD_WITH_VIDEO_INPUT_SUPPORT && BUILD_WITH_VIDEO_OUTPUT_SUPPORT -TEST(Highgui_Positioning, regression) { CV_PositioningTest test; test.safe_run(); } +TEST(Highgui_Video, seek_random_synthetic) { CV_PositioningTest test; test.safe_run(); } #endif