FFMpeg筆記(二) 使用FFmpeg對視頻進行編解碼的一般流程


 1. 編碼:

1.對編碼資源的初始化

   AVCodec*                m_pVideoEncoder;// 特定編碼器的參數信息
    AVCodecContext*         m_pVideoEncoderContext;// 設置的編碼參數信息
    AVFrame*                m_YUV_Frame;// RGB轉換為YUV數據幀以減少傳輸數據量,減少網絡帶寬占用
    AVFrame*                m_RGB_Frame;// 獲取到的數據幀
    SwsContext*             m_pSwsc;// 保存由YUV轉換為RGB的轉換參數的結構體
    // 根據給定的編碼器ID找到注冊過的編碼器
    m_pVideoEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);  
    if (!m_pVideoEncoder) 
    {
        assert(0); 
        return false;
    }  
    // 申請一個AVCodecContext結構體,注意使用avcodec_free_context()函數釋放
    m_pVideoEncoderContext = avcodec_alloc_context3(m_pVideoEncoder);  
    if(!m_pVideoEncoderContext)
    {
        assert(0);
        return false;
    }

    // 對m_pVideoEncoderContext設置一些參數
    m_pVideoEncoderContext->width = frameWidth;
    m_pVideoEncoderContext->height = frameHeight;
  // ......
  
// 初始化AVCodecContext int err = avcodec_open2(m_pVideoEncoderContext, m_pVideoEncoder,NULL); if ( err < 0) { assert(0); char errorStr[256]; av_strerror(err,errorStr,256); return false; } // 申請AVFrame m_YUV_Frame = av_frame_alloc();   // 獲取保留圖像拉伸參數的結構體 m_pSwsc = sws_getContext(frameWidth,frameHeight,g_Format,frameWidth,frameHeight,AV_PIX_FMT_YUV420P,SWS_ALGORITHM,NULL,NULL,NULL); if (!m_pSwsc) { assert(0); return false; }
m_RGB_Frame
= av_frame_alloc();

2.編碼

        // 將原始數據(RGB格式的)填充到一個RGB的AVFrame中
        avpicture_fill((AVPicture*)m_RGB_Frame, (uint8_t*)rawVideo, g_Format, m_nLastFrameWidth, m_nLastFrameHeight);
        // 將RGB格式的AVFrame轉換為YUV格式,以降低傳輸數據的總量
        sws_scale(m_pSwsc,m_RGB_Frame->data,m_RGB_Frame->linesize,0,m_pVideoEncoderContext->height,m_YUV_Frame->data,m_YUV_Frame->linesize);

        AVPacket packet;
        av_init_packet(&packet);
     int bOutPacketNonEmpty = 0;
        int nRet = avcodec_encode_video2(m_pVideoEncoderContext, &packet, m_YUV_Frame, &bOutPacketNonEmpty); 
     if(nRet < 0)
     {
return false; }
     // 將AVPacket傳輸
     // ......

2. 解碼:

1.對解碼資源的初始化

    AVCodec*            m_pVideoDecoder;  
    AVCodecContext*     m_pVideoDecoderContext;
    
    AVPacket            m_recvPacket;
    AVFrame*            m_pYUVFrame;

    SwsContext*         m_pSwsc;// 保存由YUV轉換為RGB的轉換參數的結構體
    AVFrame*            m_pRGBFrame;// 用於顯示
    // 根據數據包的編碼格式,找到對應的解碼器
   m_pVideoDecoder = avcodec_find_decoder((AVCodecID)codecid); if (!m_pVideoDecoder) { fprintf(stderr, "Codec not found\n"); return false; } m_pVideoDecoderContext = avcodec_alloc_context3(m_pVideoDecoder); int ret = avcodec_open2( m_pVideoDecoderContext, m_pVideoDecoder, NULL); if(ret < 0) { return false; }

2.解碼

    av_init_packet(&m_recvPacket);
    m_recvPacket.size = videoPacket.length;
    m_recvPacket.data = videoPacket.pData;

    int got_frame = 0;
    while (m_recvPacket.size)
    {
        int len = avcodec_decode_video2(m_pVideoDecoderContext, m_pYUVFrame, &got_frame, &m_recvPacket);
        if (len < 0) 
        {
return false;
        }
        if (m_recvPacket.data) 
        {
            m_recvPacket.size -= len;
            m_recvPacket.data += len;
        }
    }
    
    if(got_frame == 0)
    {
        return false;
    }
  // 將
m_pYUVFrame轉換為RGBFrame用於顯示
  // ......

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM