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();
return false;
}
// 申请一个AVCodecContext结构体,注意使用avcodec_free_context()函数释放
m_pVideoEncoderContext = avcodec_alloc_context3(m_pVideoEncoder);
if(!m_pVideoEncoderContext)
{
assert();
return false;
} // 对m_pVideoEncoderContext设置一些参数
m_pVideoEncoderContext->width = frameWidth;
m_pVideoEncoderContext->height = frameHeight;
  // ......
  // 初始化AVCodecContext
int err = avcodec_open2(m_pVideoEncoderContext, m_pVideoEncoder,NULL);
if ( err < )
{
assert();
char errorStr[];
av_strerror(err,errorStr,); 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();
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,,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 < )
     { 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 < )
{
return false;
}

2.解码

    av_init_packet(&m_recvPacket);
m_recvPacket.size = videoPacket.length;
m_recvPacket.data = videoPacket.pData; int got_frame = ;
while (m_recvPacket.size)
{
int len = avcodec_decode_video2(m_pVideoDecoderContext, m_pYUVFrame, &got_frame, &m_recvPacket);
if (len < )
{
return false;
}
if (m_recvPacket.data)
{
m_recvPacket.size -= len;
m_recvPacket.data += len;
}
} if(got_frame == )
{
return false;
}
  // 将m_pYUVFrame转换为RGBFrame用于显示
  // ......
上一篇:VideoToolbox硬件编解码H.264视频流错误码


下一篇:【并行计算与CUDA开发】英伟达硬件加速编解码