支持opencv的Mat图像采用x264等编码器编码的类

来源:互联网 发布:hydra windows版使用 编辑:程序博客网 时间:2024/04/29 04:41

虽然在opencv中提供了videoWriter类可以将opencv图像编码成视频,但是由于自带的videoWriter支持的格式都是未经压缩的,具体参考如下:

CV_FOURCC('P', 'I', 'M', '1') = MPEG-1 codec

CV_FOURCC('M', 'J', 'P', 'G') = motion-jpeg codec
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec 
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec 
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec 
CV_FOURCC('U', '2', '6', '3') = H263 codec 
CV_FOURCC('I', '2', '6', '3') = H263I codec 

CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

对于视觉开发末期经常需要将处理过后的视频压缩存储,此时就需要借助一些特定编码器完成,opencv中视频支持相关的都是采用ffmpeg完成的,而原本的opencv中并不支持所有的ffmpeg功能。所以一种方案是自己编译opencv + ffmpeg,另一种就是自己使用对应编码器完成编码。

本文采用第二种方法,通过参考雷霄骅大神的代码,自己封装了一个可供opencv调用的视频编码类(videoEncode),类的接口和opencv的videoWriter比较类似,可以调用各种编码器直接将Mat数据压缩成avi封装格式的视频(理论上是可以各种封装格式的,无奈没有解决pts和dts的问题,其他格式播放过快)。

贴出部分代码:

#ifndef VIDEOENCODER_H#define VIDEOENCODER_H#include <iostream>#include <string>#include <strstream>#include <opencv.hpp>#include "ffCodecs.hpp"extern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswscale/swscale.h"#include "libavutil/opt.h"}using namespace std;using namespace cv;typedef unsigned long long uInt64;
class videoEncoder{public:    videoEncoder();    videoEncoder(std::string filename, int codecID, double frameRate, int imgWidth, int imgHeight);   //编码器和输出文件名    ~videoEncoder();    bool isOpened();                                                //编码器是否已经打开    bool open(std::string filename, int codecID, double frameRate, int imgWidth, int imgHeight); //打开编码器    void setParam(int codecID, double frameRate, int imgWidth, int imgHeight);                    //设置参数    void setBitrateControl(std::string controlMode, int bpsValue);         //码流控制方式及大小    void close();                                                   //关闭编码器    bool write(const Mat &frame);                                      //写视频protected:    void init();    bool allocParamMem();               //为编码器参数分配空间    std::string int2String(int interger);    int flushEncoder(AVFormatContext *fmt_ctx,unsigned int stream_index);  //清空编码器的缓冲区    //设置编码器    int setCodec(char codec[4]);private:    AVFormatContext* pFormatCtx;        //    AVOutputFormat* fmt;    AVStream* video_st;    AVCodecContext* pCodecCtx;    AVCodec* pCodec;                    //编码器格式,可自主指定,默认由封装格式后缀名决定    AVPacket pkt;                       //视频帧packet    //uint8_t* picture_buf;               //图像buffer    unsigned char* picture_buf;         //图像buffer    AVFrame* picture;    int size;    int y_size;                         //帧大小    int bpsValue;                       //码流控制方式的对应值    int bpsMode;                        //码流控制方式,0表示平均码率(abr),1表示固定码率(crf),2表示固定质量(cqp)    cv::Mat image;                      //opencv中传来待编码的帧    int img_width;                      //帧宽    int img_height;                     //帧高    std::string outputFileName;         //输出文件名,由后缀决定封装格式    int fourcc;                         //编码器的四字节码    double fps;                         //帧率    uInt64 frameIndex;                   //当前帧序号    bool isSetEncoderFlag;               //是否自设定编码器    bool isOpenedFlag;                  //编码器是否已经打开};#endif // VIDEOENCODER_H
<pre name="code" class="cpp">//写视频帧bool videoEncoder::write(const cv::Mat& frame){    cv::Mat temp;    cvtColor(frame,temp,COLOR_BGR2YUV_I420);    picture_buf = temp.data;    picture->data[0] = picture_buf;         //Y    picture->data[1] = picture_buf+y_size;  //U    picture->data[2] = picture_buf+(y_size*5/4);//V    picture->pts = frameIndex++;    int got_picture = 0;    int ret = avcodec_encode_video2(pCodecCtx,&pkt,picture,&got_picture);    if(ret<0)    {        printf("encode error!\n");        return false;    }    if(got_picture==1)    {        pkt.stream_index = video_st->index;        printf("pkt_pts:%d dts:%d\n",pkt.pts,pkt.dts);        //ret = av_write_frame(pFormatCtx, &pkt);        ret = av_interleaved_write_frame(pFormatCtx,&pkt);        av_free_packet(&pkt);    }    return true;}


完整工程(Qt工程,vs可以自己选取c文件和h,hpp文件建立):

videoEncoder

对于封装成其他格式如MP4,flv,mkv时出现播放过快的问题没有解决,希望知道的大神给与指点!同时该类并不是和opencv自带的videoWriter一样是线程安全的,如果希望线程安全需要自己改写!



0 0
原创粉丝点击