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用于显示
// ......