最近在弄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. 解决android4.0系统中菜单(Menu)添加Icon无效问题

    本文转载自: http://blog.csdn.net/stevenhu_223/article/details/9705173 在Android4.0系统中,创建菜单Menu,通过setIcon方法 ...

  2. android使用BlueStacks作为模拟器

    android原生的模拟器启动比较慢,偶尔还会出现一些莫名的问题,我们除了可以使用我们的android手机来进行调试外,还可以使用第三方的android模拟器,例如BlueStacks模拟器: 相对原 ...

  3. bzoj 1189

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1189 这道题目看起来好像要用很高端的网络流. 这道题有一个特别之处,就是每一个空地都有人,不是 ...

  4. java进阶计划

    鉴于自己在java 的学习过程中,像是无头苍蝇一样,东扎一把,西戳一下,没有一个明确的方向,也没有一个比较明确的方面,所以有了这个大致的计划. 计划的目标: 1. java本身的目标 对线程(thre ...

  5. 深入浅出 消息队列 ActiveMQ

    http://blog.csdn.net/jwdstef/article/details/17380471

  6. c++命名空间using

    #include<iostream> namespace run1 { ; } namespace run2 { ; void show() { std::cout << x ...

  7. 关于matlab中textread

    本文主要内容引自http://linux.chinaitlab.com/administer/872894.html 笔者在此基础上进行运行,修改得到以下内容,希望大家给与补充: textread 基 ...

  8. 第31讲 UI组件之 Gallery画廊控件

    第31讲 UI组件之 Gallery画廊控件 1.Gallery的简介 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息.Gallery只 ...

  9. poj 2441 Arrange the Bulls(状态压缩dp)

    Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to ...

  10. [Qt] fontawesome图标

    fontawesome图标 fontawesome是一个图标的集合,里面有好多的图标,使用起来也还是非常方便的. 图标信息可以到官网去查:http://fontawesome.io/cheatshee ...