zoukankan      html  css  js  c++  java
  • 用ffmpeg把H264数据流解码成YUV420P

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

    首先是初始化一些参数

    [cpp] view plaincopy
     
     
    1. //下面初始化h264解码库  
    2. avcodec_init();  
    3. av_register_all();  
    4.   
    5. AVFrame *pFrame_ = NULL;  
    6.   
    7. AVCodecContext *codec_ = avcodec_alloc_context();  
    8.   
    9. /* find the video encoder */  
    10. AVCodec *videoCodec = avcodec_find_decoder(CODEC_ID_H264);  
    11.   
    12. if (!videoCodec)   
    13. {  
    14.     cout << "codec not found!" << endl;  
    15.     return -1;  
    16. }  
    17.   
    18. //初始化参数,下面的参数应该由具体的业务决定  
    19. codec_->time_base.num = 1;  
    20. codec_->frame_number = 1; //每包一个视频帧  
    21. codec_->codec_type = AVMEDIA_TYPE_VIDEO;  
    22. codec_->bit_rate = 0;  
    23. codec_->time_base.den = 30;//帧率  
    24. codec_->width = 1280;//视频宽  
    25. codec_->height = 720;//视频高  
    26.   
    27. if(avcodec_open(codec_, videoCodec) >= 0)  
    28.     pFrame_ = avcodec_alloc_frame();// Allocate video frame  
    29. else  
    30.     return -1;  


    下面是具体的解码的代码

    [cpp] view plaincopy
     
     
    1. AVPacket packet = {0};  
    2. int frameFinished = dwBufsize;//这个是随便填入数字,没什么作用  
    3.   
    4. packet.data = pBuffer;//这里填入一个指向完整H264数据帧的指针  
    5. packet.size = dwBufsize;//这个填入H264数据帧的大小  
    6.   
    7. //下面开始真正的解码  
    8. avcodec_decode_video2(codec_, pFrame_, &frameFinished, &packet);  
    9. if(frameFinished)//成功解码  
    10. {  
    11.     int picSize = codec_->height * codec_->width;  
    12.     int newSize = picSize * 1.5;  
    13.   
    14.     //申请内存  
    15.     unsigned char *buf = new unsigned char[newSize];  
    16.   
    17.     int height = p->codec->height;  
    18.     int width = p->codec->width;  
    19.   
    20.   
    21.     //写入数据  
    22.     int a=0,i;   
    23.     for (i=0; i<height; i++)   
    24.     {   
    25.         memcpy(buf+a,pFrame_->data[0] + i * pFrame_->linesize[0], width);   
    26.         a+=width;   
    27.     }   
    28.     for (i=0; i<height/2; i++)   
    29.     {   
    30.         memcpy(buf+a,pFrame_->data[1] + i * pFrame_->linesize[1], width/2);   
    31.         a+=width/2;   
    32.     }   
    33.     for (i=0; i<height/2; i++)   
    34.     {   
    35.         memcpy(buf+a,pFrame_->data[2] + i * pFrame_->linesize[2], width/2);   
    36.         a+=width/2;   
    37.     }  
    38.   
    39.     //===============  
    40.     //到这里,buf里面已经是yuv420p的数据了,可以对它做任何的处理拉!  
    41.     //===============  
    42.     delete [] buf;  
    43. }  



    不过我发现这样解码很耗cpu资源,我的Core2  E7400 2.8G的处理器,解码1920X1080分辨率每秒30帧的视频时,CPU占用率能用到差不多50%。

     

    PS:原来avcodec_decode_video2这个函数会修改codec_里面的参数的,也就是说如果原来里面填的分别率是1280X720,运行avcodec_decode_video2后codec_里面会变成实际视频的分辨率。

  • 相关阅读:
    ASP.NET Core 问题排查:Request.EnableRewind 后第一次读取不到 Request.Body
    解决 AutoMapper ProjectTo 不起作用的问题
    解决 ASP.NET Core 自定义错误页面对 Middleware 异常无效的问题
    ASP.NET Core 从 gitlab-ci 环境变量读取配置
    终于解决 xUnit.net 测试中无法输出到控制台的问题
    ASP.NET Core 新建线程中使用依赖注入的问题
    前端回顾:2016年 JavaScript 之星
    前端工程师和设计师必读文章推荐【系列三十五】
    AsciiMorph
    Notyf
  • 原文地址:https://www.cnblogs.com/lidabo/p/4582387.html
Copyright © 2011-2022 走看看