农历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中。

解码的主函数为:

主函数中的avcodec_init(),avcodec_register_all()等函数都是直接拿去的FFMPGE的源代码实现的,这个工程对于理解FFMPEG的解码流程有很大的作用。
  1. int main(){
  2. FILE * inp_file;
  3. FILE * out_file;
  4. int i;
  5. int nalLen;         /*NAL 长度*/
  6. unsigned char* Buf; /*H.264码流*/
  7. int  got_picture;       /*是否解码一帧图像*/
  8. int  consumed_bytes; /*解码器消耗的码流长度*/
  9. int cnt=0;
  10. AVCodec *codec;           /* 编解码CODEC*/
  11. AVCodecContext *c;        /* 编解码CODEC context*/
  12. AVFrame *picture;         /* 解码后的图像*/
  13. /*输出和输出的文件*/
  14. inp_file = fopen("test.h264", "rb");
  15. out_file = fopen("test.yuv", "wb");
  16. nalLen = 0;
  17. /*分配内存,并初始化为0*/
  18. Buf = (unsigned char*)calloc ( 500*1024, sizeof(char));
  19. /*CODEC的初始化,初始化一些常量表*/
  20. avcodec_init();
  21. /*注册CODEC*/
  22. avcodec_register_all();
  23. /*查找 H264 CODEC*/
  24. codec = avcodec_find_decoder(CODEC_ID_H264);
  25. if (!codec)  return 0;
  26. /*初始化CODEC的默认参数*/
  27. c = avcodec_alloc_context();
  28. if(!c)  return 0;
  29. /*1. 打开CODEC,这里初始化H.264解码器,调用decode_init本地函数*/
  30. if (avcodec_open(c, codec) < 0)  return 0;
  31. /*为AVFrame申请空间,并清零*/
  32. picture   = avcodec_alloc_frame();
  33. if(!picture)    return 0;
  34. /*循环解码*/
  35. while(!feof(inp_file))  {
  36. /*从码流中获得一个NAL包*/
  37. nalLen = getNextNal(inp_file, Buf);
  38. /*2. NAL解码,调用decode_frame本地函数*/
  39. consumed_bytes= avcodec_decode_video(c, picture, &got_picture, Buf, nalLen);
  40. cnt++;
  41. /*输出当前的解码信息*/
  42. printf("No:=%4d, length=%4d\n",cnt,consumed_bytes);
  43. /*返回<0 表示解码数据头,返回>0,表示解码一帧图像*/
  44. if(consumed_bytes > 0)
  45. {
  46. /*从二维空间中提取解码后的图像*/
  47. for(i=0; i<c->height; i++)
  48. fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, out_file);
  49. for(i=0; i<c->height/2; i++)
  50. fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, out_file);
  51. for(i=0; i<c->height/2; i++)
  52. fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, out_file);
  53. }
  54. }
  55. /*关闭文件*/
  56. if(inp_file)    fclose(inp_file);
  57. if(out_file)    fclose(out_file);
  58. /*3. 关闭CODEC,释放资源,调用decode_end本地函数*/
  59. if(c) {
  60. avcodec_close(c);
  61. av_free(c);
  62. c = NULL;
  63. }
  64. /*释放AVFrame空间*/
  65. if(picture) {
  66. av_free(picture);
  67. picture = NULL;
  68. }
  69. /*释放内存*/
  70. if(Buf) {
  71. free(Buf);
  72. Buf = NULL;
  73. }
  74. return 0;
  75. }

本工程是参考的网上的很多资料来改写的,因为开源,我们才会变的更优秀,希望所有的开发者都积极分享自己的音视频开发经验。向开源项目致敬。

源代码下载:

http://download.csdn.net/detail/rootusers/8428977

from:http://blog.csdn.net/rootusers/article/details/43560913

FFMPEG实现H264的解码(从源代码角度)的更多相关文章

  1. 用ffmpeg把H264数据流解码成YUV420P

    在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉.不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成 ...

  2. 利用ffmpeg将H264流 解码为RGB

    利用H264解码分为几个步骤: 注意一点在添加头文件的时候要添加extern "C",不然会出现错误 [cpp] view plaincopy extern "C&quo ...

  3. 让WebRTC支持H264编解码

    近期实验了下怎样让WebRTC支持H264编码.记录下,供有须要的人參考. 说明一下,我是在 Ubuntu Server 14.04 下编译的 WebRTC ,使用 native(C++) api 开 ...

  4. [ffmpeg] h264并行解码

    ffmpeg中的并行解码分为两种: Frame-level Parallelism Slice-level Parallelism Frame-level Parallelism 帧间依赖 我们之前讨 ...

  5. ffmpeg H264 编解码配置

    ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...

  6. FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库

    FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...

  7. 【视频开发】 ffmpeg支持的硬解码接口

    To enable DXVA2, use the --enable-dxva2 ffmpeg configure switch. To test decoding, use the following ...

  8. 【FFMPEG】【ARM-Linux开发】fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完)

    fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完) ffmpeg安装第三方编码器(encoder)库 关键词:ffmpeg.编码h264.第三方encoder 安装好了ff ...

  9. FFmpeg源码结构图 - 解码

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

随机推荐

  1. ios 手势返回<1>

    极其简单取巧的方法 iOS7之后是有侧滑返回手势功能的.注意,也就是说系统已经定义了一种手势,并且给这个手势已经添加了一个触发方法(重点).但是,系统的这个手势的触发条件是必须从屏幕左边缘开始滑动.我 ...

  2. hdu3579(线性同余方程组)

    Hello Kiki Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. 【BZOJ3230】相似子串 后缀数组+二分+RMQ

    [BZOJ3230]相似子串 Description Input 输入第1行,包含3个整数N,Q.Q代表询问组数.第2行是字符串S.接下来Q行,每行两个整数i和j.(1≤i≤j). Output 输出 ...

  4. 关于KMP算法的感想

    今天,看了KMP,首先是在网上看的,看了很久没看懂,有很多思想,很多next的推导,就相当于很多的版本,后来,去看了<<大话数据结构>>这本书,才看懂,这KMP的神奇之处,这本 ...

  5. ArcGIS Scalebar 比例尺

    说明.这篇博文的示例代码 地图充满body arcgis api for javascript iis怎么离线部署 请参考我前面的博文 1.运行效果 3.HTML代码 <!DOCTYPE htm ...

  6. Java NIO Buffer(netty源码死磕1.2)

    [基础篇]netty源码死磕1.2:  NIO Buffer 1. Java NIO Buffer Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区.Buffer缓冲区本质上是一块可 ...

  7. Future Promise 模式(netty源码9)

    netty源码死磕9  Future Promise 模式详解 1. Future/Promise 模式 1.1. ChannelFuture的由来 由于Netty中的Handler 处理都是异步IO ...

  8. 最简单的php验证码

    <?php session_start(); // Settings: You can customize the captcha here $image_width = 120; $image ...

  9. Bootstrap学习-导航条-分页导航

    1.导航条基础 导航条(navbar)和上一节介绍的导航(nav),就相差一个字,多了一个“条”字.其实在Bootstrap框架中他们还是明显的区别.在导航条(navbar)中有一个背景色.而且导航条 ...

  10. java面试之数据库面试知识点【转】

    1. 主键 超键 候选键 外键 主 键: 数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合.一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null). 超 键: 在关系中 ...