ffplay的數據結構分析

《ffplay分析(從啟動到讀取線程的操作)》
《ffplay分析(視頻解碼線程的操作)》
《ffplay分析(音頻解碼線程的操作)》
《ffplay 分析(音頻從Frame(解碼后)隊列取數據到SDL輸出)》
《ffplay分析 (視頻從Frame(解碼后)隊列取數據到SDL輸出)》
《ffplay分析 (音視頻同步:主時鐘為音頻)》
《ffplay分析 (暫停 / 播放處理)》
《ffplay分析 (seek操作處理)》

ffplay的數據結構分析 (版本:ffmpeg-4.2.1)

    • struct VideoState(ffplay中最大的一個封裝結構,所有信息被包含在內)
    • struct Clock(時間封裝)
    • struct MyAVPacketList(解碼前數據,PacketQueue的一個節點)
    • struct PacketQueue(解碼前的Packet隊列)
    • struct Frame(解碼后數據,FrameQueue隊列的元素)
    • struct FrameQueue(解碼后的Frame隊列)
    • struct AudioParams(音頻參數)
    • struct Decoder(解碼器數據封裝)

ffplay的播放顯示是使用SDL(Simple DirectMedia Layer 跨平臺多媒體開發庫)處理的。

ffplay結構體內的元素也是和ffmpeg一樣,一個結構體內的元素不是對應單一的功能點,比如同一個結構體就會有視頻、音頻、字幕的信息,因為都是用同一個結構體來存儲,在函數調用時就可以用一個函數接口。

struct VideoState(ffplay中最大的一個封裝結構,所有信息被包含在內)

typedef struct VideoState {//讀線程SDL線程句柄SDL_Thread *read_tid;//指向輸入的封裝格式AVInputFormat *iformat;//退出請求,(1 = 請求退出)int abort_request;//立即刷新請求(1 = 請求刷新)int force_refresh;//播放暫停狀態(1 = 暫停, 0 = 播放)int paused;//暫存播放暫停狀態(最近一次的狀態)int last_paused;int queue_attachments_req;//標識一次seek的請求int seek_req;//seek標志(AVSEEK_FLAG_BYTE等)int seek_flags;//請求seek的目標位置(當前位置 + 增量 )int64_t seek_pos;//本次請求seek的位置增量int64_t seek_rel;int read_pause_return;//iformat 輸入封裝格式的上下文AVFormatContext *ic;//標志是否為實時流數據(1 = 實時流)int realtime;//音頻時鐘Clock audclk;//視頻時鐘Clock vidclk;//外部時鐘Clock extclk;//視頻Frame隊列(解碼后)FrameQueue pictq;//字幕Frame隊列(解碼后)FrameQueue subpq;//音頻Frame隊列(解碼后)FrameQueue sampq;//音頻解碼器Decoder auddec;//視頻解碼器Decoder viddec;//字幕解碼器Decoder subdec;//音頻流索引(比如有國語、粵語就是不同音頻流的)int audio_stream;//音視頻同步類型(默認audio master)int av_sync_type;//當前音頻幀的PTS + 當前幀的Durationdouble audio_clock;//播放序列,seek可改變這個值int audio_clock_serial;//當av_sync_type != audio master時使用double audio_diff_cum; /* used for AV difference average computation */double audio_diff_avg_coef;double audio_diff_threshold;int audio_diff_avg_count;//音頻流AVStream *audio_st;//音頻Packet隊列(解碼前)PacketQueue audioq;//SDL音頻緩沖區的大小(字節)int audio_hw_buf_size;//指向待播放的一幀音頻數據,指向的數據區將被拷貝到SDL音頻緩沖區//重采樣后就是audio_buf1//需要重采樣的數據uint8_t *audio_buf;//重采樣后的數據uint8_t *audio_buf1;//audio_buf的大小unsigned int audio_buf_size; /* in bytes *///audio_buf1的大小unsigned int audio_buf1_size;//更新拷貝位置 當前音頻幀中已拷入SDL音頻緩沖區// 的位置索引(指向第一個待拷貝字節,因為拷貝到SDL可能不是完整一幀音頻數據拷貝的)int audio_buf_index; /* in bytes *///當前音頻幀中尚未拷入SDL音頻緩沖區的數據量int audio_write_buf_size;//音量int audio_volume;//是否靜音(1 = 靜音, 0 = 正常)int muted;//音頻參數struct AudioParams audio_src;
#if CONFIG_AVFILTERstruct AudioParams audio_filter_src;
#endif//SDL支持的音頻參數,重采樣轉換(文件的音頻參數SDL不支持就要轉:audio_src->audio_tgt)struct AudioParams audio_tgt;//音頻重采樣的上下文struct SwrContext *swr_ctx;//丟棄視頻Packet計數int frame_drops_early;//丟棄視頻Frame計數int frame_drops_late;enum ShowMode {SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB} show_mode;//音頻波形顯示時使用int16_t sample_array[SAMPLE_ARRAY_SIZE];int sample_array_index;int last_i_start;RDFTContext *rdft;int rdft_bits;FFTSample *rdft_data;int xpos;double last_vis_time;SDL_Texture *vis_texture;//字幕顯示SDL_Texture *sub_texture;//視頻顯示SDL_Texture *vid_texture;//字幕流索引int subtitle_stream;//字幕流索引 AVStream *subtitle_st;//字幕Packet隊列(解碼前)PacketQueue subtitleq;//記錄最后一幀播放的時間double frame_timer;double frame_last_returned_time;double frame_last_filter_delay;//視頻流索引int video_stream;//視頻流AVStream *video_st;//視頻Packet隊列(解碼前)PacketQueue videoq;//一幀最大間隔double max_frame_duration;      // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity//視頻格式尺寸轉換struct SwsContext *img_convert_ctx;//字幕格式尺寸轉換struct SwsContext *sub_convert_ctx;//是否讀取結束int eof;//文件名char *filename;//寬、高、x坐標起始、y坐標起始int width, height, xleft, ytop;//1 = 步進模式播放 ,0 = 其他模式 int step;#if CONFIG_AVFILTERint vfilter_idx;AVFilterContext *in_video_filter;   // the first filter in the video chainAVFilterContext *out_video_filter;  // the last filter in the video chainAVFilterContext *in_audio_filter;   // the first filter in the audio chainAVFilterContext *out_audio_filter;  // the last filter in the audio chainAVFilterGraph *agraph;              // audio filter graph
#endif//保留最近一次的相應audio、video、subtitle流的steam indexint last_video_stream, last_audio_stream, last_subtitle_stream;//條件變量,當讀取數據隊列滿了后進入休眠時,可以通過該condition喚醒讀線程SDL_cond *continue_read_thread;
} VideoState;

struct Clock(時間封裝)

typedef struct Clock {//當前幀(待播放)顯示時間戳, 播放后當前幀變成上一幀double pts;           /* clock base *///當前pts與當前系統時鐘的差值,audio、video對于該值是獨立double pts_drift;     /* clock base minus time at which we updated the clock *///最后一次更新的系統時鐘double last_updated;//時鐘速度控制,用于控制播放速度double speed;//播放序列,就是一段連續的播放動作,一個seek操作會啟動一段新的播放序列int serial;           /* clock is based on a packet with this serial *///播放標識 (1 = 暫停狀態)int paused;//指向當前 PacketQueue 的序列int *queue_serial;    /* pointer to the current packet queue serial, used for obsolete clock detection */
} Clock;

struct MyAVPacketList(解碼前數據,PacketQueue的一個節點)

typedef struct MyAVPacketList {//解封裝后的數據(解碼前)AVPacket pkt;//下一個節點struct MyAVPacketList *next;//播放序列int serial;
} MyAVPacketList;

struct PacketQueue(解碼前的Packet隊列)


typedef struct PacketQueue {//隊列頭,隊列尾MyAVPacketList *first_pkt, *last_pkt;//包數量,隊列元素數量int nb_packets;//隊列所有元素的數據大小總和int size;//隊列所有元素的數據播放持續時間總和int64_t duration;//用戶退出標志int abort_request;//播放序列號int serial;//維護PacketQueue的互斥量SDL_mutex *mutex;//條件變量,讀、寫相互通知SDL_cond *cond;
} PacketQueue;

struct Frame(解碼后數據,FrameQueue隊列的元素)

typedef struct Frame {//數據幀AVFrame *frame;//字幕AVSubtitle sub;//播放序列int serial;//顯示時間戳double pts;           /* presentation timestamp for the frame *///該幀持續時間double duration;      /* estimated duration of the frame *///該幀在文件中的字節位置int64_t pos;          /* byte position of the frame in the input file *///寬int width;//高int height;// 對于圖像為(enum AVPixelFormat),// 對于聲音則為(enum AVSampleFormat)int format;//圖像寬高比AVRational sar;//記錄該幀是否已經顯示過int uploaded;//垂直翻轉(1 = 180度 , 0 = 正常 )int flip_v;
} Frame;

struct FrameQueue(解碼后的Frame隊列)


typedef struct FrameQueue {//Frame數組Frame queue[FRAME_QUEUE_SIZE];//讀索引int rindex;//寫索引int windex;//當前總幀數int size;//可存儲最大幀數int max_size;//  等于 1 時,表示隊列里保持最后一幀的數據不釋放,只有在銷毀隊列在釋放int keep_last;//初始化為0 ,和keep_last一起使用int rindex_shown;//互斥量SDL_mutex *mutex;//條件變量SDL_cond *cond;//數據包緩沖隊列(解碼前隊列)PacketQueue *pktq;
} FrameQueue;

struct AudioParams(音頻參數)

typedef struct AudioParams {//采樣率int freq;//通道數int channels;//通道布局(比如:立體聲)int64_t channel_layout;//采樣格式(比如:AV_SAMPLE_FMT_S16)enum AVSampleFormat fmt;//一個采樣單元占用的字節數(channels * fmt)int frame_size;//一秒中音頻占用字節數(channels * fmt * freq)int bytes_per_sec;
} AudioParams;

struct Decoder(解碼器數據封裝)

typedef struct Decoder {AVPacket pkt;//數據包隊列(解碼前)PacketQueue *queue;//解碼器上下文AVCodecContext *avctx;//包序列int pkt_serial;//解碼器工作狀態(0 = 工作, !0= 空閑)int finished;//解碼器異常狀態(0 = 異常,1 = 正常)int packet_pending;//條件變量SDL_cond *empty_queue_cond;//初始化時stream的start timeint64_t start_pts;//初始化時stream的time baseAVRational start_pts_tb;//記錄最后一次解碼的frame的pts,如果解碼出來的幀是無效的pts就用這個值來//推算int64_t next_pts;//next_pts的單位AVRational next_pts_tb;//解碼線程SDL_Thread *decoder_tid;
} Decoder;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379062.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379062.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379062.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

tolowercase_Java String toLowerCase()方法與示例

tolowercase字符串toLowerCase()方法 (String toLowerCase() Method) toLowerCase() method is a String class method, it is used to convert given string into the lowercase. toLowerCase()方法是String類方法,用于將給定的字符串轉換為小寫。 Syntax: 句法&a…

python web 服務器實時監控 websocket_python websocket網頁實時顯示遠程服務器日志信息...

功能:用websocket技術,在運維工具的瀏覽器上實時顯示遠程服務器上的日志信息一般我們在運維工具部署環境的時候,需要實時展現部署過程中的信息,或者在瀏覽器中實時顯示程序日志給開發人員看。你還在用ajax每隔段時間去獲取服務器日…

磁盤調度算法

1,假設磁頭當前位于第105道,正在向磁道序號增加的方向移動,現有一個磁道訪問請求序列為:35,45,12,68,100,180,170,195,試用先來先服務…

C# Using用法三則

(1)引用命名空間 using作為引入命名空間指令的用法準則為: using Namespace; 在.NET程序中,最多見的代碼莫過于在程序文件的開頭引入System命名空間,其原由在于System命名空間中封裝了許多最基本最常用的操作&#xff…

iOS開發 工程

一直沒正兒八經的寫過技術文章。今日開個小窗,準備寫點東西。。。完了 1、傳統的MVC結構需要至少M、V、C三個模塊,在實際開發中往往需要添加額外的模塊,添加的模塊當然也大體上屬于這三個模塊之內。以下為較為常用的子模塊。 (1&a…

C++11 std::shared_ptr的std::move()移動語義底層分析

std::shared_ptr的std::move()移動語義底層分析 執行std::move()之前: 執行std::move()之后: 結論:一個淺拷貝 sizeof(std::shared_ptr) 8字節 pss1 : 0x0028fea8 pss2 : 0x0028fea0 (棧是逆增長的) 觀察執行std::m…

一個使用numpy.ones()的矩陣| 使用Python的線性代數

Ones Matrix - When all the entries of a matrix are one, then it is called as ones matrix. It may be of any dimension (MxN). 一個矩陣 -當矩陣的所有條目均為1時,則稱為一個矩陣。 它可以是任何尺寸( MxN )。 Properties: 特性: The determina…

python去掉字符串最外側的引號_瘋狂Python講義第二章讀書筆記

本章講解變量和簡單類型2.1 從注釋講起單行注釋使用#,#后面的代碼被注釋掉不會運行,如:# print(123) 注釋掉后123不會輸出。多行注釋使用""" """,三個雙引號,雙引號中的內容注釋掉&…

Xpath[轉]

Xpath[轉] XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。 XPath 是 W3C XSLT 標準的主要元素,并且 XQuery 和 XPointer 同時被構建于 XPath 表達之上。 因此,對 XPath 的理解是很多高級 XML 應用的基礎。 …

【轉】深入分析 ASP.NET Mvc 1.0 – 1. 深入MvcHandler

MvcHandler是一個mvc程序真正開始的地方,因為你可以直接看到并調試它的源碼。 MvcHandler的主要代碼如下:protected internal virtual void ProcessRequest(HttpContextBase httpContext) {AddVersionHeader(httpContext);// Get the controller typestring control…

C++11 右值引用與常量左值引用保存臨時變量(函數返回值)的底層分析

右值引用保存臨時變量(函數返回值)的問題 :臨時變量是右值 1、普通變量接收函數返回值: 2、右值引用變量接收函數返回值: 3、用const int& 和右值引用是一樣的效果,只是const int& 就不可以修改…

JavaScript中的位置協議屬性

JavaScript | 位置協議屬性 (JavaScript | Location protocol property) A protocol by definition simply implies a set or working rules that must be adhered to. A network protocol thus defines rules for communication between network devices. You must be familia…

axure源文件_Axure教程:實現網易云音樂有聲播放效果

為了方便講解,我們首先在桌面新建一個文件夾,命名為音樂。1、將自己想要演示播放的MP3音樂文件放在這個文件夾里面。2、給播放頁添加一個中繼器,隨便命名,我給它命名為【音樂地址鏈接器】,用來鏈接播放本地音樂文件。并…

2012年終總結

工作: 原來的文章也寫過,今年年初的時候,因為一些原因,成了另外一家公司的員工,但辦公地點還是在原來的公司。 這是一家外包公司,技術實力當然是比較強的,不過自己對于編程方面的興趣止不住的一…

PYTHON解析PE的模塊

RT,從GOOGLE CODE上找的。。雖然拿PYTHON解析PE的意義不大還有點麻煩…… 示例代碼: #coding:gbk import sys import pefile #from struct import * import structdef main():pe pefile.PE("ccalc.exe")pe.print_info()if __name__ "__…

ffplay分析(從啟動到讀取數據線程插入到字幕、音頻、視頻解碼前的隊列操作)

《ffplay的數據結構分析》 《ffplay分析(視頻解碼線程的操作)》 《ffplay分析(音頻解碼線程的操作)》 《ffplay 分析(音頻從Frame(解碼后)隊列取數據到SDL輸出)》 《ffplay分析 (視頻從Frame(解…

python3和python2 優勢_python3和python2的區別

1.性能Py3.0運行 pystone benchmark的速度比Py2.5慢30%。Guido認為Py3.0有極大的優化空間,在字符串和整形操作上可以取得很好的優化結果。Py3.1性能比Py2.5慢15%,還有很大的提升空間。2.編碼Py3.X源碼文件默認使用utf-8編碼,這就使得以下代碼…

并發進程同步

P是荷蘭語Proberen(測試)的首字母。為阻塞原語,負責把當前進程由運行狀態轉換為阻塞狀態,直到另外一個進程喚醒它。也就是不好的一方面。 V是荷蘭語Verhogen(增加)的首字母。為喚醒原語,負責把一…

寄存器和pin_16x2 LCD的PIN圖和寄存器

寄存器和pinIn these years the LCD is finding widespread use. It has replaced the LEDs or other multi-segment LEDs.This is due to the following reasons: 近年來, LCD正在廣泛使用。 它已替換LED或其他多段LED,原因如下: The decli…

【Java IO知識】讀取中文亂碼問題解決

讀取文件主要是要設置讀取的輸入流如InputStreamReader時要設置讀取的解碼格式,要和文件本身的編碼格式相同,這樣讀取出來的才不會亂碼。 InputStreamReader reader new InputStreamInputReader(input, "編碼格式"); ANSI是"gbk" 注:必須是在讀取的時候就…