2016-06-20 6 views
0

저는 OpenCV로 캡쳐/생성 된 프레임에서 avconv 라이브러리를 사용하여 C++ 응용 프로그램에서 빠르고 안정적인 그레이 스케일 비디오를 만드는 방법을 찾고있었습니다.avconv로 그레이 스케일 비디오를 만드는 방법은 무엇입니까?

OpenCV는 비디오를 제작하는 내부 방법이 있지만 일부 인코딩 성능과 옵션 제한이 있음을 알고 있습니다.

그래서이 방법으로이 작업을 수행하기위한 옵션이 무엇인지 알고 싶습니다. 내 요구에 부합이 작업, 내가 찾은 옵션 중 하나를 수행하기위한

답변

0

는 다음 클래스입니다 : 우분투 16.04에서 이것을 컴파일

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; 
    } 

}; 

, 당신은 함께 연결해야 :

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