FFMPeg代码分析:AVPacket结构体和av_read_frame函数

2023-11-23 04:58

本文主要是介绍FFMPeg代码分析:AVPacket结构体和av_read_frame函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AVPacket结构用于保存压缩编码过的数据。在解码时,该结构的实例通常作为解复用器(demuxer)的输出并输入到解码器中;在编码时,通常是编码器的输出,并输入到复用器(muxer)中。该结构体的定义如下:

typedef struct AVPacket {/*** A reference to the reference-counted buffer where the packet data is* stored.* May be NULL, then the packet data is not reference-counted.*/AVBufferRef *buf;/*** Presentation timestamp in AVStream->time_base units; the time at which* the decompressed packet will be presented to the user.* Can be AV_NOPTS_VALUE if it is not stored in the file.* pts MUST be larger or equal to dts as presentation cannot happen before* decompression, unless one wants to view hex dumps. Some formats misuse* the terms dts and pts/cts to mean something different. Such timestamps* must be converted to true pts/dts before they are stored in AVPacket.*/int64_t pts;//显示时间戳/*** Decompression timestamp in AVStream->time_base units; the time at which* the packet is decompressed.* Can be AV_NOPTS_VALUE if it is not stored in the file.*/int64_t dts;//解码时间戳uint8_t *data;//实例所包含的压缩数据,直接获取该指针指向缓存的数据可以得到压缩过的码流;int   size;//原始压缩数据的大小int   stream_index;//标识当前AVPacket所从属的码流/*** A combination of AV_PKT_FLAG values*/int   flags;/*** Additional packet data that can be provided by the container.* Packet can contain several types of side information.*/struct {uint8_t *data;int      size;enum AVPacketSideDataType type;} *side_data;int side_data_elems;/*** Duration of this packet in AVStream->time_base units, 0 if unknown.* Equals next_pts - this_pts in presentation order.*/int   duration;
#if FF_API_DESTRUCT_PACKETattribute_deprecatedvoid  (*destruct)(struct AVPacket *);attribute_deprecatedvoid  *priv;
#endifint64_t pos;                            ///< byte position in stream, -1 if unknown/*** Time difference in AVStream->time_base units from the pts of this* packet to the point at which the output from the decoder has converged* independent from the availability of previous frames. That is, the* frames are virtually identical no matter if decoding started from* the very first frame or from this keyframe.* Is AV_NOPTS_VALUE if unknown.* This field is not the display duration of the current packet.* This field has no meaning if the packet does not have AV_PKT_FLAG_KEY* set.** The purpose of this field is to allow seeking in streams that have no* keyframes in the conventional sense. It corresponds to the* recovery point SEI in H.264 and match_time_delta in NUT. It is also* essential for some types of subtitle streams to ensure that all* subtitles are correctly displayed after seeking.*/int64_t convergence_duration;
} AVPacket;
在demo中,调用了av_read_frame(pFormatCtx, &packet)函数从pFormatCtx所指向的环境的文件中读取压缩码流数据,保存到AVPacket实例packet中。av_read_frame()函数实现如下所示:

int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{const int genpts = s->flags & AVFMT_FLAG_GENPTS;int          eof = 0;int ret;AVStream *st;if (!genpts) {ret = s->packet_buffer ?read_from_packet_buffer(&s->packet_buffer, &s->packet_buffer_end, pkt) :read_frame_internal(s, pkt);if (ret < 0)return ret;goto return_packet;}for (;;) {AVPacketList *pktl = s->packet_buffer;if (pktl) {AVPacket *next_pkt = &pktl->pkt;if (next_pkt->dts != AV_NOPTS_VALUE) {int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;// last dts seen for this stream. if any of packets following// current one had no dts, we will set this to AV_NOPTS_VALUE.int64_t last_dts = next_pkt->dts;while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {if (pktl->pkt.stream_index == next_pkt->stream_index &&(av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0)) {if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b framenext_pkt->pts = pktl->pkt.dts;}if (last_dts != AV_NOPTS_VALUE) {// Once last dts was set to AV_NOPTS_VALUE, we don't change it.last_dts = pktl->pkt.dts;}}pktl = pktl->next;}if (eof && next_pkt->pts == AV_NOPTS_VALUE && last_dts != AV_NOPTS_VALUE) {// Fixing the last reference frame had none pts issue (For MXF etc).// We only do this when// 1. eof.// 2. we are not able to resolve a pts value for current packet.// 3. the packets for this stream at the end of the files had valid dts.next_pkt->pts = last_dts + next_pkt->duration;}pktl = s->packet_buffer;}/* read packet from packet buffer, if there is data */if (!(next_pkt->pts == AV_NOPTS_VALUE &&next_pkt->dts != AV_NOPTS_VALUE && !eof)) {ret = read_from_packet_buffer(&s->packet_buffer,&s->packet_buffer_end, pkt);goto return_packet;}}ret = read_frame_internal(s, pkt);if (ret < 0) {if (pktl && ret != AVERROR(EAGAIN)) {eof = 1;continue;} elsereturn ret;}if (av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt,&s->packet_buffer_end)) < 0)return AVERROR(ENOMEM);}return_packet:st = s->streams[pkt->stream_index];if (st->skip_samples) {uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);if (p) {AV_WL32(p, st->skip_samples);av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d\n", st->skip_samples);}st->skip_samples = 0;}if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & AV_PKT_FLAG_KEY) {ff_reduce_index(s, st->index);av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);}if (is_relative(pkt->dts))pkt->dts -= RELATIVE_TS_BASE;if (is_relative(pkt->pts))pkt->pts -= RELATIVE_TS_BASE;return ret;
}



这篇关于FFMPeg代码分析:AVPacket结构体和av_read_frame函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/415500

相关文章

Nginx服务器部署详细代码实例

《Nginx服务器部署详细代码实例》Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,:本文主要介绍Nginx服务器部署的相关资料,文中通过代码... 目录Nginx 服务器SSL/TLS 配置动态脚本反向代理总结Nginx 服务器Nginx是一个‌高性

Python容器转换与共有函数举例详解

《Python容器转换与共有函数举例详解》Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面:本文主要介绍Python容器转换与共有函数的相关资料,... 目录python容器转换与共有函数详解一、容器类型概览二、容器类型转换1. 基本容器转换2. 高级转换示

HTML5的input标签的`type`属性值详解和代码示例

《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获