最近在弄H264的硬件编解码,基于DM3730,但是为了调试方便,在小红帽上用FFmpeg实现了H264的软件编解码。现在弄了一个Windows的例子,给需要的同学参考一下,如果大家觉得有帮助,可以小手一抖,帮我点个赞

这个例子是Qt Mingw版本的,FFmpeg可以去官网下载,也可以自己编译,编译方法可以参考我的博文。

Windows 7(Win7)下MinGW+msys编译ffmpeg,并加入H264编码支持

linux下交叉编译ffmpeg,并加入H264编码支持

linux下编译ffmpeg,并加入H264编码支持

下面是H264解码类

ch264decoder.h

  1. #ifndef CH264DECODER_H
  2. #define CH264DECODER_H
  3. #include <string.h>
  4. //C++引用C语言的头文件
  5. extern "C"
  6. {
  7. #include "libavformat/avformat.h"
  8. #include "libswresample/swresample.h"
  9. #include "libavutil/opt.h"
  10. #include "libavutil/channel_layout.h"
  11. #include "libavutil/parseutils.h"
  12. #include "libavutil/samplefmt.h"
  13. #include "libavutil/fifo.h"
  14. #include "libavutil/intreadwrite.h"
  15. #include "libavutil/dict.h"
  16. #include "libavutil/mathematics.h"
  17. #include "libavutil/pixdesc.h"
  18. #include "libavutil/avstring.h"
  19. #include "libavutil/imgutils.h"
  20. #include "libavcodec/avcodec.h"
  21. #include "libavfilter/avfilter.h"
  22. #include "libavfilter/buffersrc.h"
  23. #include "libavfilter/buffersink.h"
  24. }
  25. class CH264Decoder
  26. {
  27. public:
  28. CH264Decoder();
  29. ~CH264Decoder();
  30. /*************************************************
  31. Function:initial
  32. Description:初始化
  33. Input:无
  34. Output:无
  35. Return:错误代码
  36. Others:无
  37. *************************************************/
  38. int initial();
  39. /*************************************************
  40. Function:decode
  41. Description:解码
  42. Input:pDataIn-待解码数据,nInSize-待解码数据长度
  43. Output:pDataOut-解码后的数据,nWidth-解码后的图像宽度,nHeight-解码后的图像高度
  44. Return:错误代码
  45. Others:解码后的数据为RGB16格式
  46. *************************************************/
  47. int decode(uint8_t *pDataIn, int nInSize, uint8_t *pDataOut, int *nWidth, int *nHeight);
  48. /*************************************************
  49. Function:unInitial
  50. Description:销毁
  51. Input:无
  52. Output:无
  53. Return:无
  54. Others:无
  55. *************************************************/
  56. void unInitial();
  57. private:
  58. void deleteYUVTab();
  59. void createYUVTab_16();
  60. void displayYUV_16(unsigned int *pdst, unsigned char *y, unsigned char *u,unsigned char *v,
  61. int width, int height, int src_ystride, int src_uvstride, int dst_ystride);
  62. private:
  63. int *colortab;
  64. int *u_b_tab;
  65. int *u_g_tab;
  66. int *v_g_tab;
  67. int *v_r_tab;
  68. unsigned int *rgb_2_pix;
  69. unsigned int *r_2_pix;
  70. unsigned int *g_2_pix;
  71. unsigned int *b_2_pix;
  72. AVCodec *codec;
  73. AVCodecContext *context;
  74. AVFrame *frame;
  75. AVPacket packet;
  76. };
  77. #endif // CH264DECODER_H

ch264decoder.cpp

  1. #include "ch264decoder.h"
  2. #include <QDebug>
  3. CH264Decoder::CH264Decoder()
  4. {
  5. createYUVTab_16();
  6. }
  7. CH264Decoder::~CH264Decoder()
  8. {
  9. deleteYUVTab();
  10. }
  11. void CH264Decoder::deleteYUVTab()
  12. {
  13. av_free(colortab);
  14. av_free(rgb_2_pix);
  15. }
  16. void CH264Decoder::createYUVTab_16()
  17. {
  18. int i;
  19. int u, v;
  20. colortab = (int *)av_malloc(4*256*sizeof(int));
  21. u_b_tab = &colortab[0*256];
  22. u_g_tab = &colortab[1*256];
  23. v_g_tab = &colortab[2*256];
  24. v_r_tab = &colortab[3*256];
  25. for (i=0; i<256; i++)
  26. {
  27. u = v = (i-128);
  28. u_b_tab[i] = (int) ( 1.772 * u);
  29. u_g_tab[i] = (int) ( 0.34414 * u);
  30. v_g_tab[i] = (int) ( 0.71414 * v);
  31. v_r_tab[i] = (int) ( 1.402 * v);
  32. }
  33. rgb_2_pix = (unsigned int *)av_malloc(3*768*sizeof(unsigned int));
  34. r_2_pix = &rgb_2_pix[0*768];
  35. g_2_pix = &rgb_2_pix[1*768];
  36. b_2_pix = &rgb_2_pix[2*768];
  37. for(i=0; i<256; i++)
  38. {
  39. r_2_pix[i] = 0;
  40. g_2_pix[i] = 0;
  41. b_2_pix[i] = 0;
  42. }
  43. for(i=0; i<256; i++)
  44. {
  45. r_2_pix[i+256] = (i & 0xF8) << 8;
  46. g_2_pix[i+256] = (i & 0xFC) << 3;
  47. b_2_pix[i+256] = (i ) >> 3;
  48. }
  49. for(i=0; i<256; i++)
  50. {
  51. r_2_pix[i+512] = 0xF8 << 8;
  52. g_2_pix[i+512] = 0xFC << 3;
  53. b_2_pix[i+512] = 0x1F;
  54. }
  55. r_2_pix += 256;
  56. g_2_pix += 256;
  57. b_2_pix += 256;
  58. }
  59. void CH264Decoder::displayYUV_16(unsigned int *pdst, unsigned char *y, unsigned char *u, unsigned char *v, int width, int height, int src_ystride, int src_uvstride, int dst_ystride)
  60. {
  61. int i, j;
  62. int r, g, b, rgb;
  63. int yy, ub, ug, vg, vr;
  64. unsigned char* yoff;
  65. unsigned char* uoff;
  66. unsigned char* voff;
  67. int width2 = width/2;
  68. int height2 = height/2;
  69. for(j=0; j<height2; j++)
  70. {
  71. yoff = y + j * 2 * src_ystride;
  72. uoff = u + j * src_uvstride;
  73. voff = v + j * src_uvstride;
  74. for(i=0; i<width2; i++)
  75. {
  76. yy  = *(yoff+(i<<1));
  77. ub = u_b_tab[*(uoff+i)];
  78. ug = u_g_tab[*(uoff+i)];
  79. vg = v_g_tab[*(voff+i)];
  80. vr = v_r_tab[*(voff+i)];
  81. b = yy + ub;
  82. g = yy - ug - vg;
  83. r = yy + vr;
  84. rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
  85. yy = *(yoff+(i<<1)+1);
  86. b = yy + ub;
  87. g = yy - ug - vg;
  88. r = yy + vr;
  89. pdst[(j*dst_ystride+i)] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
  90. yy = *(yoff+(i<<1)+src_ystride);
  91. b = yy + ub;
  92. g = yy - ug - vg;
  93. r = yy + vr;
  94. rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
  95. yy = *(yoff+(i<<1)+src_ystride+1);
  96. b = yy + ub;
  97. g = yy - ug - vg;
  98. r = yy + vr;
  99. pdst [((2*j+1)*dst_ystride+i*2)>>1] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
  100. }
  101. }
  102. }
  103. int CH264Decoder::initial()
  104. {
  105. avcodec_register_all();
  106. av_init_packet(&packet);
  107. codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  108. if (!codec)
  109. {
  110. printf("avcodec_find_encoder failed");
  111. return -1;
  112. }
  113. context = avcodec_alloc_context3(codec);
  114. if (!context)
  115. {
  116. printf("avcodec_alloc_context3 failed");
  117. return -2;
  118. }
  119. context->codec_type = AVMEDIA_TYPE_VIDEO;
  120. context->pix_fmt = AV_PIX_FMT_YUV420P;
  121. if (avcodec_open2(context, codec, NULL) < 0)
  122. {
  123. printf("avcodec_open2 failed");
  124. return -3;
  125. }
  126. frame = av_frame_alloc();
  127. if (!frame)
  128. {
  129. return -4;
  130. }
  131. return 0;
  132. }
  133. void CH264Decoder::unInitial()
  134. {
  135. avcodec_close(context);
  136. av_free(context);
  137. av_frame_free(&frame);
  138. }
  139. int CH264Decoder::decode(uint8_t *pDataIn, int nInSize, uint8_t *pDataOut,int *nWidth, int *nHeight)
  140. {
  141. av_init_packet(&packet);
  142. packet.size = nInSize;
  143. packet.data = pDataIn;
  144. if (packet.size > 0)
  145. {
  146. int got_picture=0;
  147. int ret= avcodec_decode_video2(context, frame, &got_picture, &packet);
  148. if (ret < 0)
  149. {
  150. printf("avcodec_encode_video2 failed");
  151. return -2;
  152. }
  153. if (got_picture)
  154. {
  155. *nWidth = context->width;
  156. *nHeight = context->height;
  157. displayYUV_16((unsigned int*)pDataOut, frame->data[0], frame->data[1],frame->data[2],
  158. *nWidth,*nHeight,frame->linesize[0],frame->linesize[2],*nWidth);
  159. }
  160. }
  161. else
  162. {
  163. printf("no data to decode");
  164. return -1;
  165. }
  166. return 0;
  167. }

使用方法,先调用initial()进行初始化,然后读取本地H264文件,调用decode()函数进行解码,退出时调用unInitial()函数释放资源。

需要注意的是,解码后的数据是RGB16格式,转换为QImage时,最后一个参数要用QImage::Format_RGB16,例如QImage image= QImage(outBuf, width, height, QImage::Format_RGB16);

下图是播放效果:

演示用的H264文件下载链接:http://download.csdn.net/detail/caoshangpa/9492803

源码下载链接:见http://blog.csdn.net/caoshangpa/article/details/51953208的评论

Qt基于FFmpeg播放本地 H.264(H264)文件(灿哥哥的博客)的更多相关文章

  1. 基于RTP协议的H.264传输

    1.  引言        随 着信息产业的发展,人们对信息资源的要求已经逐渐由文字和图片过渡到音频和视频,并越来越强调获取资源的实时性和互动性.但人们又面临着另外一种不可避免 的尴尬,就是在网络上看 ...

  2. 本地Markdown文件上传到博客

    本地Markdown文件上传到博客 参考:https://www.cnblogs.com/ccylhw/p/13954153.html 1.Typora 最漂亮的写作APPhttps://www.ty ...

  3. 树莓派编译安装 FFmpeg(添加 H.264 硬件编解码器支持)

    说明 FFmpeg 是一套开源的音视频编解码库,有非常强大的功能,包括视频采集功能.视频格式转换等.众所周知视频编解码是一个非常消耗系统资源的过程,而树莓派自带了 H.264 的硬件编解码器,因此本文 ...

  4. iOS中 本地通知/本地通知详解 韩俊强的博客

    布局如下:(重点讲本地通知) iOS开发者交流QQ群: 446310206 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 Notification是智能手机应用编 ...

  5. 基于SAE+CodeIgniter3.0+管理端angularjs+前台amazeui的多用户博客系统V1.0--系统设计(一)

    开发环境: 服务器系统:CentOS-6.x web服务器:Apache-2.2.x php版本:PHP-5.3.x 开发工具:sublime text 3 ,谷歌浏览器 数据库查询工具:phpmya ...

  6. 兼容各个浏览器的H.264播放: H.264+HTML5+FLOWPLAYER+WOWZA+RMTP

    一.方案确定 计划做视频播放,要求可以播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive ...

  7. [转]兼容各个浏览器的H.264播放: H.264+HTML5+FLOWPLAYER+WOWZA+RMTP

    一.方案确定 计划做视频播放,要求能够播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive ...

  8. ffmpeg接收udp输入的h264文件流,推流到rtmp服务器

    ffmpeg -re -f h264 -i udp://192.168.5.49:10002 -vcodec libx264 -f flv rtmp://192.168.5.155/live/1

  9. 3种用组策略将域帐号加入本地管理员组的方法_jinifly_新浪博客

    次当前系统域帐号是怎么在第一次登录时,自动加入域客户端本地管理员组的?我猜不外乎就是脚本.计算机策略或虚拟机初始化的自动应答脚本,结果系统的前任同事找到了答案--GPO的用户策略(确切讲是用户首选项) ...

随机推荐

  1. 自制单片机之一------AT89S51最小系统制做

    C51最小系统电路在网上一搜一大把,大同小异.我略做改动后如图: 加一个11.0592MHZ的晶振是为了以后做串口通信时和PC有相同的波特率.可用短路帽切换.说说板子的布局:网上卖的最小系统都是把板子 ...

  2. Linux & Python 导航目录

    < Python学习手册(第4版)>< Python Cookbook(第2版)>中文版.pdf< Python 高级编程>< Python 基础教程 第二版 ...

  3. NSIS脚本调用C语言写的插件

    其实NSIS的官网已经提供了很多别人开发的插件了,今天需要用到GetVersion这个插件,这是不维护的插件了,不推荐用,但是由于现实中的问题,导致我不得不用这个插件. 所以就下载下来了. 下载下来之 ...

  4. Linux企业级项目实践之网络爬虫(4)——主程序流程

    当我们设计好程序框架之后就要开始实现它了.第一步当然是要实现主程序的流程框架.之后我们逐渐填充每个流程的细节和其需要调用的模块. 主程序的流程如下: 1.  解析命令行参数,并根据参数跳转到相应的处理 ...

  5. 【转】JAVA中的浅拷贝和深拷贝

    原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...

  6. 【转】Windows 7下硬盘安装Ubuntu 14.04图文教程--不错

    原文网址:http://www.linuxidc.com/Linux/2014-04/100369p3.htm Ubuntu 官方已经发布了正式版的 Ubuntu 14.04 LTS,并宣称这是为云计 ...

  7. 关于as3实现对任何对象进行深刻复制的思考

    无意中看到关于as3深度复制思考的文章,觉得不错,于是转来记录以后用到可以参考. 转载来源:http://xmchcly.iteye.com/blog/1307425,下面是转文: 通过 ByteAr ...

  8. java开发经验分享(三)

    三. 项目开发 1. 需求: 1) 需求最终需要开发人员在产品中实现,开发不合理的设计会浪费时间,开发技术无法实现的设计带来最大的痛苦:失败.所以,开发人员要重视需求以及需求评审,提出自己能够想到的所 ...

  9. hdu2460-Network:边的双连通分量

    题目大意:给出一个无向图以及Q次询问,每次询问增加一条无向边,要求输出增加这条边后剩余的桥的数目. 算法:类似于求割点的方法,先做一次dfs求出所有的桥,并且维护这棵dfs树,当一次询问加入一条边(a ...

  10. Java 四大域对象总结

    一.ServletContext 1.生命周期:当Web应用被加载进容器时创建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时,ServletContext对象跟 ...