解密FFmpeg播放狀態控制內幕

上一篇文章(http://my.oschina.net/u/2336532/blog/400790)咱們解決了在FFmpeg下如何處理H264AAC的擴展數據,根據解出的NALU長度恢復了H264的起始碼和AACADTS頭,這樣通常來講播放是沒有問題。本篇文章來談談如何實現基於FFmpegtrack mode控制,也就是如何用FFmpeg提供的功能來實現基本的seek、快進、快退。好了,廢話少了,下面開始基於FFmpegtrack mode之旅。 程序員

FFmpeg提供了一個seek函數,原型以下: 編程

int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,                   int flags); 微信

參數說明: 微信公衆平臺

s:操做上下文; 函數

stream_index:基本流索引,表示當前的seek是針對哪一個基本流,好比視頻或者音頻等等。 spa

timestamp:要seek的時間點,以time_base或者AV_TIME_BASE爲單位。 .net

Flagsseek標誌,能夠設置爲按字節,在按時間seek時取該點以前仍是以後的關鍵幀,以及不按關鍵幀seek等,詳細請參考FFmpegavformat.h說明。基於FFmpeg的全部track mode幾乎都是用這個函數來直接或間接實現的。 code

 

  • 文件的seek功能實現 orm

要轉跳到視頻100秒(100 000毫秒)處的第一個I幀(若是沒有則向前找第一個): 視頻

av_seek_frame(pFormatCtx, vid_index, 100000*vid_time_scale/time_base, AVSEEK_FLAG_BACKWARD);

跳到音頻80秒(80 000毫秒)處的幀(採樣):

av_seek_frame(pFormatCtx, aud_index, 80000*aud_time_scale/ time_base, AVSEEK_FLAG_BACKWARD);

跳到文件開始的地方開始播放:

av_seek_frame(pFormatCtx, vid_index, 0, AVSEEK_FLAG_BACKWARD);

上面的time_scaletime_base都能經過流信息獲取到,請參考前面的文章。有的文件不必定能seek成功,能夠考慮在失敗的狀況下將AVSEEK_FLAG_BACKWARD改成AVSEEK_FLAG_ANY再次seek,不過seek到的視頻幀可能不是I幀。

這個函數無論你當前在什麼時間點上,均可以seek到任何合理位置。好比要實如今當前的基礎上向後或向前跳轉10秒,咱們能夠在av_read_frame函數拿到的包中含有當前時間戳的基礎上增長或較少一個10000(換算成播放時間單位)再seek便可。因此這個函數能夠用作進度的拖放、前進/後退必定時間、循環播放等功能。

  1. 快進快退

對於快進來講,通常解碼器能實現2倍甚至再高倍速的播放,這種狀況直接按照上一篇文章的基本播放流程就能夠了。但對於4倍、8倍、16倍、32倍等高速播放,通常不能像傳統播放那樣一幀一幀的送數據,不僅是解碼能力問題,數據讀取也可能由於帶寬不夠跟不上,咱們只能提取其中的I幀進行播放,將B幀和P幀丟掉。下面咱們就來討論這個過程的實現流程。

快進時,經過當前數據包得到當前的時間PTS,將該PTS換算成時間再加上一小段時間,做爲seek時間點向後找關鍵幀,此時flags可設置爲AVSEEK_FLAG_FRAME。以後用av_read_frame獲取到該關鍵幀。完成該幀解碼顯示後,再在該幀的PTS時間上增長一小段時間後seek,這樣一直重複上述過程,流程以下圖:

                  

 

快退時,經過當前數據包得到當前的時間PTS,將該PTS換算成時間再減去一小段時間,做爲seek時間點向前找關鍵幀,此時flags可設置爲AVSEEK_FLAG_BACKWARD。以後用av_read_frame獲取到該關鍵幀。完成該幀解碼顯示後,再在該幀的PTS時間上減去一小段時間後seek,這樣一直重複上述結果,過程以下圖:

這樣,咱們經過以上對av_seek_frame函數的運用,便可完成文件playback的各類track mode實現,其實理解了這個函數後,你還會有不少其餘辦法來實現,這裏只是提供了一種簡單且佔內存少的辦法。在特定的狀況下還能夠先所有走一遍全部幀,並記錄下所有的I幀的時間戳、幀編號、位置信息等須要的信息,而後直接從該表裏面獲取信息後進行seek和讀取這些關鍵幀進行快速播放。 

想第一時間得到更多原創文章,請關注我的微信公衆平臺:程序員互動聯盟(coder_online),掃一掃下方二維碼或者搜索微信號coder_online便可關注,裏面有大量AndroidChromiumLinux,編程技巧等相關文章等着您,咱們還能夠在線交流。

如需轉載本文,請註明出處:http://my.oschina.net/u/2336532

謝謝合做!

相關文章
相關標籤/搜索