Path: blob/master/modules/videoio/src/cap_ffmpeg_impl.hpp
16339 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., all rights reserved.14// Third party copyrights are property of their respective owners.15//16// Redistribution and use in source and binary forms, with or without modification,17// are permitted provided that the following conditions are met:18//19// * Redistribution's of source code must retain the above copyright notice,20// this list of conditions and the following disclaimer.21//22// * Redistribution's in binary form must reproduce the above copyright notice,23// this list of conditions and the following disclaimer in the documentation24// and/or other materials provided with the distribution.25//26// * The name of the copyright holders may not be used to endorse or promote products27// derived from this software without specific prior written permission.28//29// This software is provided by the copyright holders and contributors "as is" and30// any express or implied warranties, including, but not limited to, the implied31// warranties of merchantability and fitness for a particular purpose are disclaimed.32// In no event shall the Intel Corporation or contributors be liable for any direct,33// indirect, incidental, special, exemplary, or consequential damages34// (including, but not limited to, procurement of substitute goods or services;35// loss of use, data, or profits; or business interruption) however caused36// and on any theory of liability, whether in contract, strict liability,37// or tort (including negligence or otherwise) arising in any way out of38// the use of this software, even if advised of the possibility of such damage.39//40//M*/4142#include "cap_ffmpeg_api.hpp"43#if !(defined(_WIN32) || defined(WINCE))44# include <pthread.h>45#endif46#include <assert.h>47#include <algorithm>48#include <limits>4950#define OPENCV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))51#define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )5253#if defined _MSC_VER && _MSC_VER >= 120054#pragma warning( disable: 4244 4510 4610 )55#endif5657#ifdef __GNUC__58# pragma GCC diagnostic ignored "-Wdeprecated-declarations"59#endif6061#ifndef CV_UNUSED // Required for standalone compilation mode (OpenCV defines this in base.hpp)62#define CV_UNUSED(name) (void)name63#endif6465#ifdef __cplusplus66extern "C" {67#endif6869#include "ffmpeg_codecs.hpp"7071#include <libavutil/mathematics.h>7273#if LIBAVUTIL_BUILD > CALC_FFMPEG_VERSION(51,11,0)74#include <libavutil/opt.h>75#endif7677#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \78? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))79#include <libavutil/imgutils.h>80#endif8182#include <libavcodec/avcodec.h>83#include <libswscale/swscale.h>8485#ifdef __cplusplus86}87#endif8889#if defined _MSC_VER && _MSC_VER >= 120090#pragma warning( default: 4244 4510 4610 )91#endif9293#ifdef NDEBUG94#define CV_WARN(message)95#else96#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)97#endif9899#if defined _WIN32100#include <windows.h>101#if defined _MSC_VER && _MSC_VER < 1900102struct timespec103{104time_t tv_sec;105long tv_nsec;106};107#endif108#elif defined __linux__ || defined __APPLE__ || defined __HAIKU__109#include <unistd.h>110#include <stdio.h>111#include <sys/types.h>112#include <sys/time.h>113#if defined __APPLE__114#include <sys/sysctl.h>115#include <mach/clock.h>116#include <mach/mach.h>117#endif118#endif119120#ifndef MIN121#define MIN(a, b) ((a) < (b) ? (a) : (b))122#endif123124#if defined(__APPLE__)125#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)126#else127#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)128#endif129130#ifndef AVERROR_EOF131#define AVERROR_EOF (-MKTAG( 'E','O','F',' '))132#endif133134#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54,25,0)135# define CV_CODEC_ID AVCodecID136# define CV_CODEC(name) AV_##name137#else138# define CV_CODEC_ID CodecID139# define CV_CODEC(name) name140#endif141142#if LIBAVUTIL_BUILD < (LIBAVUTIL_VERSION_MICRO >= 100 \143? CALC_FFMPEG_VERSION(51, 74, 100) : CALC_FFMPEG_VERSION(51, 42, 0))144#define AVPixelFormat PixelFormat145#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24146#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24147#define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8148#define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P149#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P150#define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P151#define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P152#define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE153#define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE154#endif155156#ifndef PKT_FLAG_KEY157#define PKT_FLAG_KEY AV_PKT_FLAG_KEY158#endif159160#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \161? CALC_FFMPEG_VERSION(52, 38, 100) : CALC_FFMPEG_VERSION(52, 13, 0))162#define USE_AV_FRAME_GET_BUFFER 1163#else164#define USE_AV_FRAME_GET_BUFFER 0165#ifndef AV_NUM_DATA_POINTERS // required for 0.7.x/0.8.x ffmpeg releases166#define AV_NUM_DATA_POINTERS 4167#endif168#endif169170171#ifndef USE_AV_INTERRUPT_CALLBACK172#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 21, 0)173#define USE_AV_INTERRUPT_CALLBACK 1174#else175#define USE_AV_INTERRUPT_CALLBACK 0176#endif177#endif178179#if USE_AV_INTERRUPT_CALLBACK180#define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 30000181#define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 30000182183#ifdef _WIN32184// http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows185186static187inline LARGE_INTEGER get_filetime_offset()188{189SYSTEMTIME s;190FILETIME f;191LARGE_INTEGER t;192193s.wYear = 1970;194s.wMonth = 1;195s.wDay = 1;196s.wHour = 0;197s.wMinute = 0;198s.wSecond = 0;199s.wMilliseconds = 0;200SystemTimeToFileTime(&s, &f);201t.QuadPart = f.dwHighDateTime;202t.QuadPart <<= 32;203t.QuadPart |= f.dwLowDateTime;204return t;205}206207static208inline void get_monotonic_time(timespec *tv)209{210LARGE_INTEGER t;211FILETIME f;212double microseconds;213static LARGE_INTEGER offset;214static double frequencyToMicroseconds;215static int initialized = 0;216static BOOL usePerformanceCounter = 0;217218if (!initialized)219{220LARGE_INTEGER performanceFrequency;221initialized = 1;222usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);223if (usePerformanceCounter)224{225QueryPerformanceCounter(&offset);226frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;227}228else229{230offset = get_filetime_offset();231frequencyToMicroseconds = 10.;232}233}234235if (usePerformanceCounter)236{237QueryPerformanceCounter(&t);238} else {239GetSystemTimeAsFileTime(&f);240t.QuadPart = f.dwHighDateTime;241t.QuadPart <<= 32;242t.QuadPart |= f.dwLowDateTime;243}244245t.QuadPart -= offset.QuadPart;246microseconds = (double)t.QuadPart / frequencyToMicroseconds;247t.QuadPart = microseconds;248tv->tv_sec = t.QuadPart / 1000000;249tv->tv_nsec = (t.QuadPart % 1000000) * 1000;250}251#else252static253inline void get_monotonic_time(timespec *time)254{255#if defined(__APPLE__) && defined(__MACH__)256clock_serv_t cclock;257mach_timespec_t mts;258host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);259clock_get_time(cclock, &mts);260mach_port_deallocate(mach_task_self(), cclock);261time->tv_sec = mts.tv_sec;262time->tv_nsec = mts.tv_nsec;263#else264clock_gettime(CLOCK_MONOTONIC, time);265#endif266}267#endif268269static270inline timespec get_monotonic_time_diff(timespec start, timespec end)271{272timespec temp;273if (end.tv_nsec - start.tv_nsec < 0)274{275temp.tv_sec = end.tv_sec - start.tv_sec - 1;276temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;277}278else279{280temp.tv_sec = end.tv_sec - start.tv_sec;281temp.tv_nsec = end.tv_nsec - start.tv_nsec;282}283return temp;284}285286static287inline double get_monotonic_time_diff_ms(timespec time1, timespec time2)288{289timespec delta = get_monotonic_time_diff(time1, time2);290double milliseconds = delta.tv_sec * 1000 + (double)delta.tv_nsec / 1000000.0;291292return milliseconds;293}294#endif // USE_AV_INTERRUPT_CALLBACK295296static int get_number_of_cpus(void)297{298#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0)299return 1;300#elif defined _WIN32301SYSTEM_INFO sysinfo;302GetSystemInfo( &sysinfo );303304return (int)sysinfo.dwNumberOfProcessors;305#elif defined __linux__ || defined __HAIKU__306return (int)sysconf( _SC_NPROCESSORS_ONLN );307#elif defined __APPLE__308int numCPU=0;309int mib[4];310size_t len = sizeof(numCPU);311312// set the mib for hw.ncpu313mib[0] = CTL_HW;314mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;315316// get the number of CPUs from the system317sysctl(mib, 2, &numCPU, &len, NULL, 0);318319if( numCPU < 1 )320{321mib[1] = HW_NCPU;322sysctl( mib, 2, &numCPU, &len, NULL, 0 );323324if( numCPU < 1 )325numCPU = 1;326}327328return (int)numCPU;329#else330return 1;331#endif332}333334335struct Image_FFMPEG336{337unsigned char* data;338int step;339int width;340int height;341int cn;342};343344345#if USE_AV_INTERRUPT_CALLBACK346struct AVInterruptCallbackMetadata347{348timespec value;349unsigned int timeout_after_ms;350int timeout;351};352353// https://github.com/opencv/opencv/pull/12693#issuecomment-426236731354static355inline const char* _opencv_avcodec_get_name(AVCodecID id)356{357#if LIBAVCODEC_VERSION_MICRO >= 100 \358&& LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(53, 47, 100)359return avcodec_get_name(id);360#else361const AVCodecDescriptor *cd;362AVCodec *codec;363364if (id == AV_CODEC_ID_NONE)365{366return "none";367}368cd = avcodec_descriptor_get(id);369if (cd)370{371return cd->name;372}373codec = avcodec_find_decoder(id);374if (codec)375{376return codec->name;377}378codec = avcodec_find_encoder(id);379if (codec)380{381return codec->name;382}383384return "unknown_codec";385#endif386}387388static389inline void _opencv_ffmpeg_free(void** ptr)390{391if(*ptr) free(*ptr);392*ptr = 0;393}394395static396inline int _opencv_ffmpeg_interrupt_callback(void *ptr)397{398AVInterruptCallbackMetadata* metadata = (AVInterruptCallbackMetadata*)ptr;399assert(metadata);400401if (metadata->timeout_after_ms == 0)402{403return 0; // timeout is disabled404}405406timespec now;407get_monotonic_time(&now);408409metadata->timeout = get_monotonic_time_diff_ms(metadata->value, now) > metadata->timeout_after_ms;410411return metadata->timeout ? -1 : 0;412}413#endif414415static416inline void _opencv_ffmpeg_av_packet_unref(AVPacket *pkt)417{418#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \419? CALC_FFMPEG_VERSION(55, 25, 100) : CALC_FFMPEG_VERSION(55, 16, 0))420av_packet_unref(pkt);421#else422av_free_packet(pkt);423#endif424};425426static427inline void _opencv_ffmpeg_av_image_fill_arrays(void *frame, uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height)428{429#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \430? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))431av_image_fill_arrays(((AVFrame*)frame)->data, ((AVFrame*)frame)->linesize, ptr, pix_fmt, width, height, 1);432#else433avpicture_fill((AVPicture*)frame, ptr, pix_fmt, width, height);434#endif435};436437static438inline int _opencv_ffmpeg_av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height)439{440#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \441? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))442return av_image_get_buffer_size(pix_fmt, width, height, 1);443#else444return avpicture_get_size(pix_fmt, width, height);445#endif446};447448static AVRational _opencv_ffmpeg_get_sample_aspect_ratio(AVStream *stream)449{450#if LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(54, 5, 100)451return av_guess_sample_aspect_ratio(NULL, stream, NULL);452#else453AVRational undef = {0, 1};454455// stream456AVRational ratio = stream ? stream->sample_aspect_ratio : undef;457av_reduce(&ratio.num, &ratio.den, ratio.num, ratio.den, INT_MAX);458if (ratio.num > 0 && ratio.den > 0)459return ratio;460461// codec462ratio = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef;463av_reduce(&ratio.num, &ratio.den, ratio.num, ratio.den, INT_MAX);464if (ratio.num > 0 && ratio.den > 0)465return ratio;466467return undef;468#endif469}470471472struct CvCapture_FFMPEG473{474bool open( const char* filename );475void close();476477double getProperty(int) const;478bool setProperty(int, double);479bool grabFrame();480bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn);481482void init();483484void seek(int64_t frame_number);485void seek(double sec);486bool slowSeek( int framenumber );487488int64_t get_total_frames() const;489double get_duration_sec() const;490double get_fps() const;491int get_bitrate() const;492493double r2d(AVRational r) const;494int64_t dts_to_frame_number(int64_t dts);495double dts_to_sec(int64_t dts);496497AVFormatContext * ic;498AVCodec * avcodec;499int video_stream;500AVStream * video_st;501AVFrame * picture;502AVFrame rgb_picture;503int64_t picture_pts;504505AVPacket packet;506Image_FFMPEG frame;507struct SwsContext *img_convert_ctx;508509int64_t frame_number, first_frame_number;510511double eps_zero;512/*513'filename' contains the filename of the videosource,514'filename==NULL' indicates that ffmpeg's seek support works515for the particular file.516'filename!=NULL' indicates that the slow fallback function is used for seeking,517and so the filename is needed to reopen the file on backward seeking.518*/519char * filename;520521#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)522AVDictionary *dict;523#endif524#if USE_AV_INTERRUPT_CALLBACK525AVInterruptCallbackMetadata interrupt_metadata;526#endif527};528529void CvCapture_FFMPEG::init()530{531ic = 0;532video_stream = -1;533video_st = 0;534picture = 0;535picture_pts = AV_NOPTS_VALUE_;536first_frame_number = -1;537memset( &rgb_picture, 0, sizeof(rgb_picture) );538memset( &frame, 0, sizeof(frame) );539filename = 0;540memset(&packet, 0, sizeof(packet));541av_init_packet(&packet);542img_convert_ctx = 0;543544avcodec = 0;545frame_number = 0;546eps_zero = 0.000025;547548#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)549dict = NULL;550#endif551}552553554void CvCapture_FFMPEG::close()555{556if( img_convert_ctx )557{558sws_freeContext(img_convert_ctx);559img_convert_ctx = 0;560}561562if( picture )563{564#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \565? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))566av_frame_free(&picture);567#elif LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \568? CALC_FFMPEG_VERSION(54, 59, 100) : CALC_FFMPEG_VERSION(54, 28, 0))569avcodec_free_frame(&picture);570#else571av_free(picture);572#endif573}574575if( video_st )576{577#if LIBAVFORMAT_BUILD > 4628578avcodec_close( video_st->codec );579580#else581avcodec_close( &(video_st->codec) );582583#endif584video_st = NULL;585}586587if( ic )588{589#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)590av_close_input_file(ic);591#else592avformat_close_input(&ic);593#endif594595ic = NULL;596}597598#if USE_AV_FRAME_GET_BUFFER599av_frame_unref(&rgb_picture);600#else601if( rgb_picture.data[0] )602{603free( rgb_picture.data[0] );604rgb_picture.data[0] = 0;605}606#endif607608// free last packet if exist609if (packet.data) {610_opencv_ffmpeg_av_packet_unref (&packet);611packet.data = NULL;612}613614#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)615if (dict != NULL)616av_dict_free(&dict);617#endif618619init();620}621622623#ifndef AVSEEK_FLAG_FRAME624#define AVSEEK_FLAG_FRAME 0625#endif626#ifndef AVSEEK_FLAG_ANY627#define AVSEEK_FLAG_ANY 1628#endif629630class ImplMutex631{632public:633ImplMutex() { init(); }634~ImplMutex() { destroy(); }635636void init();637void destroy();638639void lock();640bool trylock();641void unlock();642643struct Impl;644protected:645Impl* impl;646647private:648ImplMutex(const ImplMutex&);649ImplMutex& operator = (const ImplMutex& m);650};651652#if defined _WIN32 || defined WINCE653654struct ImplMutex::Impl655{656void init()657{658#if (_WIN32_WINNT >= 0x0600)659::InitializeCriticalSectionEx(&cs, 1000, 0);660#else661::InitializeCriticalSection(&cs);662#endif663refcount = 1;664}665void destroy() { DeleteCriticalSection(&cs); }666667void lock() { EnterCriticalSection(&cs); }668bool trylock() { return TryEnterCriticalSection(&cs) != 0; }669void unlock() { LeaveCriticalSection(&cs); }670671CRITICAL_SECTION cs;672int refcount;673};674675#ifndef __GNUC__676static int _interlockedExchangeAdd(int* addr, int delta)677{678#if defined _MSC_VER && _MSC_VER >= 1500679return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);680#else681return (int)InterlockedExchangeAdd((long volatile*)addr, delta);682#endif683}684#endif // __GNUC__685686#elif defined __APPLE__687688#include <libkern/OSAtomic.h>689690struct ImplMutex::Impl691{692void init() { sl = OS_SPINLOCK_INIT; refcount = 1; }693void destroy() { }694695void lock() { OSSpinLockLock(&sl); }696bool trylock() { return OSSpinLockTry(&sl); }697void unlock() { OSSpinLockUnlock(&sl); }698699OSSpinLock sl;700int refcount;701};702703#elif defined __linux__ && !defined __ANDROID__704705struct ImplMutex::Impl706{707void init() { pthread_spin_init(&sl, 0); refcount = 1; }708void destroy() { pthread_spin_destroy(&sl); }709710void lock() { pthread_spin_lock(&sl); }711bool trylock() { return pthread_spin_trylock(&sl) == 0; }712void unlock() { pthread_spin_unlock(&sl); }713714pthread_spinlock_t sl;715int refcount;716};717718#else719720struct ImplMutex::Impl721{722void init() { pthread_mutex_init(&sl, 0); refcount = 1; }723void destroy() { pthread_mutex_destroy(&sl); }724725void lock() { pthread_mutex_lock(&sl); }726bool trylock() { return pthread_mutex_trylock(&sl) == 0; }727void unlock() { pthread_mutex_unlock(&sl); }728729pthread_mutex_t sl;730int refcount;731};732733#endif734735void ImplMutex::init()736{737impl = new Impl();738impl->init();739}740void ImplMutex::destroy()741{742impl->destroy();743delete(impl);744impl = NULL;745}746void ImplMutex::lock() { impl->lock(); }747void ImplMutex::unlock() { impl->unlock(); }748bool ImplMutex::trylock() { return impl->trylock(); }749750static int LockCallBack(void **mutex, AVLockOp op)751{752ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex);753switch (op)754{755case AV_LOCK_CREATE:756localMutex = reinterpret_cast<ImplMutex*>(malloc(sizeof(ImplMutex)));757if (!localMutex)758return 1;759localMutex->init();760*mutex = localMutex;761if (!*mutex)762return 1;763break;764765case AV_LOCK_OBTAIN:766localMutex->lock();767break;768769case AV_LOCK_RELEASE:770localMutex->unlock();771break;772773case AV_LOCK_DESTROY:774localMutex->destroy();775free(localMutex);776localMutex = NULL;777*mutex = NULL;778break;779}780return 0;781}782783static ImplMutex _mutex;784static bool _initialized = false;785786class AutoLock787{788public:789AutoLock(ImplMutex& m) : mutex(&m) { mutex->lock(); }790~AutoLock() { mutex->unlock(); }791protected:792ImplMutex* mutex;793private:794AutoLock(const AutoLock&); // disabled795AutoLock& operator = (const AutoLock&); // disabled796};797798static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs)799{800static bool skip_header = false;801static int prev_level = -1;802CV_UNUSED(ptr);803if (!skip_header || level != prev_level) printf("[OPENCV:FFMPEG:%02d] ", level);804vprintf(fmt, vargs);805size_t fmt_len = strlen(fmt);806skip_header = fmt_len > 0 && fmt[fmt_len - 1] != '\n';807prev_level = level;808}809810class InternalFFMpegRegister811{812public:813InternalFFMpegRegister()814{815AutoLock lock(_mutex);816if (!_initialized)817{818#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)819avformat_network_init();820#endif821822/* register all codecs, demux and protocols */823av_register_all();824825/* register a callback function for synchronization */826av_lockmgr_register(&LockCallBack);827828#ifndef NO_GETENV829char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");830if (debug_option != NULL)831{832av_log_set_level(AV_LOG_VERBOSE);833av_log_set_callback(ffmpeg_log_callback);834}835else836#endif837{838av_log_set_level(AV_LOG_ERROR);839}840841_initialized = true;842}843}844845~InternalFFMpegRegister()846{847_initialized = false;848av_lockmgr_register(NULL);849}850};851852static InternalFFMpegRegister _init;853854bool CvCapture_FFMPEG::open( const char* _filename )855{856AutoLock lock(_mutex);857unsigned i;858bool valid = false;859860close();861862#if USE_AV_INTERRUPT_CALLBACK863/* interrupt callback */864interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;865get_monotonic_time(&interrupt_metadata.value);866867ic = avformat_alloc_context();868ic->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;869ic->interrupt_callback.opaque = &interrupt_metadata;870#endif871872#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)873#ifndef NO_GETENV874char* options = getenv("OPENCV_FFMPEG_CAPTURE_OPTIONS");875if(options == NULL)876{877av_dict_set(&dict, "rtsp_transport", "tcp", 0);878}879else880{881#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 ? CALC_FFMPEG_VERSION(52, 17, 100) : CALC_FFMPEG_VERSION(52, 7, 0))882av_dict_parse_string(&dict, options, ";", "|", 0);883#else884av_dict_set(&dict, "rtsp_transport", "tcp", 0);885#endif886}887#else888av_dict_set(&dict, "rtsp_transport", "tcp", 0);889#endif890int err = avformat_open_input(&ic, _filename, NULL, &dict);891#else892int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);893#endif894895if (err < 0)896{897CV_WARN("Error opening file");898CV_WARN(_filename);899goto exit_func;900}901err =902#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)903avformat_find_stream_info(ic, NULL);904#else905av_find_stream_info(ic);906#endif907if (err < 0)908{909CV_WARN("Could not find codec parameters");910goto exit_func;911}912for(i = 0; i < ic->nb_streams; i++)913{914#if LIBAVFORMAT_BUILD > 4628915AVCodecContext *enc = ic->streams[i]->codec;916#else917AVCodecContext *enc = &ic->streams[i]->codec;918#endif919920//#ifdef FF_API_THREAD_INIT921// avcodec_thread_init(enc, get_number_of_cpus());922//#else923enc->thread_count = get_number_of_cpus();924//#endif925926#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)927#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO928#endif929930if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0)931{932// backup encoder' width/height933int enc_width = enc->width;934int enc_height = enc->height;935936AVCodec *codec;937if(av_dict_get(dict, "video_codec", NULL, 0) == NULL) {938codec = avcodec_find_decoder(enc->codec_id);939} else {940codec = avcodec_find_decoder_by_name(av_dict_get(dict, "video_codec", NULL, 0)->value);941}942if (!codec ||943#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)944avcodec_open2(enc, codec, NULL)945#else946avcodec_open(enc, codec)947#endif948< 0)949goto exit_func;950951// checking width/height (since decoder can sometimes alter it, eg. vp6f)952if (enc_width && (enc->width != enc_width)) { enc->width = enc_width; }953if (enc_height && (enc->height != enc_height)) { enc->height = enc_height; }954955video_stream = i;956video_st = ic->streams[i];957#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \958? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))959picture = av_frame_alloc();960#else961picture = avcodec_alloc_frame();962#endif963964frame.width = enc->width;965frame.height = enc->height;966frame.cn = 3;967frame.step = 0;968frame.data = NULL;969break;970}971}972973if(video_stream >= 0) valid = true;974975exit_func:976977#if USE_AV_INTERRUPT_CALLBACK978// deactivate interrupt callback979interrupt_metadata.timeout_after_ms = 0;980#endif981982if( !valid )983close();984985return valid;986}987988989bool CvCapture_FFMPEG::grabFrame()990{991bool valid = false;992int got_picture;993994int count_errs = 0;995const int max_number_of_attempts = 1 << 9;996997if( !ic || !video_st ) return false;998999if( ic->streams[video_stream]->nb_frames > 0 &&1000frame_number > ic->streams[video_stream]->nb_frames )1001return false;10021003picture_pts = AV_NOPTS_VALUE_;10041005#if USE_AV_INTERRUPT_CALLBACK1006// activate interrupt callback1007get_monotonic_time(&interrupt_metadata.value);1008interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;1009#endif10101011// get the next frame1012while (!valid)1013{10141015_opencv_ffmpeg_av_packet_unref (&packet);10161017#if USE_AV_INTERRUPT_CALLBACK1018if (interrupt_metadata.timeout)1019{1020valid = false;1021break;1022}1023#endif10241025int ret = av_read_frame(ic, &packet);1026if (ret == AVERROR(EAGAIN)) continue;10271028/* else if (ret < 0) break; */10291030if( packet.stream_index != video_stream )1031{1032_opencv_ffmpeg_av_packet_unref (&packet);1033count_errs++;1034if (count_errs > max_number_of_attempts)1035break;1036continue;1037}10381039// Decode video frame1040#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)1041avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);1042#elif LIBAVFORMAT_BUILD > 46281043avcodec_decode_video(video_st->codec,1044picture, &got_picture,1045packet.data, packet.size);1046#else1047avcodec_decode_video(&video_st->codec,1048picture, &got_picture,1049packet.data, packet.size);1050#endif10511052// Did we get a video frame?1053if(got_picture)1054{1055//picture_pts = picture->best_effort_timestamp;1056if( picture_pts == AV_NOPTS_VALUE_ )1057picture_pts = picture->pkt_pts != AV_NOPTS_VALUE_ && picture->pkt_pts != 0 ? picture->pkt_pts : picture->pkt_dts;10581059frame_number++;1060valid = true;1061}1062else1063{1064count_errs++;1065if (count_errs > max_number_of_attempts)1066break;1067}1068}10691070if( valid && first_frame_number < 0 )1071first_frame_number = dts_to_frame_number(picture_pts);10721073#if USE_AV_INTERRUPT_CALLBACK1074// deactivate interrupt callback1075interrupt_metadata.timeout_after_ms = 0;1076#endif10771078// return if we have a new picture or not1079return valid;1080}108110821083bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn)1084{1085if( !video_st || !picture->data[0] )1086return false;10871088if( img_convert_ctx == NULL ||1089frame.width != video_st->codec->width ||1090frame.height != video_st->codec->height ||1091frame.data == NULL )1092{1093// Some sws_scale optimizations have some assumptions about alignment of data/step/width/height1094// Also we use coded_width/height to workaround problem with legacy ffmpeg versions (like n0.8)1095int buffer_width = video_st->codec->coded_width, buffer_height = video_st->codec->coded_height;10961097img_convert_ctx = sws_getCachedContext(1098img_convert_ctx,1099buffer_width, buffer_height,1100video_st->codec->pix_fmt,1101buffer_width, buffer_height,1102AV_PIX_FMT_BGR24,1103SWS_BICUBIC,1104NULL, NULL, NULL1105);11061107if (img_convert_ctx == NULL)1108return false;//CV_Error(0, "Cannot initialize the conversion context!");11091110#if USE_AV_FRAME_GET_BUFFER1111av_frame_unref(&rgb_picture);1112rgb_picture.format = AV_PIX_FMT_BGR24;1113rgb_picture.width = buffer_width;1114rgb_picture.height = buffer_height;1115if (0 != av_frame_get_buffer(&rgb_picture, 32))1116{1117CV_WARN("OutOfMemory");1118return false;1119}1120#else1121int aligns[AV_NUM_DATA_POINTERS];1122avcodec_align_dimensions2(video_st->codec, &buffer_width, &buffer_height, aligns);1123rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0],1124_opencv_ffmpeg_av_image_get_buffer_size( AV_PIX_FMT_BGR24,1125buffer_width, buffer_height ));1126_opencv_ffmpeg_av_image_fill_arrays(&rgb_picture, rgb_picture.data[0],1127AV_PIX_FMT_BGR24, buffer_width, buffer_height );1128#endif1129frame.width = video_st->codec->width;1130frame.height = video_st->codec->height;1131frame.cn = 3;1132frame.data = rgb_picture.data[0];1133frame.step = rgb_picture.linesize[0];1134}11351136sws_scale(1137img_convert_ctx,1138picture->data,1139picture->linesize,11400, video_st->codec->coded_height,1141rgb_picture.data,1142rgb_picture.linesize1143);11441145*data = frame.data;1146*step = frame.step;1147*width = frame.width;1148*height = frame.height;1149*cn = frame.cn;11501151return true;1152}115311541155double CvCapture_FFMPEG::getProperty( int property_id ) const1156{1157if( !video_st ) return 0;11581159double codec_tag = 0;1160AVCodecID codec_id = AV_CODEC_ID_NONE;1161const char* codec_fourcc = NULL;11621163switch( property_id )1164{1165case CV_FFMPEG_CAP_PROP_POS_MSEC:1166return 1000.0*(double)frame_number/get_fps();1167case CV_FFMPEG_CAP_PROP_POS_FRAMES:1168return (double)frame_number;1169case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:1170return r2d(ic->streams[video_stream]->time_base);1171case CV_FFMPEG_CAP_PROP_FRAME_COUNT:1172return (double)get_total_frames();1173case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:1174return (double)frame.width;1175case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:1176return (double)frame.height;1177case CV_FFMPEG_CAP_PROP_FPS:1178return get_fps();1179case CV_FFMPEG_CAP_PROP_FOURCC:1180#if LIBAVFORMAT_BUILD > 46281181codec_id = video_st->codec->codec_id;1182codec_tag = (double) video_st->codec->codec_tag;1183#else1184codec_id = video_st->codec.codec_id;1185codec_tag = (double)video_st->codec.codec_tag;1186#endif11871188if(codec_tag || codec_id == AV_CODEC_ID_NONE)1189{1190return codec_tag;1191}11921193codec_fourcc = _opencv_avcodec_get_name(codec_id);1194if(!codec_fourcc || strlen(codec_fourcc) < 4 || strcmp(codec_fourcc, "unknown_codec") == 0)1195{1196return codec_tag;1197}11981199return (double) OPENCV_FOURCC(codec_fourcc[0], codec_fourcc[1], codec_fourcc[2], codec_fourcc[3]);1200case CV_FFMPEG_CAP_PROP_SAR_NUM:1201return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).num;1202case CV_FFMPEG_CAP_PROP_SAR_DEN:1203return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).den;1204default:1205break;1206}12071208return 0;1209}12101211double CvCapture_FFMPEG::r2d(AVRational r) const1212{1213return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;1214}12151216double CvCapture_FFMPEG::get_duration_sec() const1217{1218double sec = (double)ic->duration / (double)AV_TIME_BASE;12191220if (sec < eps_zero)1221{1222sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base);1223}12241225return sec;1226}12271228int CvCapture_FFMPEG::get_bitrate() const1229{1230return ic->bit_rate;1231}12321233double CvCapture_FFMPEG::get_fps() const1234{1235#if 0 && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 1, 100) && LIBAVFORMAT_VERSION_MICRO >= 1001236double fps = r2d(av_guess_frame_rate(ic, ic->streams[video_stream], NULL));1237#else1238#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)1239double fps = r2d(ic->streams[video_stream]->avg_frame_rate);1240#else1241double fps = r2d(ic->streams[video_stream]->r_frame_rate);1242#endif12431244#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)1245if (fps < eps_zero)1246{1247fps = r2d(ic->streams[video_stream]->avg_frame_rate);1248}1249#endif12501251if (fps < eps_zero)1252{1253fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base);1254}1255#endif1256return fps;1257}12581259int64_t CvCapture_FFMPEG::get_total_frames() const1260{1261int64_t nbf = ic->streams[video_stream]->nb_frames;12621263if (nbf == 0)1264{1265nbf = (int64_t)floor(get_duration_sec() * get_fps() + 0.5);1266}1267return nbf;1268}12691270int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts)1271{1272double sec = dts_to_sec(dts);1273return (int64_t)(get_fps() * sec + 0.5);1274}12751276double CvCapture_FFMPEG::dts_to_sec(int64_t dts)1277{1278return (double)(dts - ic->streams[video_stream]->start_time) *1279r2d(ic->streams[video_stream]->time_base);1280}12811282void CvCapture_FFMPEG::seek(int64_t _frame_number)1283{1284_frame_number = std::min(_frame_number, get_total_frames());1285int delta = 16;12861287// if we have not grabbed a single frame before first seek, let's read the first frame1288// and get some valuable information during the process1289if( first_frame_number < 0 && get_total_frames() > 1 )1290grabFrame();12911292for(;;)1293{1294int64_t _frame_number_temp = std::max(_frame_number-delta, (int64_t)0);1295double sec = (double)_frame_number_temp / get_fps();1296int64_t time_stamp = ic->streams[video_stream]->start_time;1297double time_base = r2d(ic->streams[video_stream]->time_base);1298time_stamp += (int64_t)(sec / time_base + 0.5);1299if (get_total_frames() > 1) av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD);1300avcodec_flush_buffers(ic->streams[video_stream]->codec);1301if( _frame_number > 0 )1302{1303grabFrame();13041305if( _frame_number > 1 )1306{1307frame_number = dts_to_frame_number(picture_pts) - first_frame_number;1308//printf("_frame_number = %d, frame_number = %d, delta = %d\n",1309// (int)_frame_number, (int)frame_number, delta);13101311if( frame_number < 0 || frame_number > _frame_number-1 )1312{1313if( _frame_number_temp == 0 || delta >= INT_MAX/4 )1314break;1315delta = delta < 16 ? delta*2 : delta*3/2;1316continue;1317}1318while( frame_number < _frame_number-1 )1319{1320if(!grabFrame())1321break;1322}1323frame_number++;1324break;1325}1326else1327{1328frame_number = 1;1329break;1330}1331}1332else1333{1334frame_number = 0;1335break;1336}1337}1338}13391340void CvCapture_FFMPEG::seek(double sec)1341{1342seek((int64_t)(sec * get_fps() + 0.5));1343}13441345bool CvCapture_FFMPEG::setProperty( int property_id, double value )1346{1347if( !video_st ) return false;13481349switch( property_id )1350{1351case CV_FFMPEG_CAP_PROP_POS_MSEC:1352case CV_FFMPEG_CAP_PROP_POS_FRAMES:1353case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:1354{1355switch( property_id )1356{1357case CV_FFMPEG_CAP_PROP_POS_FRAMES:1358seek((int64_t)value);1359break;13601361case CV_FFMPEG_CAP_PROP_POS_MSEC:1362seek(value/1000.0);1363break;13641365case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:1366seek((int64_t)(value*ic->duration));1367break;1368}13691370picture_pts=(int64_t)value;1371}1372break;1373default:1374return false;1375}13761377return true;1378}137913801381///////////////// FFMPEG CvVideoWriter implementation //////////////////////////1382struct CvVideoWriter_FFMPEG1383{1384bool open( const char* filename, int fourcc,1385double fps, int width, int height, bool isColor );1386void close();1387bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin );13881389void init();13901391AVOutputFormat * fmt;1392AVFormatContext * oc;1393uint8_t * outbuf;1394uint32_t outbuf_size;1395FILE * outfile;1396AVFrame * picture;1397AVFrame * input_picture;1398uint8_t * picbuf;1399AVStream * video_st;1400int input_pix_fmt;1401unsigned char * aligned_input;1402size_t aligned_input_size;1403int frame_width, frame_height;1404int frame_idx;1405bool ok;1406struct SwsContext *img_convert_ctx;1407};14081409static const char * icvFFMPEGErrStr(int err)1410{1411#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)1412switch(err) {1413case AVERROR_BSF_NOT_FOUND:1414return "Bitstream filter not found";1415case AVERROR_DECODER_NOT_FOUND:1416return "Decoder not found";1417case AVERROR_DEMUXER_NOT_FOUND:1418return "Demuxer not found";1419case AVERROR_ENCODER_NOT_FOUND:1420return "Encoder not found";1421case AVERROR_EOF:1422return "End of file";1423case AVERROR_EXIT:1424return "Immediate exit was requested; the called function should not be restarted";1425case AVERROR_FILTER_NOT_FOUND:1426return "Filter not found";1427case AVERROR_INVALIDDATA:1428return "Invalid data found when processing input";1429case AVERROR_MUXER_NOT_FOUND:1430return "Muxer not found";1431case AVERROR_OPTION_NOT_FOUND:1432return "Option not found";1433case AVERROR_PATCHWELCOME:1434return "Not yet implemented in FFmpeg, patches welcome";1435case AVERROR_PROTOCOL_NOT_FOUND:1436return "Protocol not found";1437case AVERROR_STREAM_NOT_FOUND:1438return "Stream not found";1439default:1440break;1441}1442#else1443switch(err) {1444case AVERROR_NUMEXPECTED:1445return "Incorrect filename syntax";1446case AVERROR_INVALIDDATA:1447return "Invalid data in header";1448case AVERROR_NOFMT:1449return "Unknown format";1450case AVERROR_IO:1451return "I/O error occurred";1452case AVERROR_NOMEM:1453return "Memory allocation error";1454default:1455break;1456}1457#endif14581459return "Unspecified error";1460}14611462/* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/1463extern "C" {1464enum CV_CODEC_ID codec_get_bmp_id(unsigned int tag);1465}14661467void CvVideoWriter_FFMPEG::init()1468{1469fmt = 0;1470oc = 0;1471outbuf = 0;1472outbuf_size = 0;1473outfile = 0;1474picture = 0;1475input_picture = 0;1476picbuf = 0;1477video_st = 0;1478input_pix_fmt = 0;1479aligned_input = NULL;1480aligned_input_size = 0;1481img_convert_ctx = 0;1482frame_width = frame_height = 0;1483frame_idx = 0;1484ok = false;1485}14861487/**1488* the following function is a modified version of code1489* found in ffmpeg-0.4.9-pre1/output_example.c1490*/1491static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)1492{1493AVFrame * picture;1494uint8_t * picture_buf = 0;1495int size;14961497#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \1498? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))1499picture = av_frame_alloc();1500#else1501picture = avcodec_alloc_frame();1502#endif1503if (!picture)1504return NULL;15051506picture->format = pix_fmt;1507picture->width = width;1508picture->height = height;15091510size = _opencv_ffmpeg_av_image_get_buffer_size( (AVPixelFormat) pix_fmt, width, height);1511if(alloc){1512picture_buf = (uint8_t *) malloc(size);1513if (!picture_buf)1514{1515av_free(picture);1516return NULL;1517}1518_opencv_ffmpeg_av_image_fill_arrays(picture, picture_buf,1519(AVPixelFormat) pix_fmt, width, height);1520}15211522return picture;1523}15241525/* add a video output stream to the container */1526static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,1527CV_CODEC_ID codec_id,1528int w, int h, int bitrate,1529double fps, int pixel_format)1530{1531AVCodecContext *c;1532AVStream *st;1533int frame_rate, frame_rate_base;1534AVCodec *codec;15351536#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)1537st = avformat_new_stream(oc, 0);1538#else1539st = av_new_stream(oc, 0);1540#endif15411542if (!st) {1543CV_WARN("Could not allocate stream");1544return NULL;1545}15461547#if LIBAVFORMAT_BUILD > 46281548c = st->codec;1549#else1550c = &(st->codec);1551#endif15521553#if LIBAVFORMAT_BUILD > 46211554c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);1555#else1556c->codec_id = oc->oformat->video_codec;1557#endif15581559if(codec_id != CV_CODEC(CODEC_ID_NONE)){1560c->codec_id = codec_id;1561}15621563//if(codec_tag) c->codec_tag=codec_tag;1564codec = avcodec_find_encoder(c->codec_id);15651566c->codec_type = AVMEDIA_TYPE_VIDEO;15671568#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54,25,0)1569// Set per-codec defaults1570AVCodecID c_id = c->codec_id;1571avcodec_get_context_defaults3(c, codec);1572// avcodec_get_context_defaults3 erases codec_id for some reason1573c->codec_id = c_id;1574#endif15751576/* put sample parameters */1577int64_t lbit_rate = (int64_t)bitrate;1578lbit_rate += (bitrate / 2);1579lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);1580c->bit_rate = lbit_rate;15811582// took advice from1583// http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html1584c->qmin = 3;15851586/* resolution must be a multiple of two */1587c->width = w;1588c->height = h;15891590/* time base: this is the fundamental unit of time (in seconds) in terms1591of which frame timestamps are represented. for fixed-fps content,1592timebase should be 1/framerate and timestamp increments should be1593identically 1. */1594frame_rate=(int)(fps+0.5);1595frame_rate_base=1;1596while (fabs(((double)frame_rate/frame_rate_base) - fps) > 0.001){1597frame_rate_base*=10;1598frame_rate=(int)(fps*frame_rate_base + 0.5);1599}1600#if LIBAVFORMAT_BUILD > 47521601c->time_base.den = frame_rate;1602c->time_base.num = frame_rate_base;1603/* adjust time base for supported framerates */1604if(codec && codec->supported_framerates){1605const AVRational *p= codec->supported_framerates;1606AVRational req = {frame_rate, frame_rate_base};1607const AVRational *best=NULL;1608AVRational best_error= {INT_MAX, 1};1609for(; p->den!=0; p++){1610AVRational error= av_sub_q(req, *p);1611if(error.num <0) error.num *= -1;1612if(av_cmp_q(error, best_error) < 0){1613best_error= error;1614best= p;1615}1616}1617if (best == NULL)1618return NULL;1619c->time_base.den= best->num;1620c->time_base.num= best->den;1621}1622#else1623c->frame_rate = frame_rate;1624c->frame_rate_base = frame_rate_base;1625#endif16261627c->gop_size = 12; /* emit one intra frame every twelve frames at most */1628c->pix_fmt = (AVPixelFormat) pixel_format;16291630if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO)) {1631c->max_b_frames = 2;1632}1633if (c->codec_id == CV_CODEC(CODEC_ID_MPEG1VIDEO) || c->codec_id == CV_CODEC(CODEC_ID_MSMPEG4V3)){1634/* needed to avoid using macroblocks in which some coeffs overflow1635this doesn't happen with normal video, it just happens here as the1636motion of the chroma plane doesn't match the luma plane */1637/* avoid FFMPEG warning 'clipping 1 dct coefficients...' */1638c->mb_decision=2;1639}16401641#if LIBAVUTIL_BUILD > CALC_FFMPEG_VERSION(51,11,0)1642/* Some settings for libx264 encoding, restore dummy values for gop_size1643and qmin since they will be set to reasonable defaults by the libx2641644preset system. Also, use a crf encode with the default quality rating,1645this seems easier than finding an appropriate default bitrate. */1646if (c->codec_id == AV_CODEC_ID_H264) {1647c->gop_size = -1;1648c->qmin = -1;1649c->bit_rate = 0;1650if (c->priv_data)1651av_opt_set(c->priv_data,"crf","23", 0);1652}1653#endif16541655#if LIBAVCODEC_VERSION_INT>0x0004091656// some formats want stream headers to be separate1657if(oc->oformat->flags & AVFMT_GLOBALHEADER)1658{1659#if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)1660c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;1661#else1662c->flags |= CODEC_FLAG_GLOBAL_HEADER;1663#endif1664}1665#endif16661667#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(52, 42, 0)1668st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base};1669#endif1670#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 20, 0)1671st->time_base = c->time_base;1672#endif16731674return st;1675}16761677static const int OPENCV_NO_FRAMES_WRITTEN_CODE = 1000;16781679static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st,1680#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)1681uint8_t *, uint32_t,1682#else1683uint8_t * outbuf, uint32_t outbuf_size,1684#endif1685AVFrame * picture )1686{1687#if LIBAVFORMAT_BUILD > 46281688AVCodecContext * c = video_st->codec;1689#else1690AVCodecContext * c = &(video_st->codec);1691#endif1692int ret = OPENCV_NO_FRAMES_WRITTEN_CODE;16931694#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)1695if (oc->oformat->flags & AVFMT_RAWPICTURE)1696{1697/* raw video case. The API will change slightly in the near1698futur for that */1699AVPacket pkt;1700av_init_packet(&pkt);17011702pkt.flags |= PKT_FLAG_KEY;1703pkt.stream_index= video_st->index;1704pkt.data= (uint8_t *)picture;1705pkt.size= sizeof(AVPicture);17061707ret = av_write_frame(oc, &pkt);1708}1709else1710#endif1711{1712/* encode the image */1713AVPacket pkt;1714av_init_packet(&pkt);1715#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)1716int got_output = 0;1717pkt.data = NULL;1718pkt.size = 0;1719ret = avcodec_encode_video2(c, &pkt, picture, &got_output);1720if (ret < 0)1721;1722else if (got_output) {1723if (pkt.pts != (int64_t)AV_NOPTS_VALUE)1724pkt.pts = av_rescale_q(pkt.pts, c->time_base, video_st->time_base);1725if (pkt.dts != (int64_t)AV_NOPTS_VALUE)1726pkt.dts = av_rescale_q(pkt.dts, c->time_base, video_st->time_base);1727if (pkt.duration)1728pkt.duration = av_rescale_q(pkt.duration, c->time_base, video_st->time_base);1729pkt.stream_index= video_st->index;1730ret = av_write_frame(oc, &pkt);1731_opencv_ffmpeg_av_packet_unref(&pkt);1732}1733else1734ret = OPENCV_NO_FRAMES_WRITTEN_CODE;1735#else1736int out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);1737/* if zero size, it means the image was buffered */1738if (out_size > 0) {1739#if LIBAVFORMAT_BUILD > 47521740if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)1741pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);1742#else1743pkt.pts = c->coded_frame->pts;1744#endif1745if(c->coded_frame->key_frame)1746pkt.flags |= PKT_FLAG_KEY;1747pkt.stream_index= video_st->index;1748pkt.data= outbuf;1749pkt.size= out_size;17501751/* write the compressed frame in the media file */1752ret = av_write_frame(oc, &pkt);1753}1754#endif1755}1756return ret;1757}17581759/// write a frame with FFMPEG1760bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )1761{1762// check parameters1763if (input_pix_fmt == AV_PIX_FMT_BGR24) {1764if (cn != 3) {1765return false;1766}1767}1768else if (input_pix_fmt == AV_PIX_FMT_GRAY8) {1769if (cn != 1) {1770return false;1771}1772}1773else {1774assert(false);1775}17761777if( (width & -2) != frame_width || (height & -2) != frame_height || !data )1778return false;1779width = frame_width;1780height = frame_height;17811782// typecast from opaque data type to implemented struct1783#if LIBAVFORMAT_BUILD > 46281784AVCodecContext *c = video_st->codec;1785#else1786AVCodecContext *c = &(video_st->codec);1787#endif17881789// FFmpeg contains SIMD optimizations which can sometimes read data past1790// the supplied input buffer.1791// Related info: https://trac.ffmpeg.org/ticket/67631792// 1. To ensure that doesn't happen, we pad the step to a multiple of 321793// (that's the minimal alignment for which Valgrind doesn't raise any warnings).1794// 2. (dataend - SIMD_SIZE) and (dataend + SIMD_SIZE) is from the same 4k page1795const int CV_STEP_ALIGNMENT = 32;1796const size_t CV_SIMD_SIZE = 32;1797const size_t CV_PAGE_MASK = ~(4096 - 1);1798const unsigned char* dataend = data + ((size_t)height * step);1799if (step % CV_STEP_ALIGNMENT != 0 ||1800(((size_t)dataend - CV_SIMD_SIZE) & CV_PAGE_MASK) != (((size_t)dataend + CV_SIMD_SIZE) & CV_PAGE_MASK))1801{1802int aligned_step = (step + CV_STEP_ALIGNMENT - 1) & ~(CV_STEP_ALIGNMENT - 1);18031804size_t new_size = (aligned_step * height + CV_SIMD_SIZE);18051806if (!aligned_input || aligned_input_size < new_size)1807{1808if (aligned_input)1809av_freep(&aligned_input);1810aligned_input_size = new_size;1811aligned_input = (unsigned char*)av_mallocz(aligned_input_size);1812}18131814if (origin == 1)1815for( int y = 0; y < height; y++ )1816memcpy(aligned_input + y*aligned_step, data + (height-1-y)*step, step);1817else1818for( int y = 0; y < height; y++ )1819memcpy(aligned_input + y*aligned_step, data + y*step, step);18201821data = aligned_input;1822step = aligned_step;1823}18241825if ( c->pix_fmt != input_pix_fmt ) {1826assert( input_picture );1827// let input_picture point to the raw data buffer of 'image'1828_opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data,1829(AVPixelFormat)input_pix_fmt, width, height);1830input_picture->linesize[0] = step;18311832if( !img_convert_ctx )1833{1834img_convert_ctx = sws_getContext(width,1835height,1836(AVPixelFormat)input_pix_fmt,1837c->width,1838c->height,1839c->pix_fmt,1840SWS_BICUBIC,1841NULL, NULL, NULL);1842if( !img_convert_ctx )1843return false;1844}18451846if ( sws_scale(img_convert_ctx, input_picture->data,1847input_picture->linesize, 0,1848height,1849picture->data, picture->linesize) < 0 )1850return false;1851}1852else{1853_opencv_ffmpeg_av_image_fill_arrays(picture, (uint8_t *) data,1854(AVPixelFormat)input_pix_fmt, width, height);1855picture->linesize[0] = step;1856}18571858picture->pts = frame_idx;1859bool ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;1860frame_idx++;18611862return ret;1863}18641865/// close video output stream and free associated memory1866void CvVideoWriter_FFMPEG::close()1867{1868// nothing to do if already released1869if ( !picture )1870return;18711872/* no more frame to compress. The codec has a latency of a few1873frames if using B frames, so we get the last frames by1874passing the same picture again */1875// TODO -- do we need to account for latency here?18761877/* write the trailer, if any */1878if(ok && oc)1879{1880#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)1881if (!(oc->oformat->flags & AVFMT_RAWPICTURE))1882#endif1883{1884for(;;)1885{1886int ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, NULL);1887if( ret == OPENCV_NO_FRAMES_WRITTEN_CODE || ret < 0 )1888break;1889}1890}1891av_write_trailer(oc);1892}18931894if( img_convert_ctx )1895{1896sws_freeContext(img_convert_ctx);1897img_convert_ctx = 0;1898}18991900// free pictures1901#if LIBAVFORMAT_BUILD > 46281902if( video_st->codec->pix_fmt != input_pix_fmt)1903#else1904if( video_st->codec.pix_fmt != input_pix_fmt)1905#endif1906{1907if(picture->data[0])1908free(picture->data[0]);1909picture->data[0] = 0;1910}1911av_free(picture);19121913if (input_picture)1914av_free(input_picture);19151916/* close codec */1917#if LIBAVFORMAT_BUILD > 46281918avcodec_close(video_st->codec);1919#else1920avcodec_close(&(video_st->codec));1921#endif19221923av_free(outbuf);19241925if (oc)1926{1927if (!(fmt->flags & AVFMT_NOFILE))1928{1929/* close the output file */19301931#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)1932#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)1933url_fclose(oc->pb);1934#else1935url_fclose(&oc->pb);1936#endif1937#else1938avio_close(oc->pb);1939#endif19401941}19421943/* free the stream */1944avformat_free_context(oc);1945}19461947av_freep(&aligned_input);19481949init();1950}19511952#define CV_PRINTABLE_CHAR(ch) ((ch) < 32 ? '?' : (ch))1953#define CV_TAG_TO_PRINTABLE_CHAR4(tag) CV_PRINTABLE_CHAR((tag) & 255), CV_PRINTABLE_CHAR(((tag) >> 8) & 255), CV_PRINTABLE_CHAR(((tag) >> 16) & 255), CV_PRINTABLE_CHAR(((tag) >> 24) & 255)19541955static inline bool cv_ff_codec_tag_match(const AVCodecTag *tags, CV_CODEC_ID id, unsigned int tag)1956{1957while (tags->id != AV_CODEC_ID_NONE)1958{1959if (tags->id == id && tags->tag == tag)1960return true;1961tags++;1962}1963return false;1964}1965static inline bool cv_ff_codec_tag_list_match(const AVCodecTag *const *tags, CV_CODEC_ID id, unsigned int tag)1966{1967int i;1968for (i = 0; tags && tags[i]; i++) {1969bool res = cv_ff_codec_tag_match(tags[i], id, tag);1970if (res)1971return res;1972}1973return false;1974}19751976/// Create a video writer object that uses FFMPEG1977bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,1978double fps, int width, int height, bool is_color )1979{1980CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_NONE);1981int err, codec_pix_fmt;1982double bitrate_scale = 1;19831984close();19851986// check arguments1987if( !filename )1988return false;1989if(fps <= 0)1990return false;19911992// we allow frames of odd width or height, but in this case we truncate1993// the rightmost column/the bottom row. Probably, this should be handled more elegantly,1994// but some internal functions inside FFMPEG swscale require even width/height.1995width &= -2;1996height &= -2;1997if( width <= 0 || height <= 0 )1998return false;19992000/* auto detect the output format from the name and fourcc code. */20012002#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)2003fmt = av_guess_format(NULL, filename, NULL);2004#else2005fmt = guess_format(NULL, filename, NULL);2006#endif20072008if (!fmt)2009return false;20102011/* determine optimal pixel format */2012if (is_color) {2013input_pix_fmt = AV_PIX_FMT_BGR24;2014}2015else {2016input_pix_fmt = AV_PIX_FMT_GRAY8;2017}20182019/* Lookup codec_id for given fourcc */2020#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)2021if( (codec_id = codec_get_bmp_id( fourcc )) == CV_CODEC(CODEC_ID_NONE) )2022return false;2023#else2024if( (codec_id = av_codec_get_id(fmt->codec_tag, fourcc)) == CV_CODEC(CODEC_ID_NONE) )2025{2026const struct AVCodecTag * fallback_tags[] = {2027#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)2028// APIchanges:2029// 2012-01-31 - dd6d3b0 - lavf 54.01.02030// Add avformat_get_riff_video_tags() and avformat_get_riff_audio_tags().2031avformat_get_riff_video_tags(),2032#endif2033#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 25, 100) && defined LIBAVFORMAT_VERSION_MICRO && LIBAVFORMAT_VERSION_MICRO >= 1002034// APIchanges: ffmpeg only2035// 2014-01-19 - 1a193c4 - lavf 55.25.100 - avformat.h2036// Add avformat_get_mov_video_tags() and avformat_get_mov_audio_tags().2037avformat_get_mov_video_tags(),2038#endif2039codec_bmp_tags, // fallback for avformat < 54.12040NULL };2041if( (codec_id = av_codec_get_id(fallback_tags, fourcc)) == CV_CODEC(CODEC_ID_NONE) )2042{2043fflush(stdout);2044fprintf(stderr, "OpenCV: FFMPEG: tag 0x%08x/'%c%c%c%c' is not found (format '%s / %s')'\n",2045fourcc, CV_TAG_TO_PRINTABLE_CHAR4(fourcc),2046fmt->name, fmt->long_name);2047return false;2048}2049}2050// validate tag2051if (cv_ff_codec_tag_list_match(fmt->codec_tag, codec_id, fourcc) == false)2052{2053fflush(stdout);2054fprintf(stderr, "OpenCV: FFMPEG: tag 0x%08x/'%c%c%c%c' is not supported with codec id %d and format '%s / %s'\n",2055fourcc, CV_TAG_TO_PRINTABLE_CHAR4(fourcc),2056codec_id, fmt->name, fmt->long_name);2057int supported_tag;2058if( (supported_tag = av_codec_get_tag(fmt->codec_tag, codec_id)) != 0 )2059{2060fprintf(stderr, "OpenCV: FFMPEG: fallback to use tag 0x%08x/'%c%c%c%c'\n",2061supported_tag, CV_TAG_TO_PRINTABLE_CHAR4(supported_tag));2062fourcc = supported_tag;2063}2064}2065#endif20662067// alloc memory for context2068#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)2069oc = avformat_alloc_context();2070#else2071oc = av_alloc_format_context();2072#endif2073assert (oc);20742075/* set file name */2076oc->oformat = fmt;2077snprintf(oc->filename, sizeof(oc->filename), "%s", filename);20782079/* set some options */2080oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */20812082// set a few optimal pixel formats for lossless codecs of interest..2083switch (codec_id) {2084#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)2085case CV_CODEC(CODEC_ID_JPEGLS):2086// BGR24 or GRAY8 depending on is_color...2087codec_pix_fmt = input_pix_fmt;2088break;2089#endif2090case CV_CODEC(CODEC_ID_HUFFYUV):2091codec_pix_fmt = AV_PIX_FMT_YUV422P;2092break;2093case CV_CODEC(CODEC_ID_MJPEG):2094case CV_CODEC(CODEC_ID_LJPEG):2095codec_pix_fmt = AV_PIX_FMT_YUVJ420P;2096bitrate_scale = 3;2097break;2098case CV_CODEC(CODEC_ID_RAWVIDEO):2099codec_pix_fmt = input_pix_fmt == AV_PIX_FMT_GRAY8 ||2100input_pix_fmt == AV_PIX_FMT_GRAY16LE ||2101input_pix_fmt == AV_PIX_FMT_GRAY16BE ? input_pix_fmt : AV_PIX_FMT_YUV420P;2102break;2103default:2104// good for lossy formats, MPEG, etc.2105codec_pix_fmt = AV_PIX_FMT_YUV420P;2106break;2107}21082109double bitrate = MIN(bitrate_scale*fps*width*height, (double)INT_MAX/2);21102111// TODO -- safe to ignore output audio stream?2112video_st = icv_add_video_stream_FFMPEG(oc, codec_id,2113width, height, (int)(bitrate + 0.5),2114fps, codec_pix_fmt);21152116/* set the output parameters (must be done even if no2117parameters). */2118#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)2119if (av_set_parameters(oc, NULL) < 0) {2120return false;2121}2122#endif21232124#if 02125#if FF_API_DUMP_FORMAT2126dump_format(oc, 0, filename, 1);2127#else2128av_dump_format(oc, 0, filename, 1);2129#endif2130#endif21312132/* now that all the parameters are set, we can open the audio and2133video codecs and allocate the necessary encode buffers */2134if (!video_st){2135return false;2136}21372138AVCodec *codec;2139AVCodecContext *c;21402141#if LIBAVFORMAT_BUILD > 46282142c = (video_st->codec);2143#else2144c = &(video_st->codec);2145#endif21462147c->codec_tag = fourcc;2148/* find the video encoder */2149codec = avcodec_find_encoder(c->codec_id);2150if (!codec) {2151fprintf(stderr, "Could not find encoder for codec id %d: %s\n", c->codec_id, icvFFMPEGErrStr(2152#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)2153AVERROR_ENCODER_NOT_FOUND2154#else2155-12156#endif2157));2158return false;2159}21602161int64_t lbit_rate = (int64_t)c->bit_rate;2162lbit_rate += (bitrate / 2);2163lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);2164c->bit_rate_tolerance = (int)lbit_rate;2165c->bit_rate = (int)lbit_rate;21662167/* open the codec */2168if ((err=2169#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)2170avcodec_open2(c, codec, NULL)2171#else2172avcodec_open(c, codec)2173#endif2174) < 0) {2175fprintf(stderr, "Could not open codec '%s': %s\n", codec->name, icvFFMPEGErrStr(err));2176return false;2177}21782179outbuf = NULL;218021812182#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)2183if (!(oc->oformat->flags & AVFMT_RAWPICTURE))2184#endif2185{2186/* allocate output buffer */2187/* assume we will never get codec output with more than 4 bytes per pixel... */2188outbuf_size = width*height*4;2189outbuf = (uint8_t *) av_malloc(outbuf_size);2190}21912192bool need_color_convert;2193need_color_convert = (c->pix_fmt != input_pix_fmt);21942195/* allocate the encoded raw picture */2196picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);2197if (!picture) {2198return false;2199}22002201/* if the output format is not our input format, then a temporary2202picture of the input format is needed too. It is then converted2203to the required output format */2204input_picture = NULL;2205if ( need_color_convert ) {2206input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);2207if (!input_picture) {2208return false;2209}2210}22112212/* open the output file, if needed */2213if (!(fmt->flags & AVFMT_NOFILE)) {2214#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)2215if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)2216#else2217if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0)2218#endif2219{2220return false;2221}2222}22232224#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)2225/* write the stream header, if any */2226err=avformat_write_header(oc, NULL);2227#else2228err=av_write_header( oc );2229#endif22302231if(err < 0)2232{2233close();2234remove(filename);2235return false;2236}2237frame_width = width;2238frame_height = height;2239frame_idx = 0;2240ok = true;22412242return true;2243}2244224522462247CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )2248{2249CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));2250if (!capture)2251return 0;2252capture->init();2253if( capture->open( filename ))2254return capture;22552256capture->close();2257free(capture);2258return 0;2259}226022612262void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)2263{2264if( capture && *capture )2265{2266(*capture)->close();2267free(*capture);2268*capture = 0;2269}2270}22712272int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)2273{2274return capture->setProperty(prop_id, value);2275}22762277double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)2278{2279return capture->getProperty(prop_id);2280}22812282int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)2283{2284return capture->grabFrame();2285}22862287int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* capture, unsigned char** data, int* step, int* width, int* height, int* cn)2288{2289return capture->retrieveFrame(0, data, step, width, height, cn);2290}22912292CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,2293int width, int height, int isColor )2294{2295CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));2296if (!writer)2297return 0;2298writer->init();2299if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))2300return writer;2301writer->close();2302free(writer);2303return 0;2304}23052306void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )2307{2308if( writer && *writer )2309{2310(*writer)->close();2311free(*writer);2312*writer = 0;2313}2314}231523162317int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,2318const unsigned char* data, int step,2319int width, int height, int cn, int origin)2320{2321return writer->writeFrame(data, step, width, height, cn, origin);2322}2323232423252326/*2327* For CUDA encoder2328*/23292330struct OutputMediaStream_FFMPEG2331{2332bool open(const char* fileName, int width, int height, double fps);2333void close();23342335void write(unsigned char* data, int size, int keyFrame);23362337// add a video output stream to the container2338static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format);23392340AVOutputFormat* fmt_;2341AVFormatContext* oc_;2342AVStream* video_st_;2343};23442345void OutputMediaStream_FFMPEG::close()2346{2347// no more frame to compress. The codec has a latency of a few2348// frames if using B frames, so we get the last frames by2349// passing the same picture again23502351// TODO -- do we need to account for latency here?23522353if (oc_)2354{2355// write the trailer, if any2356av_write_trailer(oc_);23572358// free the streams2359for (unsigned int i = 0; i < oc_->nb_streams; ++i)2360{2361av_freep(&oc_->streams[i]->codec);2362av_freep(&oc_->streams[i]);2363}23642365if (!(fmt_->flags & AVFMT_NOFILE) && oc_->pb)2366{2367// close the output file23682369#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)2370#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)2371url_fclose(oc_->pb);2372#else2373url_fclose(&oc_->pb);2374#endif2375#else2376avio_close(oc_->pb);2377#endif2378}23792380// free the stream2381av_free(oc_);2382}2383}23842385AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format)2386{2387AVCodec* codec = avcodec_find_encoder(codec_id);2388if (!codec)2389{2390fprintf(stderr, "Could not find encoder for codec id %d\n", codec_id);2391return NULL;2392}23932394#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)2395AVStream* st = avformat_new_stream(oc, 0);2396#else2397AVStream* st = av_new_stream(oc, 0);2398#endif2399if (!st)2400return 0;24012402#if LIBAVFORMAT_BUILD > 46282403AVCodecContext* c = st->codec;2404#else2405AVCodecContext* c = &(st->codec);2406#endif24072408c->codec_id = codec_id;2409c->codec_type = AVMEDIA_TYPE_VIDEO;24102411// put sample parameters2412c->bit_rate = bitrate;24132414// took advice from2415// http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html2416c->qmin = 3;24172418// resolution must be a multiple of two2419c->width = w;2420c->height = h;24212422// time base: this is the fundamental unit of time (in seconds) in terms2423// of which frame timestamps are represented. for fixed-fps content,2424// timebase should be 1/framerate and timestamp increments should be2425// identically 124262427int frame_rate = static_cast<int>(fps+0.5);2428int frame_rate_base = 1;2429while (fabs((static_cast<double>(frame_rate)/frame_rate_base) - fps) > 0.001)2430{2431frame_rate_base *= 10;2432frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);2433}2434c->time_base.den = frame_rate;2435c->time_base.num = frame_rate_base;24362437#if LIBAVFORMAT_BUILD > 47522438// adjust time base for supported framerates2439if (codec && codec->supported_framerates)2440{2441AVRational req = {frame_rate, frame_rate_base};2442const AVRational* best = NULL;2443AVRational best_error = {INT_MAX, 1};24442445for (const AVRational* p = codec->supported_framerates; p->den!=0; ++p)2446{2447AVRational error = av_sub_q(req, *p);24482449if (error.num < 0)2450error.num *= -1;24512452if (av_cmp_q(error, best_error) < 0)2453{2454best_error= error;2455best= p;2456}2457}24582459if (best == NULL)2460return NULL;2461c->time_base.den= best->num;2462c->time_base.num= best->den;2463}2464#endif24652466c->gop_size = 12; // emit one intra frame every twelve frames at most2467c->pix_fmt = pixel_format;24682469if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO))2470c->max_b_frames = 2;24712472if (c->codec_id == CV_CODEC(CODEC_ID_MPEG1VIDEO) || c->codec_id == CV_CODEC(CODEC_ID_MSMPEG4V3))2473{2474// needed to avoid using macroblocks in which some coeffs overflow2475// this doesn't happen with normal video, it just happens here as the2476// motion of the chroma plane doesn't match the luma plane24772478// avoid FFMPEG warning 'clipping 1 dct coefficients...'24792480c->mb_decision = 2;2481}24822483#if LIBAVCODEC_VERSION_INT > 0x0004092484// some formats want stream headers to be separate2485if (oc->oformat->flags & AVFMT_GLOBALHEADER)2486{2487#if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)2488c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;2489#else2490c->flags |= CODEC_FLAG_GLOBAL_HEADER;2491#endif2492}2493#endif24942495return st;2496}24972498bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)2499{2500fmt_ = 0;2501oc_ = 0;2502video_st_ = 0;25032504// auto detect the output format from the name and fourcc code2505#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)2506fmt_ = av_guess_format(NULL, fileName, NULL);2507#else2508fmt_ = guess_format(NULL, fileName, NULL);2509#endif2510if (!fmt_)2511return false;25122513CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_H264);25142515// alloc memory for context2516#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)2517oc_ = avformat_alloc_context();2518#else2519oc_ = av_alloc_format_context();2520#endif2521if (!oc_)2522return false;25232524// set some options2525oc_->oformat = fmt_;2526snprintf(oc_->filename, sizeof(oc_->filename), "%s", fileName);25272528oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG25292530// set a few optimal pixel formats for lossless codecs of interest..2531AVPixelFormat codec_pix_fmt = AV_PIX_FMT_YUV420P;2532int bitrate_scale = 64;25332534// TODO -- safe to ignore output audio stream?2535video_st_ = addVideoStream(oc_, codec_id, width, height, width * height * bitrate_scale, fps, codec_pix_fmt);2536if (!video_st_)2537return false;25382539// set the output parameters (must be done even if no parameters)2540#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)2541if (av_set_parameters(oc_, NULL) < 0)2542return false;2543#endif25442545// now that all the parameters are set, we can open the audio and2546// video codecs and allocate the necessary encode buffers25472548#if LIBAVFORMAT_BUILD > 46282549AVCodecContext* c = (video_st_->codec);2550#else2551AVCodecContext* c = &(video_st_->codec);2552#endif25532554c->codec_tag = MKTAG('H', '2', '6', '4');2555c->bit_rate_tolerance = c->bit_rate;25562557// open the output file, if needed2558if (!(fmt_->flags & AVFMT_NOFILE))2559{2560#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)2561int err = url_fopen(&oc_->pb, fileName, URL_WRONLY);2562#else2563int err = avio_open(&oc_->pb, fileName, AVIO_FLAG_WRITE);2564#endif25652566if (err != 0)2567return false;2568}25692570// write the stream header, if any2571int header_err =2572#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)2573av_write_header(oc_);2574#else2575avformat_write_header(oc_, NULL);2576#endif2577if (header_err != 0)2578return false;25792580return true;2581}25822583void OutputMediaStream_FFMPEG::write(unsigned char* data, int size, int keyFrame)2584{2585// if zero size, it means the image was buffered2586if (size > 0)2587{2588AVPacket pkt;2589av_init_packet(&pkt);25902591if (keyFrame)2592pkt.flags |= PKT_FLAG_KEY;25932594pkt.stream_index = video_st_->index;2595pkt.data = data;2596pkt.size = size;25972598// write the compressed frame in the media file2599av_write_frame(oc_, &pkt);2600}2601}26022603struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps)2604{2605OutputMediaStream_FFMPEG* stream = (OutputMediaStream_FFMPEG*) malloc(sizeof(OutputMediaStream_FFMPEG));2606if (!stream)2607return 0;26082609if (stream->open(fileName, width, height, fps))2610return stream;26112612stream->close();2613free(stream);26142615return 0;2616}26172618void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)2619{2620stream->close();2621free(stream);2622}26232624void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame)2625{2626stream->write(data, size, keyFrame);2627}26282629/*2630* For CUDA decoder2631*/26322633enum2634{2635VideoCodec_MPEG1 = 0,2636VideoCodec_MPEG2,2637VideoCodec_MPEG4,2638VideoCodec_VC1,2639VideoCodec_H264,2640VideoCodec_JPEG,2641VideoCodec_H264_SVC,2642VideoCodec_H264_MVC,26432644// Uncompressed YUV2645VideoCodec_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), // Y,U,V (4:2:0)2646VideoCodec_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,V,U (4:2:0)2647VideoCodec_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,UV (4:2:0)2648VideoCodec_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), // YUYV/YUY2 (4:2:2)2649VideoCodec_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')) // UYVY (4:2:2)2650};26512652enum2653{2654VideoChromaFormat_Monochrome = 0,2655VideoChromaFormat_YUV420,2656VideoChromaFormat_YUV422,2657VideoChromaFormat_YUV4442658};26592660struct InputMediaStream_FFMPEG2661{2662public:2663bool open(const char* fileName, int* codec, int* chroma_format, int* width, int* height);2664void close();26652666bool read(unsigned char** data, int* size, int* endOfFile);26672668private:2669InputMediaStream_FFMPEG(const InputMediaStream_FFMPEG&);2670InputMediaStream_FFMPEG& operator =(const InputMediaStream_FFMPEG&);26712672AVFormatContext* ctx_;2673int video_stream_id_;2674AVPacket pkt_;26752676#if USE_AV_INTERRUPT_CALLBACK2677AVInterruptCallbackMetadata interrupt_metadata;2678#endif2679};26802681bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)2682{2683int err;26842685ctx_ = 0;2686video_stream_id_ = -1;2687memset(&pkt_, 0, sizeof(AVPacket));26882689#if USE_AV_INTERRUPT_CALLBACK2690/* interrupt callback */2691interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;2692get_monotonic_time(&interrupt_metadata.value);26932694ctx_ = avformat_alloc_context();2695ctx_->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;2696ctx_->interrupt_callback.opaque = &interrupt_metadata;2697#endif26982699#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)2700avformat_network_init();2701#endif27022703#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)2704err = avformat_open_input(&ctx_, fileName, 0, 0);2705#else2706err = av_open_input_file(&ctx_, fileName, 0, 0, 0);2707#endif2708if (err < 0)2709return false;27102711#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)2712err = avformat_find_stream_info(ctx_, 0);2713#else2714err = av_find_stream_info(ctx_);2715#endif2716if (err < 0)2717return false;27182719for (unsigned int i = 0; i < ctx_->nb_streams; ++i)2720{2721#if LIBAVFORMAT_BUILD > 46282722AVCodecContext *enc = ctx_->streams[i]->codec;2723#else2724AVCodecContext *enc = &ctx_->streams[i]->codec;2725#endif27262727if (enc->codec_type == AVMEDIA_TYPE_VIDEO)2728{2729video_stream_id_ = static_cast<int>(i);27302731switch (enc->codec_id)2732{2733case CV_CODEC(CODEC_ID_MPEG1VIDEO):2734*codec = ::VideoCodec_MPEG1;2735break;27362737case CV_CODEC(CODEC_ID_MPEG2VIDEO):2738*codec = ::VideoCodec_MPEG2;2739break;27402741case CV_CODEC(CODEC_ID_MPEG4):2742*codec = ::VideoCodec_MPEG4;2743break;27442745case CV_CODEC(CODEC_ID_VC1):2746*codec = ::VideoCodec_VC1;2747break;27482749case CV_CODEC(CODEC_ID_H264):2750*codec = ::VideoCodec_H264;2751break;27522753default:2754return false;2755};27562757switch (enc->pix_fmt)2758{2759case AV_PIX_FMT_YUV420P:2760*chroma_format = ::VideoChromaFormat_YUV420;2761break;27622763case AV_PIX_FMT_YUV422P:2764*chroma_format = ::VideoChromaFormat_YUV422;2765break;27662767case AV_PIX_FMT_YUV444P:2768*chroma_format = ::VideoChromaFormat_YUV444;2769break;27702771default:2772return false;2773}27742775*width = enc->coded_width;2776*height = enc->coded_height;27772778break;2779}2780}27812782if (video_stream_id_ < 0)2783return false;27842785av_init_packet(&pkt_);27862787#if USE_AV_INTERRUPT_CALLBACK2788// deactivate interrupt callback2789interrupt_metadata.timeout_after_ms = 0;2790#endif27912792return true;2793}27942795void InputMediaStream_FFMPEG::close()2796{2797if (ctx_)2798{2799#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 24, 2)2800avformat_close_input(&ctx_);2801#else2802av_close_input_file(ctx_);2803#endif2804}28052806// free last packet if exist2807if (pkt_.data)2808_opencv_ffmpeg_av_packet_unref(&pkt_);2809}28102811bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile)2812{2813bool result = false;28142815#if USE_AV_INTERRUPT_CALLBACK2816// activate interrupt callback2817get_monotonic_time(&interrupt_metadata.value);2818interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;2819#endif28202821// free last packet if exist2822if (pkt_.data)2823_opencv_ffmpeg_av_packet_unref(&pkt_);28242825// get the next frame2826for (;;)2827{2828#if USE_AV_INTERRUPT_CALLBACK2829if(interrupt_metadata.timeout)2830{2831break;2832}2833#endif28342835int ret = av_read_frame(ctx_, &pkt_);28362837if (ret == AVERROR(EAGAIN))2838continue;28392840if (ret < 0)2841{2842if (ret == (int)AVERROR_EOF)2843*endOfFile = true;2844break;2845}28462847if (pkt_.stream_index != video_stream_id_)2848{2849_opencv_ffmpeg_av_packet_unref(&pkt_);2850continue;2851}28522853result = true;2854break;2855}28562857#if USE_AV_INTERRUPT_CALLBACK2858// deactivate interrupt callback2859interrupt_metadata.timeout_after_ms = 0;2860#endif28612862if (result)2863{2864*data = pkt_.data;2865*size = pkt_.size;2866*endOfFile = false;2867}28682869return result;2870}28712872InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height)2873{2874InputMediaStream_FFMPEG* stream = (InputMediaStream_FFMPEG*) malloc(sizeof(InputMediaStream_FFMPEG));2875if (!stream)2876return 0;28772878if (stream && stream->open(fileName, codec, chroma_format, width, height))2879return stream;28802881stream->close();2882free(stream);28832884return 0;2885}28862887void release_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream)2888{2889stream->close();2890free(stream);2891}28922893int read_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile)2894{2895return stream->read(data, size, endOfFile);2896}289728982899