来源:http://www.xuebuyuan.com/1466771.html

FFMPEG处理音频时间戳的主要逻辑

2013年12月09日 ⁄ 综合 ⁄ 共 2226字 ⁄ 字号 ⁄ 评论关闭
 

FFMPEG处理音频时间戳的主要逻辑是:

1. demux读取AVPacket。以输入flv为例,timebase是1/1000,第一个音频包可能是46,代表0.046秒。

2. decoder解码AVPacket为AVFrame,frame的pts为NOPTS,需要设置,否则后面都会有问题。主要是调用:av_rescale_delta:

AVRational in_tb = decoded_frame_tb;
AVRational fs_tb = (AVRational){1, ist->codec->sample_rate};
int duration = decoded_frame->nb_samples;
AVRational out_tb = (AVRational){1, ist->codec->sample_rate}; decoded_frame->pts = av_rescale_delta(in_tb, decoded_frame->pts, fs_tb, duration, &rescale_last_pts, out_tb);

相当于下面的逻辑:

// init the rescale_last_pts, set to 0 for the first decoded_frame->pts is 0
if (rescale_last_pts == AV_NOPTS_VALUE) {
rescale_last_pts = av_rescale_q(decoded_frame->pts, in_tb, fs_tb) + duration;
}
// the fs_tb equals to out_tb, so decoded_frame->pts equals to rescale_last_pts
decoded_frame->pts = av_rescale_q(rescale_last_pts, fs_tb, out_tb);;
rescale_last_pts += duration;

还可以简化为:

    /**
* for audio encoding, we simplify the rescale algorithm to following.
*/
if (rescale_last_pts == AV_NOPTS_VALUE) {
rescale_last_pts = 0;
}
decoded_frame->pts = rescale_last_pts;
rescale_last_pts += decoded_frame->nb_samples; // duration

实际上就是以nb_samples为时长,让pts为这个的总和,累积的samples就可以。因为默认把tb设置为sample_rate,所以samples数目就是pts。

3. filter过滤,实际上没有处理。

        // correct the pts
int64_t filtered_frame_pts = AV_NOPTS_VALUE;
if (picref->pts != AV_NOPTS_VALUE) {
// rescale the tb, actual the ofilter tb equals to ost tb,
// so this step canbe ignored and we always set start_time to 0.
filtered_frame_pts = av_rescale_q(picref->pts, ofilter->inputs[0]->time_base, ost->codec->time_base)
- av_rescale_q(start_time, AV_TIME_BASE_Q, ost->codec->time_base);
} // convert to frame
avfilter_copy_buf_props(filtered_frame, picref);
printf("filter -> picref_pts=%"PRId64", frame_pts=%"PRId64", filtered_pts=%"PRId64"\n",
picref->pts, filtered_frame->pts, filtered_frame_pts);
filtered_frame->pts = filtered_frame_pts;

4. encoder编码,主要是生成dts。

5. muxer输出前,需要做处理。譬如输出rtmp流,要将tb变为1/1000,flv的tb,也就是毫秒单位。

另外,时间戳从零开始。

    // correct the output, enforce start at 0.
static int64_t starttime = -1;
#if 1
if (starttime < 0) {
starttime = (pkt.dts < pkt.pts)? pkt.dts : pkt.pts;
}
pkt.dts -= starttime;
pkt.pts -= starttime;
#endif #if 1
// rescale audio ts to AVRational(1, 1000) for flv format.
AVRational flv_tb = (AVRational){1, 1000};
pkt.dts = av_rescale_q(pkt.dts, ost->codec->time_base, flv_tb);
pkt.pts = av_rescale_q(pkt.pts, ost->codec->time_base, flv_tb);
#endif

6. 最后一步,写入:

    ret = av_interleaved_write_frame(oc, &pkt);

就OK了。

FFMPEG处理音频时间戳的主要逻辑的更多相关文章

  1. [总结]FFMPEG视音频编解码零基础学习方法--转

    ffmpeg编解码学习   目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...

  2. FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  3. 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

    http://blog.csdn.net/leixiaohua1020/article/details/25430449 本文介绍一个最简单的基于FFMPEG的音频编码器.该编码器实现了PCM音频采样 ...

  4. FFMPEG视音频编解码零基础学习方法-b

    感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...

  5. [总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  6. [Audio processing] FFMPEG转音频格式和采样率

    利用FFMPEG转音频格式和采样率 import os import string import subprocess as sp #Full path of ffmpeg FFMPEG_BIN = ...

  7. 【转】[总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  8. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——解码篇:(二)用ffmpeg解码音频

    其实这篇的内容和(一)用ffmpeg解码视频基本是一样的,重点还是给ffmpeg指定callback函数,而这个函数是从RTSP服务端那里获取音频数据的. 这里,解码音频的示例代码量之所以比解码视频的 ...

  9. C# 使用 ffmpeg 进行音频转码

    先放一下 ffmpeg 的官方文档以及下载地址: 官方文档:http://ffmpeg.org/ffmpeg.html 下载地址:http://ffmpeg.org/download.html 用 f ...

随机推荐

  1. pycharm运行过程中pycharm控制台和python控制台之间的切换

    有时候在调试(debug)python代码的时候,希望像matlab那样输入某一个变量以查看其值,这是需要把pycharm的console切换到python的console,以输入变量查看其值,点击那 ...

  2. code 1716

    # import_company def test_import_company(self): headers=self.headers headers["Content-Type" ...

  3. pacemaker和keepalived的区别

    1.pacemaker Pacemaker 是一款开源的高可用资源管理软件,适合大集群或者小集群. Pacemaker 由Novell支持,SLES HAE就是用Pacemaker来管理集群,并且Pa ...

  4. 【BigData】Java基础_ArrayList的使用

    ArrayList概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. 数组有自身的特点,不变性,一旦数组被初始化,那么其长度就固定了,不 ...

  5. 2018-2019-2 网络对抗技术 20165318 Exp7 网络欺诈防范

    2018-2019-2 网络对抗技术 20165318 Exp7 网络欺诈防范 原理与实践说明 实践目标 实践内容概述 基础问题回答 实践过程记录 简单应用SET工具建立冒名网站 ettercap D ...

  6. PHP strlen 对中文 的定义

    $zhStr = ‘您好,中国!’; // gbk编码下每个中文字符所占字节为2echo strlen($zhStr); // 输出:12 //utf-8编码下每个中文字符所占字节为3 echo st ...

  7. bolt继承关系和区别

    先上个图:  具体区别: IRichBolt/IBasicBolt 区别IRichBolt和IBasicBolt IRichBolt继承自IBolt和IComponent.IBasicBolt继承自I ...

  8. 第七节:Asp.Net Core内置日志和整合NLog(未完)

    一. Asp.Net Core内置日志 1. 默认支持三种输出方式:控制台.调试(底部输出窗口).EventSource,当然也可以在Program类中通过logging.ClearProviders ...

  9. Java随堂笔记三

    今天学习了Java运算符的最后一部分 public static void main(String[] args) {        //算数运算符:+ - * / % ++ --        // ...

  10. 【Rust】Rust的安装和配置

    -----------------------参考文档------------------------------------- https://www.rust-lang.org/tools/ins ...