opencv with ffmpeg 代码解析(二) 桃扇骨 2021-05-16 20:36 499阅读 0赞 1、代码入口 看opencv的代码,最好的切入点就是对外的头文件 opencv.hpp ![20200606172421742.png][] include 目录下仅有opencv.hpp文件 ![2020060617323515.png][] 所有的video read和write相关代码都在modules/videoio这个模块里 2、IVideoCapture IVideoWriter 实现 在videoio.hpp里声明了VideoCapture VideoWriter IVideoCapture IVideoWriter 四种类 其中 IVideoCapture IVideoWriter 为接口类,定义位于 cap\_interface.hpp 当需要使用第三方库如ffmpeg实现video读写时,可以继承接口类 这两个类定义了很多虚函数,方便调用者调用,而继承者只要继承并实现这些函数,就可以实现video read和write功能 class IVideoCapture { public: virtual ~IVideoCapture() {} virtual double getProperty(int) const { return 0; } virtual bool setProperty(int, double) { return false; } virtual bool grabFrame() = 0; virtual bool retrieveFrame(int, OutputArray) = 0; virtual bool isOpened() const = 0; virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc... }; class IVideoWriter { public: virtual ~IVideoWriter() {} virtual double getProperty(int) const { return 0; } virtual bool setProperty(int, double) { return false; } virtual bool isOpened() const = 0; virtual void write(InputArray) = 0; virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc... }; 3、FFmpeg 读功能实现 下面我们以ffmpeg为例简述这种功能实现方式,功能实现位于 cap\_ffmpeg.cpp、cap\_ffmpeg\_impl.hpp、cap\_ffmpeg\_legacy\_api.hpp 文件中 CvCapture\_FFMPEG\_proxy继承了IVideoCapture,CvCapture\_FFMPEG\_proxy通过 CvCapture\_FFMPEG类实现了video的读取 CvCapture\_FFMPEG定义如下: struct CvCapture_FFMPEG { bool open( const char* filename ); void close(); double getProperty(int) const; bool setProperty(int, double); bool grabFrame(); bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn); void init(); void seek(int64_t frame_number); void seek(double sec); bool slowSeek( int framenumber ); int64_t get_total_frames() const; double get_duration_sec() const; double get_fps() const; int64_t get_bitrate() const; double r2d(AVRational r) const; int64_t dts_to_frame_number(int64_t dts); double dts_to_sec(int64_t dts) const; AVFormatContext * ic; AVCodec * avcodec; int video_stream; AVStream * video_st; AVFrame * picture; AVFrame rgb_picture; int64_t picture_pts; AVPacket packet; Image_FFMPEG frame; struct SwsContext *img_convert_ctx; int64_t frame_number, first_frame_number; double eps_zero; /* 'filename' contains the filename of the videosource, 'filename==NULL' indicates that ffmpeg's seek support works for the particular file. 'filename!=NULL' indicates that the slow fallback function is used for seeking, and so the filename is needed to reopen the file on backward seeking. */ char * filename; #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0) AVDictionary *dict; #endif #if USE_AV_INTERRUPT_CALLBACK AVInterruptCallbackMetadata interrupt_metadata; #endif bool setRaw(); bool processRawPacket(); bool rawMode; bool rawModeInitialized; AVPacket packet_filtered; #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(58, 20, 100) AVBSFContext* bsfc; #else AVBitStreamFilterContext* bsfc; #endif }; [20200606172421742.png]: /images/20210516/d7ec9f57bbba40e78adc23ddcba6cdc4.png [2020060617323515.png]: /images/20210516/3dfdb35491174c4eaa81f3f9931d80ce.png
还没有评论,来说两句吧...