您的位置:首页 > 其它

时间戳问题汇总

2015-05-07 16:40 260 查看
A:RFC3984 规定采用 90000 Hz 的时钟,因此如果编码帧频是 30,那么时间戳间隔就该是 90000 / 30 = 3000,根据抓包来看,似乎时间戳间隔的确是 3000。

时间戳的间隔不固定,比如有的时间戳间隔是 2990 有的是 3002,会导致解析出来的视频出现快播的效果么?

Q:各位大侠好:

我现在正在开发视频实时流播放,简单的过程如下:

采集视频流 -> 视频流转换为Sorenson H.263编码格式 -> 把编码的实时流通过RTMP协议发送 -> flash客户端进行播放。

现在我的时间戳颗粒是这样生成的:

第一帧的时间戳为0;

第二帧的时间戳的算法为:第一个字符编码的当前时间 - 上一帧第一个字符编码的当前时间。

根据这个时间颗粒的算法,我在flash客户端播放就会产生延时。

请问各位大侠有什么好的建议或是文档之类的,以前firstime管管建议我看RFC4629文档,但是效果不太明显?谢谢!

A:时间戳顺序累加就行了,每次加1。

Q:最近做了一个捕捉摄像头并保存FLV的小东西,发现转换完毕后的FLV文件,用播放器播放的时候,速度特别快,大概是正常速度的4倍。请问这是怎么回事?网上搜了一下,说是时间戳的问题,可是PTS我跟了,***Packet的PTS是每帧增长40,time_base为: 25/s.。DTS是个无效值。PTS的计算是根据ffmpeg的例子写的。

pkt.pts= av_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);

1. dts到底需不需要自己计算?

2. 还有播放速度过快的可能原因?

3. 还有PTS和DTS的具体含义?

int64_t pts; ///< presentation time stamp in time_base units

int64_t dts; ///< decompression time stamp in time_base units

上面的意思是不是说,播放器根据PTS进行播放。然后DTS是在编码的时候自己设置?

刚用ffmpeg,好些东西不懂,还请大侠多多指教。刚才又试了一下,把time_base降为10帧每秒。播放速度和正常速度接近。但是不知道FLV文件的帧率该设置多少合适。有没有一个权威的说法。

A:我也做摄像头捕捉,跟你出现一样的问题,我自己分析的话,应该是捕捉摄像头的图像的速度只有10帧每秒,但是保存成视频25帧每秒的话播放看起来就非常快,但是我摄像头捕捉设定的是25帧每秒,难道是速度达不到?

反正我还没解决,LZ解决了的话告诉下,

谢谢。暂时认为是摄像头捕捉速率问题。换了一个高清无驱摄像头就好了

Q:在每个音视频数据包中都含有PTS和DTS,一个数据包中应该含有多个数据帧以及音频数据,那么这里的PTS和DTS它是如何来标识数据帧的?PTS和DTS的单位是什么?视频的最小单位是帧,可通过PTS来指定它何时播放,那音频的最小单位是什么?这里的PTS对音频而言它标识的是什么?是这个时间点采样点吗?

在网上找了很久关于音视频编解码的资料,都没有合适的。

A:

audio_timebase = av_q2d(fmtctx->streams[audio_index]->time_base);

video_timebase = av_q2d(fmtctx->streams[video_index]->time_base);

last_video_pts = pts * video_timebase;

last_audio_pts = pts * audio_timebase;

timebase就是单位

以audio为基准同步video。只要设置好了 ao 的参数,如sample rate, channels, sample size等, audio驱动就能以正确的速度播放,所以只要程序里write不出大问题的话,这种同步是非常有效的。

在video out里如下做:

pre_time = av_gettime();

gl_vo->vo_display(pic);

after_time = av_gettime();

rest_time = 1000*1000/fps - (after_time - pre_time);

av_diff = last_audio_pts - last_video_pts;

if ( av_diff > 0.2 )

{

if( av_diff < 0.5 ) rest_time -= rest_time / 4;

else rest_time -= rest_time / 2;

}

else if ( av_diff < -0.2)

{

if( av_diff > -0.5 ) rest_time += rest_time / 4;

else rest_time += rest_time / 2;

}

if ( rest_time > 0 )

usleep(rest_time);

Q:谢谢kf701的回复,看后明白了不少。

这种同步是音频抽样一次就与一帧图像去同步的吗?

A:上面的代码是每display一个picture,就与audio的PTS比较一下,如果没有audio,只有video,那么video就会以fps显示,靠的就是那个 usleep(rest_time)。

Q:如何利用***Packet包里的pts,dts实现音视频同步?声频播放是只管自己播放,视频有一个初始化播放帧率,如何根据***Packet里的pts,dts还实现两者的同步?

现在我的视频播放一直按原始播放帧率播放,声音有点卡!哪位知道,尽快告知小弟!

A:

DTS:decoding time stamp

PTS:presentation time stamp

Generally the PTS and DTS will only differ when the stream we are playing has B frames in it.

Q:关于b帧和时间戳的问题

我从mpeg2视频中用av_read_frame()读取视频帧并解码,顺序是IPBBPBB...

它们的pts顺序是1423756...现在我要把这个视频再用mpeg2编码,最大b帧数还是2.那么我在编码时是否要将视频数据调整为按显示时间先后的顺序,再交给avcodec_encode_video()编码?即把第2帧放在3、4帧之后,第7帧放在5、6帧之后?

A:你不能这么做,编码器会给你这么做的。如果你有B帧,那么所有的B帧都会被放在缓冲区里直到下一个I/P帧到来

例如:你的输入序列是IBBPBBPBBI

那么输出的序列是

输入I,编码I,输出I

输入B

输入B

输入P,编码P,输出P

编码B,输出B

编码B,输出B

输入P,编码P,输出P

……

在解码端所有的P帧都会被放在缓冲力直到下一个I/P真的到来

如:解码I,输出I

解码P,放入缓冲P

解码B,输出B

解码B,输出B

解码P,输出上一次P帧

Q:解码出来的图片的时间戳问题MPEG一个包中包含有时间戳,而可能几个包才能解码出一张图象,也可能一个包能解码出几张图,请问包中的时间戳与解码出来的图象如何对应上?

A:在ffmpeg中通过parser部件把从avformat部件取下来的原始包重新“合成”为有仅包含一个完整帧的包。从MPEG2部份的代码中看出,如果“几个包才能解码出一张图象”的话,会取第一个包的PTS和DTS,如果“也可能一个包能解码出几张图”,则会跟据这个包的PTS和DTS通过帧频推算出其它帧的DTS。

Q:ffmpeg的avcodec_decode_video 函数解码时间戳问题?在 VLC 中调用 avcodec_decode_video() 函数进行解码时,***Frame->pts 时间戳不对,导致我的图像不能够显示?请问有谁知道它的解码原理,这个 PTS 怎么得出的吗?还是外部传入的?

A:

is->video_st->codec->reordered_opaque= pkt->pts;

len1 = avcodec_decode_video(is->video_st->codec,

frame, &got_picture,

pkt->data, pkt->size);

if( (decoder_reorder_pts || pkt->dts == ***_NOPTS_VALUE)

&& frame->reordered_opaque != ***_NOPTS_VALUE)

pts= frame->reordered_opaque;

else if(pkt->dts != ***_NOPTS_VALUE)

pts= pkt->dts;

else

pts= 0;

pts *= av_q2d(is->video_st->time_base);

Q:我贴下 VLC 的代码,(vlc-0.9.8a/modules/codec/avcodec/video.c 文件中)

i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,

&b_gotpicture,

p_sys->i_buffer <= 0 && p_sys->b_flush ? NULL : (uint8_t*)p_sys->p_buffer, p_sys- >i_buffer );

中间省略

取得 PTS ,

if( p_sys->p_ff_pic->pts )

{

printf(" p_sys->p_ff_pic->pts = %Lx\n", p_sys->p_ff_pic->pts);

p_sys->i_pts = p_sys->p_ff_pic->pts;

}

从 ***Frame 结构中取得 这个 PTS ,但是这个 ***Frame 结构中取得 这个 PTS 从哪里取得的呢?

A:时间戳一般是在编码的时候加入到媒体文件中的,所以在解码时可以从中分析出PTS。

转自:http://blog.sina.com.cn/s/blog_99cc8f0d0101tkck.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: