FFMPEG实现H264的解码(从源代码角度)
农历2014年底了,将前段时间工作中研究的FFMPEG解码H264流程在此做一下整理,也算作年终技术总结了!
H264解码原理:
H264的原理参考另一篇博文 http://blog.csdn.net/rootusers/article/details/43563133
H264分为NAL(网络抽象层)和VCL(视频编码层)
解码器的总框架:
解码器的流程为:将NAL数据位流输入到H264的解码器中,熵解码模块解码后输出量化系数X;系数经过反量化和反变换得到残差数据R;解码器使用从码流中解码的头信息生成预测块Pred,然后Pred与残差R求和得到块数据dF;每个块dF通过去除块效应的滤波得到解码图像的重建块F。
FFMPEG源代码解析:
FFMPEG中对于codec的注册和初始化在另一篇博文中有介绍,在这里不在涉及了:av_register_all。
FFMPEG处理h264的模块主要是在h264.c中。
解码的主函数为:
- int main(){
- FILE * inp_file;
- FILE * out_file;
- int i;
- int nalLen; /*NAL 长度*/
- unsigned char* Buf; /*H.264码流*/
- int got_picture; /*是否解码一帧图像*/
- int consumed_bytes; /*解码器消耗的码流长度*/
- int cnt=0;
- AVCodec *codec; /* 编解码CODEC*/
- AVCodecContext *c; /* 编解码CODEC context*/
- AVFrame *picture; /* 解码后的图像*/
- /*输出和输出的文件*/
- inp_file = fopen("test.h264", "rb");
- out_file = fopen("test.yuv", "wb");
- nalLen = 0;
- /*分配内存,并初始化为0*/
- Buf = (unsigned char*)calloc ( 500*1024, sizeof(char));
- /*CODEC的初始化,初始化一些常量表*/
- avcodec_init();
- /*注册CODEC*/
- avcodec_register_all();
- /*查找 H264 CODEC*/
- codec = avcodec_find_decoder(CODEC_ID_H264);
- if (!codec) return 0;
- /*初始化CODEC的默认参数*/
- c = avcodec_alloc_context();
- if(!c) return 0;
- /*1. 打开CODEC,这里初始化H.264解码器,调用decode_init本地函数*/
- if (avcodec_open(c, codec) < 0) return 0;
- /*为AVFrame申请空间,并清零*/
- picture = avcodec_alloc_frame();
- if(!picture) return 0;
- /*循环解码*/
- while(!feof(inp_file)) {
- /*从码流中获得一个NAL包*/
- nalLen = getNextNal(inp_file, Buf);
- /*2. NAL解码,调用decode_frame本地函数*/
- consumed_bytes= avcodec_decode_video(c, picture, &got_picture, Buf, nalLen);
- cnt++;
- /*输出当前的解码信息*/
- printf("No:=%4d, length=%4d\n",cnt,consumed_bytes);
- /*返回<0 表示解码数据头,返回>0,表示解码一帧图像*/
- if(consumed_bytes > 0)
- {
- /*从二维空间中提取解码后的图像*/
- for(i=0; i<c->height; i++)
- fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, out_file);
- for(i=0; i<c->height/2; i++)
- fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, out_file);
- for(i=0; i<c->height/2; i++)
- fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, out_file);
- }
- }
- /*关闭文件*/
- if(inp_file) fclose(inp_file);
- if(out_file) fclose(out_file);
- /*3. 关闭CODEC,释放资源,调用decode_end本地函数*/
- if(c) {
- avcodec_close(c);
- av_free(c);
- c = NULL;
- }
- /*释放AVFrame空间*/
- if(picture) {
- av_free(picture);
- picture = NULL;
- }
- /*释放内存*/
- if(Buf) {
- free(Buf);
- Buf = NULL;
- }
- return 0;
- }
本工程是参考的网上的很多资料来改写的,因为开源,我们才会变的更优秀,希望所有的开发者都积极分享自己的音视频开发经验。向开源项目致敬。
源代码下载:
http://download.csdn.net/detail/rootusers/8428977
from:http://blog.csdn.net/rootusers/article/details/43560913
FFMPEG实现H264的解码(从源代码角度)的更多相关文章
- 用ffmpeg把H264数据流解码成YUV420P
在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉.不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成 ...
- 利用ffmpeg将H264流 解码为RGB
利用H264解码分为几个步骤: 注意一点在添加头文件的时候要添加extern "C",不然会出现错误 [cpp] view plaincopy extern "C&quo ...
- 让WebRTC支持H264编解码
近期实验了下怎样让WebRTC支持H264编码.记录下,供有须要的人參考. 说明一下,我是在 Ubuntu Server 14.04 下编译的 WebRTC ,使用 native(C++) api 开 ...
- [ffmpeg] h264并行解码
ffmpeg中的并行解码分为两种: Frame-level Parallelism Slice-level Parallelism Frame-level Parallelism 帧间依赖 我们之前讨 ...
- ffmpeg H264 编解码配置
ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...
- FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库
FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...
- 【视频开发】 ffmpeg支持的硬解码接口
To enable DXVA2, use the --enable-dxva2 ffmpeg configure switch. To test decoding, use the following ...
- 【FFMPEG】【ARM-Linux开发】fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完)
fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完) ffmpeg安装第三方编码器(encoder)库 关键词:ffmpeg.编码h264.第三方encoder 安装好了ff ...
- FFmpeg源码结构图 - 解码
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
随机推荐
- Centos命令行报bash:.....:command not found的解决办法
命令行报bash:.....:command not found的解决办法(几乎所有命令) 命令行输入命令执行后报“bash:....:command not found”这是由于系统PATH设置 ...
- 源码安装Apache,报错:Cannot use an external APR with the bundled APR-util
一般在第一次源码安装是没有问题的,在版本变化情况下在次源码安装可能会遇到此问题: apache2.0.x与apache2.2.x在apr有很大区别,前者为依赖公用apr,后者依赖于自身的apr.一般前 ...
- 纯JS实现动态时间
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Android设备各种使用尺寸整理
// 获取屏幕的宽度.高度 Display defDip = getWindowManager().getDefaultDisplay(); int disWidth = defDip.getWidt ...
- Python赋值原理:Python无变量,万物皆对象
有几个和以前的常见语言,比如c语言不同 改变变量数据不覆盖原来的 name = '苍老师' print(id(name)) name = '志玲' print(id(name)) 运行结果 73955 ...
- DAS、NAS、SAN
目前磁盘存储市场上,存储分类(如下表一)根据服务器类型分为:封闭系统的存储和开放系统的存储,封闭系统主要指大型机,AS400等服务器, 开放系统指基于包括Windows.UNIX.Linux等操作系统 ...
- python利用wxpy监控微信公众号
此次利用wxpy可以进行微信公众号的消息推送监测(代码超级简单),这样能进行实时获取链接.但是不光会抓到公众号的消息,好友的消息也会抓到(以后会完善的,毕竟现在能用了,而且做项目的微信号肯定是没有好友 ...
- LeetCode:长度最小的子数组【209】
LeetCode:长度最小的子数组[209] 题目描述 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 ...
- 每天一个Linux命令(28)df命令
报告文件系统磁盘空间的使用情况.获取硬盘被占用了多少空间,目前还剩下多少空间等信息. (1)用法: 用法: df [选项] [文件] (2)功能: 功能: 显示 ...
- oracle 序列 + 触发器 实现 ID自动增长
1.创建序列 create sequence emp_sequence increment by ----每次增加几个 minvalue ----最小值为1 nomaxvalue----不限制最大值 ...