当前位置: 首页 > news >正文

网站设计的初衷软文标题

网站设计的初衷,软文标题,wordpress url地址,桑拿网络推广方案一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息&#xff0…

一、引言

从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts:

打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显示时间戳;“dts”实际是AVPacket结构体中的成员变量dts,是以AVStream->time_base为单位的解码时间戳。音频跟视频不一样,音频没有B帧,所以音频的pts和dts输出顺序一样,即pts等于dts。上述的这些值都是通过fftools/ffprobe.c中的show_packet函数打印出来的:

static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
//...print_ts  ("pts",             pkt->pts);
//...print_ts  ("dts",             pkt->dts);
//...
}

本文讲述上述pts、dts的值是怎样被计算出来的。如果想直接看结论,可以跳到本文的最后,直接看“总结”。

二、FFmpeg源码中计算WAV音频文件每个packet的pts和dts的实现

FFmpeg得到每个packet的pts和dts的过程,实际也是解封装(解复用)的过程。

(一)对FFFormatContext结构体的AVPacket类型成员变量pkt进行初始化

FFmpeg对WAV音频文件进行解封装(解复用)时,首先会调用avformat_alloc_context函数分配解复用器上下文(AVFormatContext)。而avformat_alloc_context函数内部会调用av_packet_alloc函数给FFFormatContext结构体的AVPacket类型成员变量pkt分配内存,对pkt的成员变量进行初始化:

AVFormatContext *avformat_alloc_context(void)
{FFFormatContext *const si = av_mallocz(sizeof(*si));
//...si->pkt = av_packet_alloc();
//...return s;
}

 从文章《FFmpeg源码:av_init_packet、get_packet_defaults、av_packet_alloc函数分析》中可以知道,av_packet_alloc函数内部会调用get_packet_defaults函数。所以执行av_packet_alloc函数后,FFFormatContext结构体的成员变量pkt的成员pts、dts的值会变为AV_NOPTS_VALUE,也就是十进制的:-9223372036854775808。

(二)对FFStream结构体的成员变量cur_dts进行初始化

调用完avformat_alloc_context函数后,FFmpeg会调用avformat_open_input函数打开WAV音频文件。而avformat_open_input函数内部会调用wav_read_header函数解码WAV Header,关于wav_read_header函数具体可以参考:《音视频入门基础:WAV专题(5)——FFmpeg源码中解码WAV Header的实现》。然后wav_read_header函数内部又会调用avformat_new_stream函数创建音频流。avformat_new_stream函数内部会执行语句:sti->cur_dts = RELATIVE_TS_BASE对FFStream结构体的成员变量cur_dts进行初始化:

AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{FFFormatContext *const si = ffformatcontext(s);FFStream *sti;
//...sti = av_mallocz(sizeof(*sti));
//...if (s->iformat) {
//.../* we set the current DTS to 0 so that formats without any timestamps* but durations get some timestamps, formats with some unknown* timestamps have their first few packets buffered and the* timestamps corrected before they are returned to the user */sti->cur_dts = RELATIVE_TS_BASE;
//...}return NULL;
}

从《FFmpeg源码:RELATIVE_TS_BASE宏定义和is_relative函数分析》中可以知道,RELATIVE_TS_BASE的值为十进制的9223090561878065151,所以执行avformat_new_stream函数后,FFStream结构体的成员变量cur_dts会被初始化为9223090561878065151。

(三)compute_pkt_fields函数

调用完avformat_open_input函数后,FFmpeg会调用avformat_find_stream_info函数读取媒体的部分packet(数据包)以获取码流信息。而avformat_find_stream_info函数内部会调用read_frame_internal函数,read_frame_internal函数内部又会调用compute_pkt_fields函数。通过compute_pkt_fields函数可以获取每个packet的pts和dts:

static void compute_pkt_fields(AVFormatContext *s, AVStream *st,AVCodecParserContext *pc, AVPacket *pkt,int64_t next_dts, int64_t next_pts)
{FFFormatContext *const si = ffformatcontext(s);FFStream *const sti = ffstream(st);int num, den, presentation_delayed, delay;int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&st->codecpar->codec_id != AV_CODEC_ID_HEVC &&st->codecpar->codec_id != AV_CODEC_ID_VVC;
//.../* do we have a video B-frame ? */delay = sti->avctx->has_b_frames;presentation_delayed = 0;
//.../* Interpolate PTS and DTS if they are not present. We skip H264* currently because delay and has_b_frames are not reliably set. */if ((delay == 0 || (delay == 1 && pc)) && onein_oneout) {if (presentation_delayed) {//...}else if (pkt->pts != AV_NOPTS_VALUE ||pkt->dts != AV_NOPTS_VALUE ||pkt->duration > 0             ) {/* presentation is not delayed : PTS and DTS are the same */if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = pkt->dts;update_initial_timestamps(s, pkt->stream_index, pkt->pts,pkt->pts, pkt);if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = sti->cur_dts;pkt->dts = pkt->pts;if (pkt->pts != AV_NOPTS_VALUE && duration.num >= 0)sti->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);}}
//...
}

compute_pkt_fields函数内部,由于音频的压缩编码格式不可能是H.264、HEVC(H.265)、VVC(H.266),所以局部变量onein_oneout的值为1:

int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&st->codecpar->codec_id != AV_CODEC_ID_HEVC &&st->codecpar->codec_id != AV_CODEC_ID_VVC;

音频跟视频不一样,音频没有B帧,所以局部变量delay的值为0。局部变量presentation_delayed的值为0:

/* do we have a video B-frame ? */
delay = sti->avctx->has_b_frames;
presentation_delayed = 0;

所以表达式:(delay == 0 || (delay == 1 && pc)) && onein_oneout为真,执行大括号里的内容:

    /* Interpolate PTS and DTS if they are not present. We skip H264* currently because delay and has_b_frames are not reliably set. */if ((delay == 0 || (delay == 1 && pc)) &&onein_oneout) {

从《音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现》中可以知道,音频文件的格式正常的情况下,pkt->duration 肯定是大于0的,所以会执行下面大括号里的内容:

else if (pkt->pts != AV_NOPTS_VALUE ||pkt->dts != AV_NOPTS_VALUE ||pkt->duration > 0             ) {/* presentation is not delayed : PTS and DTS are the same */if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = pkt->dts;update_initial_timestamps(s, pkt->stream_index, pkt->pts,pkt->pts, pkt);if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = sti->cur_dts;pkt->dts = pkt->pts;if (pkt->pts != AV_NOPTS_VALUE && duration.num >= 0)sti->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);}

 从上面可以知道FFFormatContext结构体的成员变量pkt的成员pts、dts的值会在avformat_alloc_context函数中被av_packet_alloc函数初始化为AV_NOPTS_VALUE,所以会执行下面语句,让pkt->pts = pkt->dts = AV_NOPTS_VALUE:

            /* presentation is not delayed : PTS and DTS are the same */if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = pkt->dts;

然后由于pkt->pts等于AV_NOPTS_VALUE,所以会执行pkt->pts = sti->cur_dts:

if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = sti->cur_dts;
pkt->dts = pkt->pts;

下面分情况讨论:

1.第一个packet的pts和dts

从上面可以知道,执行avformat_new_stream函数后,sti->cur_dts会被初始化为RELATIVE_TS_BASE(9223090561878065151)。所以对于第一个packet,其pkt->pts和pkt->dts的值会变为RELATIVE_TS_BASE(9223090561878065151):

if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = sti->cur_dts;
pkt->dts = pkt->pts;

这时候表达式:pkt->pts != AV_NOPTS_VALUE && duration.num >= 0为真,所以执行语句:sti->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1),让sti->cur_dts = pkt->pts + (1 × duration ÷ st->time_base)。关于av_add_stable函数的用法可以参考:《FFmpeg源码:av_rescale_rnd、av_rescale_q_rnd、av_rescale_q、av_add_stable函数分析》:

if (pkt->pts != AV_NOPTS_VALUE && duration.num >= 0)sti->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);

从《FFmpeg源码:compute_frame_duration函数分析》中可以知道,duration.num为该音频packet占用的以AVStream的time_base为单位的时间值,duration.den为该音频的采样频率(单位为Hz);从《音视频入门基础:WAV专题(8)——FFmpeg源码中计算WAV音频文件AVStream的time_base的实现》中可以知道st->time_base.num为1,st->time_base.den为音频采样频率;

所以语句sti->cur_dts = pkt->pts + (1 × duration ÷ st->time_base) 等价于

sti->cur_dts = pkt->pts + duration.num。

sti->cur_dts为下一个音频packet的pts和dts,也就是说下一个音频packet的pts和dts的值是在上一个音频packet的pts和dts基础上增加duration.num。

2.第一个packet之后的packet的pts和dts

对于第一个packet之后的packet,比如第二个packet。再次调用compute_pkt_fields函数时,会继续执行语句: pkt->pts = sti->cur_dts,得到sti->cur_dts中保存的下一个packet的dts和pts:

if (pkt->pts == AV_NOPTS_VALUE)pkt->pts = sti->cur_dts;

(四)av_read_frame函数

调用完avformat_find_stream_info函数后,FFmpeg会调用av_read_frame函数从文件中读取数据包。av_read_frame函数内部会执行:

    if (is_relative(pkt->dts))pkt->dts -= RELATIVE_TS_BASE;if (is_relative(pkt->pts))pkt->pts -= RELATIVE_TS_BASE;

让该packet的pts和dts减去RELATIVE_TS_BASE(9223090561878065151)。从而得到最终的pts和dts。

三、总结

1.音频跟视频不一样,音频没有B帧,所以音频的pts和dts输出顺序一样,即pts等于dts。

2.对于音频,其第1个packet的pts和dts的值为0。之后的每个packet的pts和dts值在上一个音频packet的pts和dts基础上增加duration,也就是增加该音频packet占用的以AVStream的time_base为单位的时间值。

举个例子,某音频文件,其第1个packet的pts和dts值为0,duration值为4096。所以第2个packet的pts和dts值为0 + 4096 = 4096。第3个packet的pts和dts值为4096 + 4096 = 8192:

关于duration的概念可以参考:《音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现》

http://www.dinnco.com/news/49119.html

相关文章:

  • 网站界面用什么做百度应用商店app
  • 网站可以做哪些广告网站推广的常用方法有哪些?
  • 自己的网站做微信接口平台百度推广手机客户端
  • 博物馆布展设计公司排名北京seo排名优化网站
  • 建设银行官方网站登整站seo排名要多少钱
  • 聊城商城网站建设营销型网站建设公司价格
  • 印花图案设计网站成都网络营销策划
  • 带后台的html网站源码成都自动seo
  • 在线购物网站建设潍坊网站建设
  • 做网站如何实现url拦截东莞网络推广哪家公司奿
  • wordpress 上一页 下一页广州谷歌优化
  • wordpress手机登录代码太原百度推广排名优化
  • 播州区建设局网站手机网站怎么优化关键词
  • 天津有哪些好的做网站公司网站免费建站app
  • 江苏cms建站系统微信营销工具
  • 官方网站建设的必要沈阳今天刚刚发生的新闻
  • 青岛公司网站设计关键词你们都搜什么
  • 各种网站名称大全广东省白云区
  • jquery网站后台推广计划怎么做
  • 福建联美建设集团有限公司网站海外seo培训
  • 网站建设方案模板重庆搜索排名提升
  • 企业网站建设费在会计上哈尔滨最新疫情通报
  • 江苏省住房和城乡建设委员会官方网站淘宝新店怎么快速做起来
  • 外贸付款方式重庆网站优化软件
  • 如何把自己做的网站发布到网上搜索引擎营销的主要方式有
  • 杭州网站建设前三广东又出现新病毒
  • 设置网站模板百度竞价员
  • 学院网站建设总结bt磁力猪
  • 承接博彩网站建设网站如何推广
  • 怎么样做淘宝优惠券网站实体店怎么引流推广