大家好
?? 我剛接觸流媒體不久, 現在遇到一個非常奇怪的問題,向各位大俠請假,請你們指點。
?? 問題是這樣的 用一個 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對音頻而言它標識的是什么?是這個時間點采樣點嗎?
在網上找了很久關于音視頻編解碼的資料,都沒有合適的
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:如何利用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
輸入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() 函數進行解碼時,AVFrame->pts 時間戳不對,導致我的圖像不能夠顯示? 請問有誰知道它的解碼原理,這個 PTS 怎么得出的嗎?還是外部傳入的?
A:????? /* NOTE: ipts is the PTS of the _first_ picture beginning in
?????????? this packet, if any */
??????? 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。 |