ffmpeg编解码——数据包(packet)概念(如何正确处理数据包中的显示时间戳pts与解码时间戳dts关系?)

文章目录

  • FFmpeg编解码——数据包(Packet)概念
    • 1. 数据包(Packet)简介
    • 2. 数据包(Packet)在FFmpeg中的应用
      • 2.1 从媒体文件读取数据包
      • 2.2 向媒体文件写入数据包
    • 3. 数据包(Packet)相关问题与解决方案
      • 3.1 数据包内存管理
      • 3.2 时间戳处理
    • 4. 如何正确处理数据包中的pts(显示时间戳:Presentation Time Stamp)、dts(解码时间戳:Decoding Time Stamp)关系?
      • 1. PTS与DTS简介
        • 1.1 PTS (Presentation Time Stamp)
        • 1.2 DTS (Decoding Time Stamp)
      • 2. PTS与DTS的关系
      • 3. 如何处理PTS和DTS
    • 5. 相关疑问
      • 为什么我视频的第一帧I帧的PTS与DTS不一样,PTS为0,DTS为-2002?

FFmpeg编解码——数据包(Packet)概念

FFmpeg是一个完全开源的音视频编解码库,它不仅包含了众多的音视频编解码算法,而且还提供了用于音视频处理的工具。本文将主要介绍FFmpeg中关于数据包(Packet)的相关概念和应用。

1. 数据包(Packet)简介

在FFmpeg中,数据包(Packet)是存储压缩编码数据的基本单位。数据包可以包含一个或多个编码帧的数据(也存在多个数据包包含一个编码帧的不同片段的情况)。在音频编码中,通常一个数据包只包含一帧数据;但在视频编码中,由于B帧和P帧的存在,可能会出现一个数据包包含多帧数据的情况。

typedef struct AVPacket {AVBufferRef *buf;  int64_t pts;int64_t dts;uint8_t *data;int   size;int   stream_index;int   flags;AVPacketSideData *side_data;int side_data_elems;
} AVPacket;

AVPacket是FFmpeg中定义的数据包结构,其主要字段包括:

  • buf:指向数据包内存的引用。
  • ptsdts:分别代表显示时间戳和解码时间戳。
  • datasize:指向数据包的数据和大小。
  • stream_index:该数据包属于哪个流。
  • flags:标志位,如关键帧等。
  • side_dataside_data_elems:存储额外的数据和元素数量。

2. 数据包(Packet)在FFmpeg中的应用

数据包在FFmpeg编解码过程中扮演着至关重要的角色。以下是其主要应用:

2.1 从媒体文件读取数据包

在使用FFmpeg从媒体文件读取数据时,我们需要先打开文件,然后循环调用av_read_frame()函数来读取数据包。以下是相关代码:

AVFormatContext *pFormatCtx = avformat_alloc_context();
if(avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0){printf("Couldn't open input stream.\n");return -1;
}AVPacket packet;
while(av_read_frame(pFormatCtx, &packet)>=0){// do something with packet
}

2.2 向媒体文件写入数据包

向媒体文件写入数据也是通过数据包实现的。具体操作是创建一个数据包,然后将编码后的数据填充到数据包中,最后调用av_interleaved_write_frame()av_write_frame()函数将数据包写入媒体文件。

AVFormatContext *pFormatCtx = NULL;
avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, outfile);
// ...AVPacket pkt;
av_new_packet(&pkt,data_size);
memcpy(pkt.data,framebuf,data_size);
pkt.stream_index = video_st->index;
ret = av_interleaved_write_frame(pFormatCtx, &pkt);

3. 数据包(Packet)相关问题与解决方案

在实际使用中,可能会遇到一些关于数据包的问题。以下是一些常见问题及其解决方案:

3.1 数据包内存管理

FFmpeg在处理数据包时,会自动分配和释放内存。为了防止内存泄露,我们需要在每次处理完一个数据包后,调用av_packet_unref()函数来释放数据包所占用的内存。

AVPacket pkt;
while(av_read_frame(pFormatCtx, &pkt)>=0){// do something with packetav_packet_unref(&pkt);
}

3.2 时间戳处理

在处理音视频同步等问题时,需要正确处理数据包中的ptsdts时间戳。FFmpeg提供了av_packet_rescale_ts()函数,可以用来将数据包中的时间戳从一个时间基准转换到另一个时间基准。

AVPacket pkt;
// ...
av_packet_rescale_ts(&pkt, in_time_base, out_time_base);

4. 如何正确处理数据包中的pts(显示时间戳:Presentation Time Stamp)、dts(解码时间戳:Decoding Time Stamp)关系?

在使用FFmpeg进行音视频编解码时,我们会遇到两个重要的概念:PTS(Presentation Time Stamp)和DTS(Decoding Time Stamp)。这两者都是时间戳,但用途不同。正确理解和处理它们对于实现流畅的播放和准确的音视频同步至关重要。

1. PTS与DTS简介

1.1 PTS (Presentation Time Stamp)

PTS指的是“显示时间戳”,表示何时应该将帧显示出来。也就是说,当媒体播放器读取一个带有PTS的数据包时,它会等待直到PTS指定的时间,然后再显示这一帧。

1.2 DTS (Decoding Time Stamp)

DTS指的是“解码时间戳”,表示何时应该开始解码这一帧。由于B-frames可能依赖于后续的帧,所以需要先解码后续的帧,因此DTS可能较原来稍大(要等待其参考帧解码后,它才能解码)。

在这里插入图片描述

20231210:经过我的初步观察,ffprobe -show_packets xxx显示packets顺序为解码顺序,不是显示顺序,显示顺序是乱的。要看显示顺序,直接看每个packet的pts,由小到大就是显示顺序。

在这里插入图片描述

2. PTS与DTS的关系

在没有B-frames的情况下,每一帧的PTS和DTS是相同的,因为解码顺序和显示顺序是相同的。然而,如果存在B-frames,那么解码顺序和显示顺序就可能不同,因此PTS和DTS也可能不同。

对于B-frames,其PTS通常大于前一帧的PTS,但DTS可能小于前一帧的DTS。这是因为B-frames需要依赖其后面的帧来解码,因此需要先解码后面的帧。

如图,第二个B帧,其解码时间戳(0)比第一个B帧的解码时间戳(1001)还要题前:

在这里插入图片描述

3. 如何处理PTS和DTS

当从文件中读取数据包时,我们需要确保正确地处理PTS和DTS。下面是一个例子:

AVPacket packet;
while (av_read_frame(format_context, &packet) >= 0) {// Convert the timestamps from the packet's time_base to the stream's time_base.packet.pts = av_rescale_q(packet.pts, format_context->streams[packet.stream_index]->time_base, stream->time_base);packet.dts = av_rescale_q(packet.dts, format_context->streams[packet.stream_index]->time_base, stream->time_base);// Do something with the packet...
}

在这个例子中,av_rescale_q()函数用于将时间戳从一个时间基准转换到另一个时间基准。这是必要的,因为不同的流可能有不同的时间基准。

另外,在写入数据包到文件时,也需要确保正确地设置PTS和DTS。否则,播放器可能无法正确地播放生成的文件。下面是一个例子:

AVPacket packet;
// Fill the packet...// Set the PTS and DTS.
packet.pts = next_pts++;
packet.dts = next_dts++;// Write the packet.
if (av_interleaved_write_frame(format_context, &packet) < 0) {// Handle the error...
}

在这个例子中,next_ptsnext_dts变量用于存储下一个PTS和DTS。每写入一个数据包,就将它们增加1。

总的来说,正确处理PTS和DTS是音视频编解码中非常重要的一步,它可以保证我们得到的结果文件能够被正确地播放。

5. 相关疑问

为什么我视频的第一帧I帧的PTS与DTS不一样,PTS为0,DTS为-2002?

在这里插入图片描述

解释:

在一些情况下,视频的第一帧(I帧)的PTS(Presentation Time Stamp,显示时间戳)和DTS(Decoding Time Stamp,解码时间戳)可能不同。这主要是由于视频编码中的时间基准设置。

通常情况下,我们期望视频的第一帧I帧的PTS和DTS都为0,因为它是视频播放的起点。然而,在某些视频流中,可能会出现I帧的DTS小于PTS的情况,这主要是为了容纳后续可能出现的B帧。如你所提到的例子,DTS为-2002,这意味着解码器需要在实际播放前提前开始解码。

但这种情况在播放时并不会影响正常观看,因为播放设备会根据PTS进行正确的帧显示。当然,如果你需要对视频进行进一步处理(比如编辑或转码等),那么可能就需要调整时间戳以确保它们从0开始。

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

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

相关文章

【EI会议征稿中|IEEE出版】第三届信息技术与当代体育国际学术会议(TCS 2023)

【IEEE出版】第三届信息技术与当代体育国际学术会议&#xff08;TCS 2023&#xff09; 2023 3rd International Conference on Information Technology and Contemporary Sports 2023年第三届信息技术与当代体育国际学术会议&#xff08;TCS 2023&#xff09;将于2023年12月2…

Dueling DQN 跑 Pendulum-v1

gym-0.26.1 Pendulum-v1 Dueling DQN 因为还是DQN,所以我们沿用double DQN,然后把 Qnet 换成 VAnet。 其他的不变&#xff0c;详情参考前一篇文章。 class VA(nn.Module):"""只有一层隐藏层的A网络和V网络"""def __init__(self, state_dim, hidd…

子目录文件夹图片汇总

import os import shutildef collect_images(source_folder, target_folder):# 遍历主文件夹及其所有子文件夹for root, dirs, files in

位1的个数

题目链接 位1的个数 题目描述 注意点 输入必须是长度为 32 的 二进制串 解答思路 位运算判断每一位是否为1 代码 public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n) {int res 0;for (int i 0; i < 32; i) {res …

项目经理和产品经理该如何选择?

最近很多人咨询“项目经理跟产品经理该怎么选&#xff0c;我更适合哪个&#xff1f;”“项目经理跟产品经理哪个更有钱途 ”“项目经理转产品经理好转吗”等等&#xff0c;今天就一次性说清楚项目经理跟产品经理有什么区别&#xff0c;应该怎么选择。 不想看长篇大论的&#x…

Python+Pytest接口自动化之HTTP协议基础

HTTP协议简介 HTTP 即 HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09;&#xff0c;是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件都必须遵守这个标准。 设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。HTTP 协议在 OSI 模型…

Kubernetes版本升级到v1.18.0方法

升级k8s版本才能使用kube-prometheus安装监控 1、查看集群状态 [rootk8s-master k8s-script]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready master 5d22h v1.18.0 k8s-slave1 Ready <none> 4d10h v1.18.0 k…

ActiveMQ使用指南

介绍 ActiveMQ是Apache开源组织旗下的一个项目&#xff0c;是一个流行的开源消息中间件。它完全支持JMS1.1和J2EE1.4规范的JMS Provider实现&#xff0c;并且是纯Java开发的产品。ActiveMQ支持多种语言编写客户端&#xff0c;包括C,C,C#,Perl,PHP,Ruby,Ajax等&#xff0c;同时…

做数据分析为何要学统计学(6)——什么问题适合使用卡方检验?

卡方检验作为一种非常著名的非参数检验方法&#xff08;不受总体分布因素的限制&#xff09;&#xff0c;在工程试验、临床试验、社会调查等领域被广泛应用。但是也正是因为使用的便捷性&#xff0c;造成时常被误用。本文参阅相关的文献&#xff0c;对卡方检验的适用性进行粗浅…

【unity】如何用Unity获取Windows桌面

【背景】 默认的Unity可实现的屏幕共享仅仅针对Unity编辑器的编辑窗口中的Camera展现的内容。本篇研究如何实现用Unity实时反映Windows桌面窗口画面。 【准备插件】 下载地址&#xff1a; https://download.csdn.net/download/weixin_41697242/88623496 将解压后的文件夹直…

Feign-自定义配置

目录 一、自定义Feign配置 二、修改日志级别 方式一&#xff1a;application配置文件方式 方式二&#xff1a;java代码方式 三、总结 一、自定义Feign配置 二、修改日志级别 配置Feign日志有两种方式 方式一&#xff1a;application配置文件方式 &#xff08;1&#xff09…

目标检测DOTA数据集提取感兴趣类别数据

DOTA数据集 DOTA数据集包含2806张航空图像&#xff0c;尺寸大约从800x800到4000x4000不等&#xff0c;包含15个类别共计188282个实例。其标注方式为四点确定的任意形状和方向的四边形&#xff08;区别于传统的对边平行bbox&#xff09;。类别分别为&#xff1a;plane, ship, s…

前端八股文

前端八股文 目录 前端八股文1.css选择优先级&#xff1f;2.px与rem区别&#xff1f;3.重绘与重排的区别&#xff1f;4.元素水平垂直居中的方法&#xff1f;5.什么是闭包&#xff0c;闭包有什么特点&#xff1f;6.什么是事件委托&#xff1f;7.什么是原型链&#xff1f;8.new操作…

交易历史记录20231205 记录

昨日回顾&#xff1a; select top 10000 * from dbo.CODEINFO A left join dbo.全部&#xff21;股20231205010101 B ON A.CODE B.代码 left join dbo.全部&#xff21;股20231205CONF D on A.CODED.代码left join dbo.全部&#xff21;股20231205 G on A.CODEG.代码 left…

LeetCode-合并有序链表问题

1.合并两个有序链表 题目描述&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 思路&#xff1a; 首先建立一个头节点方便后续操作&#xff0c;然后开始循环将两个链表的节点值进行比较&#xff0c;如果list1…

Windows Subsystem for Linux (WSL) 安装与使用笔记

文章目录 Part.I IntroductionPart.II 安装Chap.I 安装流程Chap.II 迁移至其他盘 Part.III 使用Chap.I 一些信息Chap.II 配置下载软件的源Chap.III 安装 pip Reference Part.I Introduction Windows Subsystem for Linux 简写为 WSL&#xff0c;是 Windows 的一个 Linux 子系统…

常用的建表但范式、反规范化

规范化&#xff1a; 规范化是用于数据库设计的一系列原理和技术&#xff0c;它可以减少表中数据的冗余&#xff0c;增加数据完整性和一致性。通常有很多范式。 第一范式&#xff08;1NF&#xff09;&#xff1a; 常用的三种范式&#xff1a; 表中的字段都是不可再分割的原子属…

蝴蝶Butterfly 数据集VOC+yolo-2000张(labelImg标注)

蝴蝶被誉为“会飞的花朵”&#xff0c;是一类非常美丽的昆虫。蝴蝶大多数体型属于中型至大型&#xff0c;翅展在15~260毫米之间&#xff0c;有2对膜质的翅。体躯长圆柱形&#xff0c;分为头、胸、腹三部分。体及翅膜上覆有鳞片及毛&#xff0c;形成各种色彩斑纹。今天要介绍的是…

算法导论复习(二)

算法导论第二次复习以 分治法 为专题 文章目录 分治算法是什么归并排序Strassen矩阵乘法最近点对 求解递推表达式 分治算法是什么 归并排序 代码如下&#xff1a; #include <iostream> #include <vector>using namespace std;// 归并函数&#xff0c;将两个有序数…

代码随想Day36 | 435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 这道题和前一天的射箭题目思想类似&#xff0c;用总区间个数-不重叠的区间个数等于需要去除的区间个数。首先对左边界排序&#xff0c;如果当前的左边界大于等于上一区间的右边界&#xff0c;则说明是一个不重叠的区间&#xff0c;否则&#xff0c;更新上一重…