Qt基于FFmpeg播放本地 H.264(H264)文件

网友投稿 1362 2022-12-01

Qt基于FFmpeg播放本地 H.264(H264)文件

Qt基于FFmpeg播放本地 H.264(H264)文件

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

这个例子是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 //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 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>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);

下图是播放效果:

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:(第七集——第二章)python面向对象高级
下一篇:如何解决hibernate一对多注解懒加载失效问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~