• 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 "); 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用于显示
      // ......
  • 相关阅读:
    HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)
    HDU 1241 Oil Deposits DFS(深度优先搜索) 和 BFS(广度优先搜索)
    邮件推广工具
    aix-syslog
    能量点
    知识picture
    C中运算符
    stdio.h头文件中申明的基本函数
    字符串
    指针字符串
  • 原文地址:https://www.cnblogs.com/jiayayao/p/6506212.html
Copyright © 2020-2023  润新知