利用H264解码分为几个步骤:

注意一点在添加头文件的时候要添加extern "C",不然会出现错误

  1. extern "C"
  2. {
  3. #include <avcodec.h>
  4. #include <avformat.h>
  5. #include <avutil.h>
  6. #include <swscale.h>
  7. };

这里申明了几个全局变量

  1. AVCodec         *pCodec = NULL;
  2. AVCodecContext  *pCodecCtx = NULL;
  3. SwsContext      *img_convert_ctx = NULL;
  4. AVFrame         *pFrame = NULL;
  5. AVFrame         *pFrameRGB = NULL;

1. 初始化

  1. int H264_Init(void)
  2. {
  3. /* must be called before using avcodec lib*/
  4. avcodec_init();
  5. /* register all the codecs */
  6. avcodec_register_all();
  7. /* find the h264 video decoder */
  8. pCodec = avcodec_find_decoder(CODEC_ID_H264);
  9. if (!pCodec) {
  10. fprintf(stderr, "codec not found\n");
  11. }
  12. pCodecCtx = avcodec_alloc_context();
  13. /* open the coderc */
  14. if (avcodec_open(pCodecCtx, pCodec) < 0) {
  15. fprintf(stderr, "could not open codec\n");
  16. }
  17. // Allocate video frame
  18. pFrame = avcodec_alloc_frame();
  19. if(pFrame == NULL)
  20. return -1;
  21. // Allocate an AVFrame structure
  22. pFrameRGB=avcodec_alloc_frame();
  23. if(pFrameRGB == NULL)
  24. return -1;
  25. return 0;
  26. }

在最早使用的时候没有使用全局变量,初始化中也就只有init和regisger这两个函数,而这样做的下场是,非关键帧全部无法解码,只有关键帧才有办法解码。

2. 解码

解码的时候avcodec_decode_video函数是进行解码操作,在外部定义outputbuf的大小时,pixes*3,outsize是返回的outputbuf的size,值也是pixes*3。

在解码的时候这几句话的意义是将YUV420P的数据倒置。在原先使用中,发现解出来的图像居然是中心旋转图,后面在网上找了些办法,觉得这个比较实用。解码实时是很重要的,图像转化完之后也可以讲RGB图再次转化,那样也能成为一个正的图,但是那样效率就明显低了。

  1. pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);
  2. pFrame->linesize[0] *= -1;
  3. pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;
  4. pFrame->linesize[1] *= -1;
  5. pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;
  6. pFrame->linesize[2] *= -1;
  1. int H264_2_RGB(unsigned char *inputbuf, int frame_size, unsigned char *outputbuf, unsigned int*outsize)
  2. {
  3. int             decode_size;
  4. int             numBytes;
  5. int             av_result;
  6. uint8_t         *buffer = NULL;
  7. printf("Video decoding\n");
  8. av_result = avcodec_decode_video(pCodecCtx, pFrame, &decode_size, inputbuf, frame_size);
  9. if (av_result < 0)
  10. {
  11. fprintf(stderr, "decode failed: inputbuf = 0x%x , input_framesize = %d\n", inputbuf, frame_size);
  12. return -1;
  13. }
  14. // Determine required buffer size and allocate buffer
  15. numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,
  16. pCodecCtx->height);
  17. buffer = (uint8_t*)malloc(numBytes * sizeof(uint8_t));
  18. // Assign appropriate parts of buffer to image planes in pFrameRGB
  19. avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,
  20. pCodecCtx->width, pCodecCtx->height);
  21. img_convert_ctx = sws_getCachedContext(img_convert_ctx,pCodecCtx->width,pCodecCtx->height,
  22. //PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,
  23. pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,PIX_FMT_RGB24 ,
  24. SWS_X ,NULL,NULL,NULL) ;
  25. if (img_convert_ctx == NULL)
  26. {
  27. printf("can't init convert context!\n") ;
  28. return -1;
  29. }
  30. pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height-1);
  31. pFrame->linesize[0] *= -1;
  32. pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height/2 - 1);;
  33. pFrame->linesize[1] *= -1;
  34. pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height/2 - 1);;
  35. pFrame->linesize[2] *= -1;
  36. sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
  37. 0, 0 - pCodecCtx->width, pFrameRGB->data, pFrameRGB->linesize);
  38. if (decode_size)
  39. {
  40. *outsize = pCodecCtx->width * pCodecCtx->height * 3;
  41. memcpy(outputbuf, pFrameRGB->data[0], *outsize);
  42. }
  43. free(buffer);
  44. return 0;
  45. }
//解码yuv 修改 PIX_FMT_YUV420P
memcpy(outputbuf, pFrameRGB->data[2], 720*576/4);
			memcpy(outputbuf, pFrameRGB->data[1], 720*576/4);
			memcpy(outputbuf, pFrameRGB->data[0], 720*576);

3. 释放资源

资源的回收。

  1. void H264_Release(void)
  2. {
  3. avcodec_close(pCodecCtx);
  4. av_free(pCodecCtx);
  5. av_free(pFrame);
  6. av_free(pFrameRGB);
  7. }

利用ffmpeg将H264流 解码为RGB的更多相关文章

  1. FFMPEG实现H264的解码(从源代码角度)

    农历2014年底了,将前段时间工作中研究的FFMPEG解码H264流程在此做一下整理,也算作年终技术总结了! H264解码原理: H264的原理参考另一篇博文 http://blog.csdn.net ...

  2. 利用ffmpeg将H264解码为RGB

    因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...

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

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

  4. 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中

    既然已经可以通过 RTSP 获取h264 裸流了.那么通过 FFmpeg 将其保存到文件中怎么做呢? 一.首先RTSP获取 h264 裸流 我们上面两篇文章主要讲的是通过 rtsp://Your ip ...

  5. [ffmpeg] h264并行解码

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

  6. VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时

    之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...

  7. ps流提取H264并解码播放

    因为需要从海康ps流中提取H264数据并进行解码播放,才有了这篇文章.因为是视频编解码领域的纯入门新手,个别理解或者方法有误,需要自行判断,不过相关方法已经测试通过,对于 像我这样的新手还是有一定的借 ...

  8. ffmpeg H264 编解码配置

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

  9. 【VS开发】【视频开发】利用ffmpeg+opencv实现画中画

    需求:把两路视频合成一路,即一个画面同时显示两路视频,其中一路缩小成小视频叠在大视频上面,和电视机的画中画效果类似. 思路:用h264编码的视频举例,文件中存储的es流是h264,经过解码成yuv,y ...

随机推荐

  1. 包装类和基本类型区别?(integer和int取值范围一样大)

    1.声明方式不同,int不需要new .Integer需要new 2.性质上根本不同点:int是基本数据类型.Integer是引用数据类型,它有自己的属性,方法 3.存储位置和方式不同:int是存储在 ...

  2. easyUI前后台分页代码实现

    一.后台分页 (1)客户端代码: var dg = $('#table'); var opts = dg.datagrid('options'); var pager = dg.datagrid('g ...

  3. JAVA设计模式---装饰者模式

    写在前面的话: 该模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案.装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的 ...

  4. 手把手的SpringBoot教程,SpringBoot创建web项目(一)

    1.引子 大家好,在接下里的半个多小时,我会给大家详细的介绍SpringBoot的基本使用,相信学完这门课程以后,你会对SpringBoot有一个清晰的认识,并且能够运用这门比较新颖的技术开发一些小程 ...

  5. Log4Net记录到MySql

    1.新建控制台程序. 2.添加Log4Net nuget 3.添加MySql 引用 4.添加配置文件如下: <?xml version="1.0"?> <conf ...

  6. Java程序只运行一个实例[转]

    如果希望你的Java程序只能存在一个实例,可以参考下面的用法. 原文链接:http://blog.csdn.net/yaerfeng/article/details/7264729 Java没有提供这 ...

  7. 夏令营讲课内容整理 Day 5.

    DP专场.. 动态规划是运筹学的一个分支, 求解决策过程最优化的数学方法. 我们一般把动态规划简称为DP(Dynamic Programming)   1.动态规划的背包问题 有一个容量为m的背包,有 ...

  8. BZOJ 3932: [CQOI2015]任务查询系统 [主席树]

    传送门 题意: 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi 调度系统会经常向查询系统询问,第Xi ...

  9. 为Android添加JNI支持

    起因 今天在进行Android原生开发时,需要通过JNI调用C++代码实现一些处理.以前没有做过类似的东西,在网上找了很久才解决问题,特记录下来以便以后翻阅. Eclipse无cygwin编译so的方 ...

  10. Spring Mybatis-分页插件使用

    Mybatis分页切入点 Mybatis内部有个plugins(插件)概念,本质上属于拦截器的思想.具体的解析可见外文MyBatis拦截器原理探究.本文将在此基础上直接展示实现代码和其他的相关解析 分 ...