简单介绍下FFmpeg解码的流程,具体可以参考雷神的博客:点击打开链接

    

    声明变量:

AVCodec *pCodec;
AVCodecContext *pCodecCtx = NULL;
AVPacket packet;
AVFrame	*pFrame;
AVCodecID codec_id = AV_CODEC_ID_H264;

    AVCodec是包含了编解码器信息的结构体;

    AVCodecContext里包含的信息很多,像编解码器的类型,附加信息,视频宽高,参考帧等等;

    AVPacket存储压缩编码数据相关信息;

    AVFrame存储着码流数据,解码后的原始数据都保存在这里;

    AVCodecID指定码流对应标准;


    打开文件:

FILE *fp_in = fopen("test.h264", "rb");
if (!fp_in)
{
	printf("Could not open input stream\n");
	return -1;
}


    首先要注册解码器及各种组件,这样才能进行解码:

av_register_all();

    通过上面的函数注册好后,查找解码器:

pCodec = avcodec_find_decoder(codec_id);
    为AVCodecContext分配存储空间:
pCodecCtx = avcodec_alloc_context3(pCodec); 
    打开解码器:
avcodec_open2(pCodecCtx, pCodec, NULL);
    为解码后的数据分配内存空间,且初始化packet:   
pFrame = av_frame_alloc();
av_init_packet(&packet);
   

    准备工作完成后,我们读取本地的H264文件,读取的数据交给函数av_parser_parse2()解析,解析完成得到一帧数据即可交给解码器进行解码。

    av_parser_parse2()的原型和各参数:

int av_parser_parse2(AVCodecParserContext *s,AVCodecContext *avctx,  uint8_t **poutbuf, int *poutbuf_size,  const uint8_t *buf, int buf_size,  int64_t pts, int64_t dts,  int64_t pos);  

    第一个参数:结构体AVCodecParserContext;第二个参数:结构体AVCodecContext;第三个参数:初始化后的packet.data;第四个参数:初始化后的packet.size;第五个参数:一次接收的数据包;第六个参数:接收数据包的长度;第七个参数:pts;第八个参数:dts;第九个参数:pos;

    解码函数是avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet),可以解码一帧数据,输入压缩编码数据的结构体AVPacket,输出解码后的结构体AVFrame。解码成功时,got_picture为非零值。

    代码如下:

while (1)
{
	cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
	cur_ptr = in_buffer;
	while (cur_size > 0)
	{
		int len = av_parser_parse2(pCodecParserCtx, pCodecCtx, &packet.data, &packet.size, cur_ptr, cur_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
		cur_ptr += len;
		cur_size -= len;

		ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);  
		if (ret < 0)
		{
			printf("Decode Error\n");
			return ret;
		}
		if (got_picture)
		{
			printf("Succeed to decode 1 frame!\n");
		}
	}
}
    

    收尾工作,释放我们分配的空间,关掉打开的解码器:

fclose(fp_in);
fclose(fp_out);
av_parser_close(pCodecParserCtx);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);