最近在弄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. 多线程操作UI界面的示例 - 更新进度条

    http://blog.csdn.net/liang19890820/article/details/52186626

  2. Qt的Script、Quick、QML的关系与总结

    背景 最近在学QML,感觉也不难,就是一直以来接触 Qt 的脚本类的东西的顺序是Script.Quick1.Declarative.Quick2.QML.那么每一个都是干什么的呢,这些东西搞的我有点混 ...

  3. BZOJ2023: [Usaco2005 Nov]Ant Counting 数蚂蚁

    2023: [Usaco2005 Nov]Ant Counting 数蚂蚁 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 56  Solved: 16[S ...

  4. POJ1845 数论 二分快速取余

    大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题思路: 应用定理主要有三个: (1)   整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. ...

  5. 关于void*函数返回

    一. sample #include<iostream> using namespace std; void* test(void* pass) { return pass; } int ...

  6. c语言枚举型常量

    #include <stdio.h> //代表百度工程师的级别 enum level { //如果没有指定初始的值 那么c语言会自动分配一个编号 整数编号 T14=,T13=,T12=,T ...

  7. python高级编程:有用的设计模式1

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...

  8. APP常用模块

    2016年上半年 APICloud合作云服务商提供了各种类型模块多达45个 其中最新发布的重要模块有 美洽客服模块 亲加视频直播相关模块 保利威视视频播放器模块 苹果银联支付模块 贝宝支付模块 谷歌分 ...

  9. [Angular 2] Using ng-for to repeat template elements

    This lesson covers Angular 2’s version of looping through data in your templates: ng-for. It’s conce ...

  10. C# 异步和委托学习

    IAsyncResult是接口: IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来实现原同步方法的异步调用,如 ...