Qt基于FFmpeg播放本地 H.264(H264)文件(灿哥哥的博客)
最近在弄H264的硬件编解码,基于DM3730,但是为了调试方便,在小红帽上用FFmpeg实现了H264的软件编解码。现在弄了一个Windows的例子,给需要的同学参考一下,如果大家觉得有帮助,可以小手一抖,帮我点个赞
。
这个例子是Qt Mingw版本的,FFmpeg可以去官网下载,也可以自己编译,编译方法可以参考我的博文。
Windows 7(Win7)下MinGW+msys编译ffmpeg,并加入H264编码支持
下面是H264解码类
ch264decoder.h
- #ifndef CH264DECODER_H
- #define CH264DECODER_H
- #include <string.h>
- //C++引用C语言的头文件
- extern "C"
- {
- #include "libavformat/avformat.h"
- #include "libswresample/swresample.h"
- #include "libavutil/opt.h"
- #include "libavutil/channel_layout.h"
- #include "libavutil/parseutils.h"
- #include "libavutil/samplefmt.h"
- #include "libavutil/fifo.h"
- #include "libavutil/intreadwrite.h"
- #include "libavutil/dict.h"
- #include "libavutil/mathematics.h"
- #include "libavutil/pixdesc.h"
- #include "libavutil/avstring.h"
- #include "libavutil/imgutils.h"
- #include "libavcodec/avcodec.h"
- #include "libavfilter/avfilter.h"
- #include "libavfilter/buffersrc.h"
- #include "libavfilter/buffersink.h"
- }
- class CH264Decoder
- {
- public:
- CH264Decoder();
- ~CH264Decoder();
- /*************************************************
- Function:initial
- Description:初始化
- Input:无
- Output:无
- Return:错误代码
- Others:无
- *************************************************/
- int initial();
- /*************************************************
- Function:decode
- Description:解码
- Input:pDataIn-待解码数据,nInSize-待解码数据长度
- Output:pDataOut-解码后的数据,nWidth-解码后的图像宽度,nHeight-解码后的图像高度
- Return:错误代码
- Others:解码后的数据为RGB16格式
- *************************************************/
- int decode(uint8_t *pDataIn, int nInSize, uint8_t *pDataOut, int *nWidth, int *nHeight);
- /*************************************************
- Function:unInitial
- Description:销毁
- Input:无
- Output:无
- Return:无
- Others:无
- *************************************************/
- void unInitial();
- private:
- void deleteYUVTab();
- void createYUVTab_16();
- void 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);
- private:
- int *colortab;
- int *u_b_tab;
- int *u_g_tab;
- int *v_g_tab;
- int *v_r_tab;
- unsigned int *rgb_2_pix;
- unsigned int *r_2_pix;
- unsigned int *g_2_pix;
- unsigned int *b_2_pix;
- AVCodec *codec;
- AVCodecContext *context;
- AVFrame *frame;
- AVPacket packet;
- };
- #endif // CH264DECODER_H
ch264decoder.cpp
- #include "ch264decoder.h"
- #include <QDebug>
- CH264Decoder::CH264Decoder()
- {
- createYUVTab_16();
- }
- CH264Decoder::~CH264Decoder()
- {
- deleteYUVTab();
- }
- void CH264Decoder::deleteYUVTab()
- {
- av_free(colortab);
- av_free(rgb_2_pix);
- }
- void CH264Decoder::createYUVTab_16()
- {
- int i;
- int u, v;
- colortab = (int *)av_malloc(4*256*sizeof(int));
- u_b_tab = &colortab[0*256];
- u_g_tab = &colortab[1*256];
- v_g_tab = &colortab[2*256];
- v_r_tab = &colortab[3*256];
- for (i=0; i<256; i++)
- {
- u = v = (i-128);
- u_b_tab[i] = (int) ( 1.772 * u);
- u_g_tab[i] = (int) ( 0.34414 * u);
- v_g_tab[i] = (int) ( 0.71414 * v);
- v_r_tab[i] = (int) ( 1.402 * v);
- }
- rgb_2_pix = (unsigned int *)av_malloc(3*768*sizeof(unsigned int));
- r_2_pix = &rgb_2_pix[0*768];
- g_2_pix = &rgb_2_pix[1*768];
- b_2_pix = &rgb_2_pix[2*768];
- for(i=0; i<256; i++)
- {
- r_2_pix[i] = 0;
- g_2_pix[i] = 0;
- b_2_pix[i] = 0;
- }
- for(i=0; i<256; i++)
- {
- r_2_pix[i+256] = (i & 0xF8) << 8;
- g_2_pix[i+256] = (i & 0xFC) << 3;
- b_2_pix[i+256] = (i ) >> 3;
- }
- for(i=0; i<256; i++)
- {
- r_2_pix[i+512] = 0xF8 << 8;
- g_2_pix[i+512] = 0xFC << 3;
- b_2_pix[i+512] = 0x1F;
- }
- r_2_pix += 256;
- g_2_pix += 256;
- b_2_pix += 256;
- }
- 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)
- {
- int i, j;
- int r, g, b, rgb;
- int yy, ub, ug, vg, vr;
- unsigned char* yoff;
- unsigned char* uoff;
- unsigned char* voff;
- int width2 = width/2;
- int height2 = height/2;
- for(j=0; j<height2; j++)
- {
- yoff = y + j * 2 * src_ystride;
- uoff = u + j * src_uvstride;
- voff = v + j * src_uvstride;
- for(i=0; i<width2; i++)
- {
- yy = *(yoff+(i<<1));
- ub = u_b_tab[*(uoff+i)];
- ug = u_g_tab[*(uoff+i)];
- vg = v_g_tab[*(voff+i)];
- vr = v_r_tab[*(voff+i)];
- b = yy + ub;
- g = yy - ug - vg;
- r = yy + vr;
- rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
- yy = *(yoff+(i<<1)+1);
- b = yy + ub;
- g = yy - ug - vg;
- r = yy + vr;
- pdst[(j*dst_ystride+i)] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
- yy = *(yoff+(i<<1)+src_ystride);
- b = yy + ub;
- g = yy - ug - vg;
- r = yy + vr;
- rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];
- yy = *(yoff+(i<<1)+src_ystride+1);
- b = yy + ub;
- g = yy - ug - vg;
- r = yy + vr;
- pdst [((2*j+1)*dst_ystride+i*2)>>1] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);
- }
- }
- }
- int CH264Decoder::initial()
- {
- avcodec_register_all();
- av_init_packet(&packet);
- codec = avcodec_find_decoder(AV_CODEC_ID_H264);
- if (!codec)
- {
- printf("avcodec_find_encoder failed");
- return -1;
- }
- context = avcodec_alloc_context3(codec);
- if (!context)
- {
- printf("avcodec_alloc_context3 failed");
- return -2;
- }
- context->codec_type = AVMEDIA_TYPE_VIDEO;
- context->pix_fmt = AV_PIX_FMT_YUV420P;
- if (avcodec_open2(context, codec, NULL) < 0)
- {
- printf("avcodec_open2 failed");
- return -3;
- }
- frame = av_frame_alloc();
- if (!frame)
- {
- return -4;
- }
- return 0;
- }
- void CH264Decoder::unInitial()
- {
- avcodec_close(context);
- av_free(context);
- av_frame_free(&frame);
- }
- int CH264Decoder::decode(uint8_t *pDataIn, int nInSize, uint8_t *pDataOut,int *nWidth, int *nHeight)
- {
- av_init_packet(&packet);
- packet.size = nInSize;
- packet.data = pDataIn;
- if (packet.size > 0)
- {
- int got_picture=0;
- int ret= avcodec_decode_video2(context, frame, &got_picture, &packet);
- if (ret < 0)
- {
- printf("avcodec_encode_video2 failed");
- return -2;
- }
- if (got_picture)
- {
- *nWidth = context->width;
- *nHeight = context->height;
- displayYUV_16((unsigned int*)pDataOut, frame->data[0], frame->data[1],frame->data[2],
- *nWidth,*nHeight,frame->linesize[0],frame->linesize[2],*nWidth);
- }
- }
- else
- {
- printf("no data to decode");
- return -1;
- }
- return 0;
- }
使用方法,先调用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)文件(灿哥哥的博客)的更多相关文章
- 基于RTP协议的H.264传输
1. 引言 随 着信息产业的发展,人们对信息资源的要求已经逐渐由文字和图片过渡到音频和视频,并越来越强调获取资源的实时性和互动性.但人们又面临着另外一种不可避免 的尴尬,就是在网络上看 ...
- 本地Markdown文件上传到博客
本地Markdown文件上传到博客 参考:https://www.cnblogs.com/ccylhw/p/13954153.html 1.Typora 最漂亮的写作APPhttps://www.ty ...
- 树莓派编译安装 FFmpeg(添加 H.264 硬件编解码器支持)
说明 FFmpeg 是一套开源的音视频编解码库,有非常强大的功能,包括视频采集功能.视频格式转换等.众所周知视频编解码是一个非常消耗系统资源的过程,而树莓派自带了 H.264 的硬件编解码器,因此本文 ...
- iOS中 本地通知/本地通知详解 韩俊强的博客
布局如下:(重点讲本地通知) iOS开发者交流QQ群: 446310206 每日更新关注:http://weibo.com/hanjunqiang 新浪微博 Notification是智能手机应用编 ...
- 基于SAE+CodeIgniter3.0+管理端angularjs+前台amazeui的多用户博客系统V1.0--系统设计(一)
开发环境: 服务器系统:CentOS-6.x web服务器:Apache-2.2.x php版本:PHP-5.3.x 开发工具:sublime text 3 ,谷歌浏览器 数据库查询工具:phpmya ...
- 兼容各个浏览器的H.264播放: H.264+HTML5+FLOWPLAYER+WOWZA+RMTP
一.方案确定 计划做视频播放,要求可以播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive ...
- [转]兼容各个浏览器的H.264播放: H.264+HTML5+FLOWPLAYER+WOWZA+RMTP
一.方案确定 计划做视频播放,要求能够播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive ...
- 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
- 3种用组策略将域帐号加入本地管理员组的方法_jinifly_新浪博客
次当前系统域帐号是怎么在第一次登录时,自动加入域客户端本地管理员组的?我猜不外乎就是脚本.计算机策略或虚拟机初始化的自动应答脚本,结果系统的前任同事找到了答案--GPO的用户策略(确切讲是用户首选项) ...
随机推荐
- java解析网页的内容
有时候,我们需要在java程序中获取一个连接,然后解析连接后,获取连接返回的内容结果来解析.准确的说是解析一个链接. 以下代码时解析百度首页的链接,获取的html代码的效果: public stati ...
- CoreData Multiple Context性能分析-读书笔记
From: http://floriankugler.com/blog/2013/4/29/concurrent-core-data-stack-performance-shootout http: ...
- (Stack)Basic Calculator I && II
Basic Calculator I Implement a basic calculator to evaluate a simple expression string. The expressi ...
- 用c++编写一个不能被继承的类(但是可以在类外部定义该类的对象)
据我们知道,我们只要把类的构造函数和析构函数定义为private类型,那么就不能够在外部建立给类的对象,也就不能以给类为基类进行继承,因为如果继承,建立对象的时候将要调用基类的构造函数,但是因为为pr ...
- c语言指向结构体数组的指针
#include <stdio.h> #include <stdlib.h> struct dangdang { ]; ]; ]; int num; int bugnum; ] ...
- centerOS安装chkrootkit
Chkrootkit是一个在本地系统检查rootkit痕迹的工具,它是检查系统二进制文件是否被rootkit病毒修改的一个shell脚本. (1)centerOS安装chkrootkit 安装gcc编 ...
- 给那些因为Firebug而舍不得FireFox的朋友
Google Chrome浏览器调试 作为Web开发人员,我为什么喜欢Google Chrome浏览器 [原文地址:http://www.cnblogs.com/QLeelulu/archive/20 ...
- 全响应跨设备的Zoomla!逐浪CMS2 x2.0正式公布
2014年是中国互联网的重要一年,京东上市.聚美优品领衔创业风范,小米进军国际化.滴滴快的锋火争雄. 作为中国互联网的中间力量,Zoomla!逐浪软件团队坚守信念,始终以WEB开发和科研创新为己任,并 ...
- HDU--1584--蜘蛛牌--深搜版本号
蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- windows消息常量值
WM_NULL = 0WM_CREATE = 1应用程序创建一个窗口WM_DESTROY = 2一个窗口被销毁WM_MOVE = 3移动一个窗口WM_SIZE = 5改变一个窗口的大小WM_ACTIV ...