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

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

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

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

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

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

下面是H264解码类

ch264decoder.h

[cpp] view plain copy

  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

[cpp] view plain copy

  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的评论

时间: 2024-08-03 00:05:13

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

基于RTP协议的H.264传输

1.  引言        随 着信息产业的发展,人们对信息资源的要求已经逐渐由文字和图片过渡到音频和视频,并越来越强调获取资源的实时性和互动性.但人们又面临着另外一种不可避免 的尴尬,就是在网络上看到生动清晰的媒体演示的同时,不得不为等待传输文件而花费大量时间.为了解决这个矛盾,一种新的媒体技术应运而生,这就是流媒体技 术.流媒体由于具有启动时延小.节省客户端存储空间等优势,逐渐成为人们的首选,流媒体网络应用也在全球范围内得到不断的发展.其中实时流传输协议 RTP 详细说明了在互联网上传递音频

使用jrtplib(RTP)传输H.264视频文件(2)

上一篇我们介绍了RTP协议的一些基本知识,下面我们介绍如何使用jrtplib这个库传输H264编码. JRTP传输: 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释.发送端也可以接收接收端发送过来的RTCP数据包. #define MAX_RTP_PKT_LENGTH 1360 #define H264               96 bool CheckError(int rtperr); class CRTPSender : public RTPSessio

使用jrtplib传输H.264视频文件(3)

介绍如何发送h264,下面我们介绍下如何接收h264文件. 其中主要关注的就是被拆分的数据包的重组,下面的代码中有详尽的注释. class CRTPReceiver : public RTPSession { protected: void OnPollThreadStep(); void ProcessRTPPacket(const RTPSourceData &srcdat,const RTPPacket &rtppack); void OnRTCPCompoundPacket(RTC

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

布局如下:(重点讲本地通知) 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 Notification是智能手机应用编程中非常常用的一种传递信息的机制,而且可以非常好的节省资源,不用消耗资源来不停地检查信息状态(Pooling),在iOS下应用分为两种不同的Notification种类,本地和远程.本地的Notification由iOS下NotificationManager统一管理,只需要将封装好的本地Notification对象加入到系统Notificat

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

开发环境: 服务器系统:CentOS-6.x web服务器:Apache-2.2.x php版本:PHP-5.3.x 开发工具:sublime text 3 ,谷歌浏览器 数据库查询工具:phpmyadmin 协作工具:乌龟SVN 约定: 数据表前缀:blog_ 数据表主键名:表名_id,自增,不为空 时间字段类型统一为timestamp,每个表必须含有创建时间(默认当前时间),更新时间(默认由mysql更新) 字符集采用UTF-8 项目定义:多用户博客系统--运行在SAE上,基于php的最新3

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

一.方案确定 计划做视频播放,要求可以播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive/2011/04/21/html5_video_ipad_firefox_chrome_ie9876_flash.html.这个方法将视频播放分为两部分.一是html5播放,二是flash播放.假设浏览器支持用html5的video标签播放h264的mp4文件,如ie9,chrome,safari採

调用FFmpeg SDK对H.264格式的视频压缩码流进行解码

由于作者不习惯该编辑器,只是将本文的截图贴了出来,详文见:https://www.yuque.com/docs/share/cce69b1b-b619-44b5-acd1-efa229d88627 原文地址:http://blog.51cto.com/4754569/2324664

iOS中 基于LBXScan库二维码扫描 韩俊强的博客

每日更新关注:http://weibo.com/hanjunqiang  新浪微博 首先声明这个二维码扫描是借助于zxing. 功能模块都完全封装好了,不过界面合你口味,直接使用就好,如果不合口味,后面告诉你怎么修改. - 1.cocoaPods导入pod 'LBXScan', '~> 1.1.1' 导入方法看这: - 2.将JQScan文件夹拖到你的工程中(这个是写好的). <code class="language-Objective-C hljs objectivec has-

QT 生成的exe 无法打开 说缺少QTCORED4.DLL文件-三点水兽-ChinaUnix博客

还需要已经运行时提示缺少的组件添加一些dll 来源:http://blog.chinaunix.net/uid-20620288-id-3356186.html#0-hi-1-67586-89fdc647f52c5196c0d5da60d38d89ea