【FFmpeg+Qt开发】解码流程 详细分析+代码示例

目录

一、FFMPEG 概述

​二、FFMPEG 解码

2.1解码流程

2.2解码示例


一、FFMPEG 概述

  • FFmpeg 是一套可以用来记录、转换,数字音频、视频,并能将其转化为流的开源计算机程序。
  • FFmpeg 采用 LGPL GPL 许可证;它提供了录制、转换以及流化音视频的完整解决案;它还包含了非常先进的音频\视频编解码库 libavcodec,为了保证高可移植性和编解码质量,libavcodec 里很多 code 都是从头开发的。
  • FFmpeg Linux 平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括 WindowsMac OS X 等。
  • FFmpeg最早由 Fabrice Bellard 发起,2004 年至 2015 年间由 Michael Niedermayer 主要负责维护。许多 FFmpeg 的开发人员都来自 MPlayer 项目,而且当前 FFmpeg 也是放在MPlayer 项目组的服务器上。
  • FFmpeg名称来自 MPEG 视频编码标准,前面的"FF" 代表"Fast Forward"

下载链接:Download FFmpeg

具体下载详见:Qt+FFmpeg----windows下环境搭建_猿力猪的博客-CSDN博客_ffmpeg开发环境搭建

​二、FFMPEG 解码

2.1解码流程

🔴解码:将带有封装格式的视频解封装后得到的压缩码流数据(编码数据)经过解码得到像素数据的过程。
例如:解码 H.264 压缩码流数据得到 YUV (或者 RGB )的像素数据。
### 如何在QT中集成或使用FFmpeg 要在QT项目中集成或使用FFmpeg,可以采用多种方法实现视频处理功能。以下是几种常见的技术路径: #### 方法一:通过命令行调用FFmpeg 可以直接利用系统的`QProcess`类来执行FFmpeg命令行工具。这种方式简单易用,适合不需要频繁交互的应用场景。 ```cpp #include <QCoreApplication> #include <QProcess> void runFfmpegCommand() { QProcess process; QStringList arguments; arguments << "-i" << "/tmp/test%d.Y" << "/tmp/out.mpg"; // 使用YUV文件作为输入[^2] process.start("ffmpeg", arguments); if (!process.waitForStarted()) { qDebug() << "Failed to start FFmpeg"; return; } if (!process.waitForFinished()) { qDebug() << "FFmpeg execution failed:" << process.errorString(); return; } qDebug() << "FFmpeg output:" << process.readAllStandardOutput(); } ``` 这种方法的优点在于无需编译FFmpeg库到应用程序中,缺点是性能可能不如直接链接动态库的方式高效。 --- #### 方法二:静态/动态链接FFmpeg库 如果需要更高效的控制和更高的灵活性,可以选择将FFmpeg库嵌入到QT应用中。这通常涉及以下几个步骤: 1. **下载并安装FFmpeg** 需要先获取FFmpeg源码并构建共享库或静态库。可以通过官方文档指导完成此操作[^1]。 2. **配置Qt Creator工程文件(.pro)** 将FFmpeg库添加至项目的`.pro`文件中以便于链接。 ```plaintext INCLUDEPATH += /path/to/ffmpeg/include LIBS += -L/path/to/ffmpeg/lib -lavformat -lavcodec -lswscale -lavutil ``` 3. **编写C++代码加载FFmpeg功能** 下面是一个简单的例子展示如何读取视频帧数据并通过OpenCV显示出来(假设已成功部署模型API接口[^3])。 ```cpp extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> } void decodeVideo(const char *filename) { AVFormatContext *pFormatCtx = nullptr; int videoStream; av_register_all(); // 注册所有可用的解码器、编码器和其他组件 if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0){ fprintf(stderr, "Couldn't open file\n"); return; // 打开失败退出程序运行 } if(avfindstreaminfo(pFormatCtx)<0){ printf("Didn't find stream information.\n"); return ; } videoStream=ff_find_stream_info(pFormatCtx); AVCodecParameters *codecpar=pFormatCtx->streams[videoStream]->codecpar; const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id); if(!codec){ fprintf(stderr,"Unsupported codec!\n"); return ; } AVFrame *frame,*rgb_frame; struct SwsContext *img_convert_ctx=NULL; uint8_t *out_buffer; frame=av_frame_alloc(); rgb_frame=av_frame_alloc(); img_convert_ctx=sws_getContext( pFormatCtx->streams[videoStream]->width, pFormatCtx->streams[videoStream]->height, codecpar->format, pFormatCtx->streams[videoStream]->width, pFormatCtx->streams[videoStream]->height, AV_PIX_FMT_RGB24, SWS_BILINEAR,NULL,NULL,NULL); out_buffer=(uint8_t*)av_malloc( av_image_get_buffer_size(AV_PIX_FMT_RGB24,pFormatCtx->streams[videoStream]->width, pFormatCtx->streams[videoStream]->height,1)); av_image_fill_arrays(rgb_frame->data,rgb_frame->linesize,out_buffer, AV_PIX_FMT_RGB24,pFormatCtx->streams[videoStream]->width, pFormatCtx->streams[videoStream]->height,1); AVPacket packet; while(av_read_frame(pFormatCtx,&packet)>=0){ if(packet.stream_index==videoStream){ int ret=avcodec_send_packet(codecctx,&packet); if(ret<0){ continue; } while(ret>=0){ ret=avcodec_receive_frame(codecctx,frame); if(ret==AVERROR(EAGAIN)||ret==AVERROR_EOF) break; else if(ret<0){ fprintf(stderr,"Error during decoding\n"); exit(1); } sws_scale(img_convert_ctx,(const uint8_t* const *)frame->data, frame->linesize,0,frame->height, rgb_frame->data,rgb_frame->linesize); QImage image((uchar*)rgb_frame->data[0],pFormatCtx->streams[videoStream]->width, pFormatCtx->streams[videoStream]->height,QImage::Format_RGB888); QLabel label; QPixmap pixmap=QPixmap::fromImage(image); label.setPixmap(pixmap.scaled(label.size(), Qt::KeepAspectRatio)); } } av_packet_unref(&packet); } } ``` 上述代码片段展示了如何解析视频流并将每一帧转换成RGB图像格式供进一步处理或者渲染。 --- #### 方法三:借助第三方封装库简化开发流程 对于不想深入研究底层细节的情况,可考虑引入一些基于FFmpeg二次开发而成的高级框架,比如QtAV 或者 VLC-Qt 。这些库提供了更加友好的界面以及跨平台支持能力,能够显著减少工作量。 --- ### 总结 无论采取哪种方式,在实际运用过程中都需要充分考虑到目标设备架构差异所带来的兼容性挑战;另外还需注意版权许可方面的要求以免触犯法律风险。
评论 62
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿力猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值