如何使用AvConv创建灰度视频



我一直在寻找一段时间,以一种快速可靠的方式来创建与avconv库中的灰度视频,这些视频是在C 应用程序中使用openCV捕获/创建的框架的。

我知道OpenCV具有创建视频的内部方式,但是它具有一些编码性能和选项限制。

那么,这样,我想知道完成此任务的选择是哪些?

用于完成此任务,我发现的选项之一,符合我的需求是以下类:

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/mathematics.h>
}
class AVConvVideoMaker
{
    AVCodec* codec;
    AVCodecContext* context;
    AVFrame* picture;
    int imgWidth, imgHeight, imgBufferSize;
    FILE* outputFile;
    int outputBufferSize;
    uint8_t* outputBuffer;
    int pictureBufferSize;
    uint8_t* pictureBuffer;
    int outputSize;
public:
    AVConvVideoMaker(std::string outputFilePath, int imgWidth, int imgHeight)
        : codec(NULL)
        , context(NULL)
        , picture(NULL)
        , imgWidth(imgWidth)
        , imgHeight(imgHeight)
        , imgBufferSize(imgWidth*imgHeight)
        , outputFile(fopen(outputFilePath.c_str(), "wb"))
        , outputBufferSize(100000)
        , outputBuffer(new uint8_t[outputBufferSize])
        , pictureBufferSize((imgBufferSize*3)/2)
        , pictureBuffer(new uint8_t[pictureBufferSize])
        , outputSize(0)
    {
        avcodec_register_all();
        this->codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
        if (!this->codec)
        {
            throw std::runtime_error("Codec not found");
        }
        this->context = avcodec_alloc_context3(codec);
        this->picture = avcodec_alloc_frame();
        this->context->bit_rate = 400000;
        this->context->width = this->imgWidth;
        this->context->height = this->imgHeight;
        this->context->time_base = (AVRational){1, 25};
        this->context->gop_size = 10;
        this->context->max_b_frames = 1;
        this->context->pix_fmt = PIX_FMT_YUV420P;
        if(avcodec_open2(this->context, this->codec, NULL) < 0)
        {
            throw std::runtime_error("Could not open codec");
        }
        if(!this->outputFile)
        {
            throw std::runtime_error("Could not open video output file");
        }
        this->picture->data[0] = this->pictureBuffer;
        this->picture->data[1] = this->picture->data[0] + imgBufferSize;
        this->picture->data[2] = this->picture->data[1] + imgBufferSize / 4;
        this->picture->linesize[0] = this->imgWidth;
        this->picture->linesize[1] = this->imgWidth / 2;
        this->picture->linesize[2] = this->imgWidth / 2;
    }
    void insertFrame(cv::Mat1b& img)
    {
        fflush(stdout);
        /* Y */
        for(int y=0; y < this->context->height; y++)
        {
            for(int x=0; x < this->context->width; x++)
            {
                this->picture->data[0][y * picture->linesize[0] + x] = img.at<uchar>(y,x);
            }
        }
        /* Cb and Cr */
        for(int y=0; y < this->context->height/2; y++)
        {
            for(int x=0; x < this->context->width/2; x++)
            {
                this->picture->data[1][y * this->picture->linesize[1] + x] = 128;
                this->picture->data[2][y * this->picture->linesize[2] + x] = 128;
            }
        }
        this->outputSize = avcodec_encode_video(this->context, this->outputBuffer, this->outputBufferSize, this->picture);
        fwrite(this->outputBuffer, 1, outputSize, this->outputFile);
    }
    ~AVConvVideoMaker()
    {
        this->outputBuffer[0] = 0x00;
        this->outputBuffer[1] = 0x00;
        this->outputBuffer[2] = 0x01;
        this->outputBuffer[3] = 0xb7;
        fwrite(this->outputBuffer, 1, 4, this->outputFile);
        fclose(this->outputFile);
        avcodec_close(this->context);
        av_free(this->context);
        av_free(this->picture);
        delete outputBuffer;
        delete pictureBuffer;
    }
};

要在Ubuntu 16.04中编译此内容,您必须链接:

g++ --std=c++11 main.cpp -lopencv_core -lopencv_highgui -lavutil -lavcodec

最新更新