ffmpeg 时间戳问题汇总
http://www.cnblogs.com/loveclover/archive/2011/03/23/1993065.html
问题是这样的 用一个 VLC(流媒体客户端) 去请求流媒体服务器上的数据, 但是获得的数据播放速度明显快于1倍速,大概是 timestamp 不对,不知道是服务器的错误,还是客户端解码时出错, 总感觉服务器那边有问题, 由于服务器端是客户端提供的,客户说是我们的问题,我还不知道如何证明是谁的错。
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我跟了,AVPacket的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对音频而言它标识的是什么?是这个时间点采样点吗?
在网上找了很久关于音视频编解码的资料,都没有合适的
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:如何利用AVPacket包里的pts,dts实现音视频同步?
声频播放是只管自己播放,视频有一个初始化播放帧率,如何根据AVPacket里的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
输入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() 函数进行解码时,AVFrame->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 == AV_NOPTS_VALUE)
&& frame->reordered_opaque != AV_NOPTS_VALUE)
pts= frame->reordered_opaque;
else if(pkt->dts != AV_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;
}
从
AVFrame 结构中取得
这个 PTS ,但是这个
AVFrame 结构中取得
这个 PTS 从哪里取得的呢?
A:时间戳
一般是在编码的时候加入到媒体文件中的,所以在解码时可以从中分析出PTS。
VIDEOFRAMETS 试图通过定量视频分析解决一个
问题
。 尽管mpeg 视频是以固定的帧率录制的,实际上视频帧经常偏离这个值。 [我认为这是由于编码器的延迟,对于例如,如果计算机录制视频负载过大,则会出现帧在较慢]。 如果帧通常比预期慢一点(经验帧率 < 标称帧率),
问题
在视频过程中变得复杂: 如果用户采用固定帧率,则视频末尾的数据将是与现实大相径庭。 这给
时间
锁定视频分析带来了巨大的
问题
。 MATLAB 的VideoReader 提供了一个实用的解决方案:VideoReader 对象包含一个属性标识/设置视频中的当前
时间
。 这通常是一个实用的
问题
的解决方案(注意:当与较新的 .readFrame 方法一起使用时比旧的 .read 方法)。 但是,这有一些限制: 1:知道帧数和对应的帧数通常很有用视频分析开始时的
时间戳
(尽管粗略估算是可以使用 VideoReader 的 .FrameR
第二,timebase是个什么
timebase是个有点抽象的东西, 在这里不说抽象的概念,你就把它当成
时间
的单位;
例如25帧的视频,如果不存在timebase这个东西, 我们打
时间戳
应该是这样的,0-40-80-120-以此类推,40毫秒一帧...
我刚接触流媒体不久, 现在遇到一个非常奇怪的
问题
,向各位大侠请假,请你们指点。
问题
是这样的 用一个 VLC(流媒体客户端) 去请求流媒体服务器上的数据, 但是获得的数据播放速度明显快于1倍速,大概是 timestamp 不对, 不知道是服务器的错误,还是客户端解码时出错, 总感觉服务器那边有
问题
, 由于服务器端是客户端提供的,客户说是我们的问
首先,了解
时间戳
几个基本概念:
时间戳
单位:
时间戳
计算的单位不是秒之类的单位,而是由采样频率所代替的单位,这样做的目的就是为了是
时间戳
单位更为精准。比如说一个音频的采样频率为8000Hz,那么我们可以把
时间戳
单位设为1 / 8000。
时间戳
增量:相邻两个RTP包之间的
时间
差(以
时间戳
单位为基准)。
采样频率:每秒钟抽取样本的次数,例如音频的采样率一般为8000Hz
FFMPEG
给视频加
时间戳
水印
项目中需要给视频
添加
时间戳
,理所当然最好用的办法是
ffmpeg
。在找到正确的做法前,还被网上的答案timecode给水了一下(水的不轻,在这里转了2天),大概是这样写的:
ffmpeg
-i wildlife.wmv -vf "drawtext=fontfile=arial.ttf: text='fuck': timecode='09\:57\:00\:00':...
谈谈RTP传输中的负载类型和
时间戳
最近被RTP的负载类型和
时间戳
搞郁闷了,一个
问题
调试了近一周,终于圆满解决,回头看看,发现其实主要原因还是自己没有真正地搞清楚RTP协议中负载类型和
时间戳
的含义。虽然做RTP传输,有着Jrtplib和Ortp这两个强大的库支持,一个是c++接口,一个是c...
关于对错误pts () 出现这种错误是由于视频pts大于dts。pts是视频播放
时间
,dts是送入解码器解码
时间
。所以一帧视频播放
时间
必须在解码
时间
点之后。解决方法是进行判断:if(packet.pts
产生错误的原因一般是对dts,pts操作不当。比如在进行视频分割时,常用的方法是视频截取后半段视频pts与dts减去前半段pts和dts。前半段pts可能比dts大(当解码的视频帧不是I帧时)
last [-num | -n num] [-f file] [-t YYYYMMDDHHMMSS] [-R] [-adioxFw] [username..] [tty..]
last作用是显示近期用户或终端的登录情况。通过last命令查看该程序的log,管理员可以获知谁曾经或者企图连接系统。
执行last命令时,它会读取/var/log目录下名称为wtmp的文件,并把该文件记录的登录...
error: invalid conversion from ‘const char *' to 'char *' [-fpermissive]
slash = strchr(name, '/');
出错代码:
static int create_media_for_iptv(const char *name)
char *slash;
name += strlen("ip
自己所负责的模块中使用到了
ffmpeg
,一直都很正常。但最近碰到了个奇怪的
问题
,使用av_read_frame连续读取摄像头实时视频流,运行一段
时间
后,该函数会返回AVERROR_EOF,代码如下:
void MediaSource::DataProvider::_RecvThread(void)
INFO_LOG(m_LogHandler, "recv thread ENTER, ur...