Qt基于FFmpeg播放本地 H.264(H264)文件
2016-07-19 11:06
603 查看
最近在弄H264的硬件编解码,基于DM3730,但是为了调试方便,在小红帽上用FFmpeg实现了H264的软件编解码。现在弄了一个Windows的例子,给需要的同学参考一下,如果大家觉得有帮助,可以小手一抖,帮我点个赞
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/61c17ed2eb67211a84e137429ac3f7ad.gif)
。
这个例子是Qt Mingw版本的,FFmpeg可以去官网下载,也可以自己编译,编译方法可以参考我的博文。
【1】Windows 7(Win7)下MinGW+msys编译ffmpeg,并加入H264编码支持
【2】linux下编译ffmpeg,并加入H264编码支持
【3】 linux下交叉编译ffmpeg,并加入H264编码支持
下面是H264解码类
ch264decoder.h
需要注意的是,解码后的数据是RGB16格式,转换为QImage时,最后一个参数要用QImage::Format_RGB16,例如QImage image= QImage(outBuf, width, height, QImage::Format_RGB16);
下图是播放效果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/18/79a845a844e7abecc2387991cb8458e0)
演示用的H264文件下载链接:http://download.csdn.net/detail/caoshangpa/9492803
源码下载链接:见http://blog.csdn.net/caoshangpa/article/details/51953208的评论
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/61c17ed2eb67211a84e137429ac3f7ad.gif)
。
这个例子是Qt Mingw版本的,FFmpeg可以去官网下载,也可以自己编译,编译方法可以参考我的博文。
【1】Windows 7(Win7)下MinGW+msys编译ffmpeg,并加入H264编码支持
【2】linux下编译ffmpeg,并加入H264编码支持
【3】 linux下交叉编译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_Hch264decoder.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的评论
相关文章推荐
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- Managed Media Aggregation using Rtsp and Rtp
- QT学习 第一章:基本对话框
- 使用Shiboken为C++和Qt库创建Python绑定
- [总结]FFMPEG视音频编解码零基础学习方法
- Qt 5.6更新至RC版,最终版本近在咫尺
- 利用Ffmpeg获得flv视频缩略图和视频时间的代码
- Qt定时器和随机数详解
- codeigniter教程之上传视频并使用ffmpeg转flv示例
- Qt实现图片移动实例(图文教程)
- PHP使用ffmpeg给视频增加字幕显示的方法
- PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
- Qt for Android开发实例教程
- 快速解决Android平台移植ffmpeg的一些问题
- java调用ffmpeg实现视频转换的方法
- python+ffmpeg视频并发直播压力测试
- php使用ffmpeg向视频中添加文字字幕的实现方法
- H.264编码
- QModelIndex/Role/Model介紹<二>