FFmepg视频解码

1 前言

上一篇文章<FFmpeg下载安装及Windows开发环境设置>介绍了FFmpeg的下载安装及环境配置,本文介绍最简单的FFmpeg视频解码示例。

2 视频解码过程

本文只讨论视频解码。
FFmpeg视频解码的过程比较简单,实际就4步:

  1. 打开媒体流获取编码格式;
  2. 循环获取解码帧
  3. 显示图像
  4. 关闭流

实际上前两步即已实现视频解码。

2.1 打开媒体流获取编码格式

1 打开流文件
这个函数avformat_open_input打开一个媒体流并读取其头信息,对于实时流或者不包含头信息的视频流,此函数通过几帧数据分析以获取其信息
此函数支持的媒体流非常广泛,包括本地视频文件、远程视频流、TCP码流、UDP码流等等都支持。

m_pFmtCtx = nullptr;
ret = avformat_open_input(&m_pFmtCtx, sVideoUrl.c_str(), nullptr, nullptr);

2 在媒体流中寻找视频流
一个媒体流中可能包含了视频、音频、字幕、文本等多个流,到底哪个是我们要的视频流,需要首先确定,这个实际有两种方法,方法1是遍历媒体中所有的流,检查流类型判断哪个是视频流,找到视频流后获取其解码器

	m_nIndexVideo = -1;AVCodec* pAVCodec;//method 1for (i = 0; i < m_pFmtCtx->nb_streams; i++){if (m_pFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){m_nIndexVideo = i;break;}}if (m_nIndexVideo < 0)return false;pAVCodec = (AVCodec*)avcodec_find_decoder(m_pFmtCtx->streams[m_nIndexVideo]->codecpar->codec_id);

方法2就更简单,直接av_find_best_stream按视频格式查找最符合的流,并直接返回视频流序号及相应的解码器

	m_nIndexVideo = av_find_best_stream(m_pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, (const AVCodec**)&pAVCodec, 0);

此两种方法结果是同样的,选择其中一种方法使用即可。
3 分配解码器
根据视频流解码格式分配及设置解码器,此处得到的解码器m_pAVCodecCtx即可用于后续的连续帧的解码了

	m_pAVCodecCtx = avcodec_alloc_context3(pAVCodec);if (m_pAVCodecCtx == nullptr)return false;ret = avcodec_parameters_to_context(m_pAVCodecCtx, m_pFmtCtx->streams[m_nIndexVideo]->codecpar);

4 准备解码
调用函数avcodec_open2后,即可开始解码

	ret = avcodec_open2(m_pAVCodecCtx, pAVCodec, nullptr);

至此,一个媒体流的视频流解码工作就准备好了,可以进行获取和解码视频帧了。

2.2 获取解码帧

获取解码帧的过程是:得到一个流原始包(AVPacket),用以上的解码器从这个包里解出视频帧(AVFrame),具体过程如下:
1 用函数av_read_frame从流中取出一个帧包,此包为流中的原始数据,未解码的。
前面说过,一个媒体流中可能包含了多个流,所以av_read_frame获取的数据包不一定是我们想要的视频流包,需要根据这个包所在流的序号来判断是不是属于前面确定视频流的包。

while (1)
{ret = av_read_frame(m_pFmtCtx, m_pPkt);if (ret < 0)return nullptr;if (m_pPkt->stream_index == m_nIndexVideo)break;
}

2 解码这个包,获取一帧解码图像
用前面获得的解码器m_pAVCodecCtx对这个包进行解码,获得AVFrame。

	avcodec_send_packet(m_pAVCodecCtx, m_pPkt);avcodec_receive_frame(m_pAVCodecCtx, m_pFrame);

此时获得的m_pFrame即为已解码出的一幅视频帧,为一个AVFrame结构,此结构中包含了图像数据、宽高、格式等等信息,可以用于显示、存储等后续工作。

2.3 显示图像帧

有很多软件架构支持直接对AVFrame结构进行显示,如SDL、D3DX等等。
我们这里用最基本的RGB图像方式来显示这个AVFrame,但AVFrame的图像数据大多数是YUV格式,需要做YUV->RGB转换,当然可以自己找公式转换,实际上FFmpeg对此也提供了方便的转换方法sws_scale:

	int ret;int wid, hei;wid = pFrame->width;hei = pFrame->height;if (m_pSwsCtx == nullptr){m_pSwsCtx = sws_getContext(wid, hei, (AVPixelFormat)pFrame->format, wid, hei, AV_PIX_FMT_RGB24, SWS_POINT, nullptr, nullptr, nullptr);}uint8_t* data[1];data[0] = pDib;int lines[1] = { wid * 3 };ret = sws_scale(m_pSwsCtx, pFrame->data, pFrame->linesize, 0, hei, data, lines);

这样转出的pDib就是24位RGB的图像了,之后的显示此处就不再赘述了。

2.4 关闭流

以上打开的流,以及分配的各种资源,最后不用时记得要释放,如

	if (m_pFmtCtx != nullptr){avformat_close_input(&m_pFmtCtx);m_pFmtCtx = nullptr;}if (m_pAVCodecCtx != nullptr){avcodec_close(m_pAVCodecCtx);avcodec_free_context(&m_pAVCodecCtx);m_pAVCodecCtx = nullptr;}

3 示例

下图为程序运行视频解码结果。
在这里插入图片描述
以上代码的完整工程,已上传,供参考。地址:https://download.csdn.net/download/hangl_ciom/88152736

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

监控对象都有哪些分类

1、业务监控 这类指标是管理层非常关注的&#xff0c;代表企业营收&#xff0c;或者跟客户主流程相关&#xff0c;类似 BI 数据。不过相比 BI 数据&#xff0c;业务监控指标有两点不同。 对精确度要求没有那么高&#xff1a;因为监控只要发现趋势异常就可以&#xff0c;至于是…

极简在线商城系统,支持docker一键部署

Hmart 给大家推荐一个简约自适应电子商城系统&#xff0c;针对虚拟商品在线发货&#xff0c;支持企业微信通知&#xff0c;支持docker一键部署&#xff0c;个人资质也可搭建。 前端 后端 H2 console 运行命令 docker run -d --name mall --restartalways -p 8080:8080 -e co…

使用树莓派picow和drv8833驱动直流电机

raspberry pico w引脚图 1. 准备工作 板子编辑器raspberry pico wmicropython&#xff08;thonny编辑器&#xff09; 最新的raspberry pi pico w系统包下载地址。 点亮板载led灯 需要注意的是pico的板载led灯是GPIO25引脚&#xff0c;picow的板子led灯则直接用Pin包的&qu…

Unity 使用SharpZipLib解压时报错

报错信息&#xff1a; NotSupportedException: Encoding 936 data could not be found. Make sure you have correct international System.Text.Encoding.GetEncoding (System.Int32 codepage) ICSharpCode.SharpZipLib.Zip.ZipConstants.ConvertToString。 出现问题分析&…

【leetcode】138.复制带随机指针的链表

方法一&#xff1a;暴力求解 1️⃣遍历原链表&#xff0c;复制节点尾插 2️⃣更新random&#xff0c;原链表中的random对应第几个节点则复制链表中的random就对应第几个 &#x1f4d6;Note 不能通过节点中的val判断random的指向&#xff0c;因为链表中可能存在两个val相等的节点…

【PCB专题】案例:Allegro如何在PCB板上直接修改封装中的特定焊盘

在实际产品设计中我们很可能因为结构、封装的制约而将两个器件放的很近。并且也可能因为是接口器件,所以要求上锡量要多。 但是因为成本的原因我们很可能不会去为了几个器件增加钢网的阶数,以求获得更多的锡量,让PIN脚爬锡更好。而会通过扩大钢网开口的形式来增加锡量。 如…

代码随想录—力扣算法题:704二分查找.Java版(示例代码与导图详解)

版本说明 当前版本号[20230802]。 版本修改说明20230802初版 目录 文章目录 版本说明目录数组数组理论基础二分查找思路左闭右闭[left, right]左闭右开[left, right)两种方法的区别总结 数组 数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合。 数组可以方便…

基于Spring Boot的美食分享网站设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的美食分享网站设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java springboot…

深入解析Linux进程内存:VSS、RSS、PSS、USS及查看方式

VSS 虚拟耗用内存大小&#xff0c;是进程可以访问的所有虚拟内存的总量&#xff0c;包括进程独自占用的物理内存、和其他进程共享的内存、分配但未使用的内存。 RSS 驻留内存大小&#xff0c;是进程当前实际占用的物理内存大小&#xff0c;包括进程独自占用的物理内存、和其…

1400*C. Computer Game

Example input 6 15 5 3 2 15 5 4 3 15 5 2 1 15 5 5 1 16 7 5 2 20 5 7 3 output 4 -1 5 2 0 1 解析&#xff1a; k个电&#xff0c; 第一种为 k>a 时&#xff0c;只玩游戏 k-a; 第二种&#xff0c;k>b,一边玩一边充电 k-b 问完成n轮游戏的情况下&#xff0c;优先第…

配置VS Code 使其支持vue项目断点调试

起因 每个应用&#xff0c;不论大小&#xff0c;都需要理解程序是如何运行失败的。当我们写的程序没有按照自己写的逻辑走的时候&#xff0c;我们就会逐步一一排查问题。在平常开发过程中我们可能会借助 console.log 来排查,但是现在我们可以借助 VS Code 断点来调试项目。 前…

防火墙监控工具

防火墙监控是跟踪在高效防火墙性能中起着关键作用的重要防火墙指标&#xff0c;防火墙监控通常应包括&#xff1a; 防火墙日志监控防火墙规则监控防火墙配置监控防火墙警报监控 防火墙监控服务的一个重要方面是它应该是主动的。主动识别内部和外部安全威胁有助于在早期阶段识…

使用Gunicorn+Nginx部署Flask项目

部署-开发机上的准备工作 确认项目没有bug。用pip freeze > requirements.txt将当前环境的包导出到requirements.txt文件中&#xff0c;方便部署的时候安装。将项目上传到服务器上的/srv目录下。这里以git为例。使用git比其他上传方式&#xff08;比如使用pycharm&#xff…

【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)

【JavaEE】Spring的开发要点总结&#xff08;4&#xff09; 文章目录 【JavaEE】Spring的开发要点总结&#xff08;4&#xff09;1. Bean的作用域1.1 一个例子感受作用域的存在1.2 通过例子说明作用域的定义1.3 六种不同的作用域1.3.1 singleton单例模式&#xff08;默认作用域…

隐藏程序文档窗口工具1.0下载

在录屏或直播时有些窗口&#xff0c;比如讲稿提词器等&#xff0c;不想录进视频里&#xff0c;或者不想被观众看到&#xff0c;您可以使用这个窗口隐藏工具。 这个隐藏并不是真的隐藏了&#xff0c;我们在电脑上依然可以看到&#xff0c;但是直播或录屏工具抓取不到了&#xf…

Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单 em

&#xfeff;Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含&#xff1a;录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署&#xff0c;免费售…

android Glide加载gif动图和本地视频,Java

droid Glide加载gif动图和本地视频&#xff0c;Java //从手机存储本地加载视频 String filePath "/storage/emulated/0/Pictures/my_video.mp4"; Glide .with( context ).load( Uri.fromFile( new File( filePath ) ) ).into( imageView );//加载gif Glide .with(…

【JAVA】String ,StringBuffer 和 StringBuilder 三者有何联系?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言StringBufferStringBuffer方法 StringBuilderStringBuilder方法 String &#xff0c;StringBuffer 和 StringBuilder的区别String和StringBuffer互相转换 前言 在之前的文章…

改变C++中私有变量成员的值

1、没有引用的情况&#xff1a; #include <iostream> #include <queue> using namespace std; class Person { public:queue<int>que; public:queue<int> getQueue(){return que;}void push(int a){que.push(a);}void pop(){que.pop();} };int main()…

SpringBoot2学习笔记

信息来源&#xff1a;https://www.bilibili.com/video/BV19K4y1L7MT?p5&vd_source3969f30b089463e19db0cc5e8fe4583a 作者提供的文档&#xff1a;https://www.yuque.com/atguigu/springboot 作者提供的代码&#xff1a;https://gitee.com/leifengyang/springboot2 ----…