zoukankan      html  css  js  c++  java
  • 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中。

    解码的主函数为:

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

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

    源代码下载:

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

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

  • 相关阅读:
    给tkinter文本框添加右键菜单
    Python读取图片尺寸、图片格式
    sublime text 3 build 3143 安装详解
    一种使用pyinstaller时图标问题解决方案
    讠己 —— 冫欠 自 云力 扌仓 石马
    python桌面端开发手记(序列化、压缩包、加密、图形界面GUI)
    Spark安装过程纪录
    Zookeeper与HBse安装过程纪录
    搭建分布式Hadoop的填坑纪录
    使用几种常见分类器预测海难幸存者(二分类)
  • 原文地址:https://www.cnblogs.com/lidabo/p/7327053.html
Copyright © 2011-2022 走看看