ffmepg中的时间戳,是以微秒为单位,关乎timebase变量,它是作为dts、pts的时间基准粒度,数值会很大。
static intmpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
{
。。。
constint64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
//开始时,pkt->dts为0,pkt->pts为7200。
int64_tdts = pkt->dts, pts = pkt->pts;
if(ts->copyts < 1) {
if (pts != AV_NOPTS_VALUE)
pts += delay; //pts为133200
if (dts != AV_NOPTS_VALUE)
dts += delay; //dts为126000
}
。。。
}
视频
编码前,会设置帧率,如1秒25帧, 按90000的时间基,一帧就是3600。
avcodec_encode_video2成功后(如ffmpeg.c中do_video_out),pkt->pts被设置成帧序号,如33帧。
紧接着是av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);这个函数的分析如下:
void av_packet_rescale_ts(AVPacket *pkt,
AVRational src_tb, //这个是个时间基,就是我们设置的帧率(num=1,den=25)
AVRational dst_tb) //这个是视频的时间基,就是(num=1,den=90000)
{
if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); //帧序到时间的转换
if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
if (pkt->duration > 0)
pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
......
}
最终ptk->pts变成了118800,除以3600刚好就是33。
音频
音频帧的DTS/PTS计算:
一个音频帧(对于AAC来说, 是1024个采样点),
相对于音频采样率(如 44100个采样点/second = 44.1KHz)来说,
累加上每帧的增量(1024*1000/44100 = 23.219ms/frame)
1024*1000/48000= 21.333ms/frame
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000 / sample_rate
例如:sample_rate = 44100HZ时,计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。
问题:
Queue input is backward in time
Non-monotonous DTS in output stream 0:1; previous: 359040, current: 0; changing to 359041. This may result in incorrect timestamps in the output file.
*** dropping frame 100 from stream 0 at ts 0
.....
*** dropping frame 100 from stream 0 at ts 97
[hls @ 0x23015c0] Non-monotonous DTS in output stream 0:1; previous: 359227, current: 359040; changing to 359228. This may result in incorrect timestamps in the output file.
此问题由于音频突然出现了错误,导致输出音频的DTS变为0,这样为了保证音视频同步,再来的视频帧先丢掉,知道音视频DTS接近。