http://www.4ucode.com/Study/Topic/1819715

來源:互聯網
上載者:User
大家好
   我剛接觸流媒體不久, 現在遇到一個非常奇怪的問題,向各位大俠請假,請你們指點。
   問題是這樣的 用一個 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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.