當前位置:
首頁 > 知識 > JPEG流封裝AVI視頻

JPEG流封裝AVI視頻


前言:前幾天工作任務,要把JPEG流封裝為AVI視頻,就找了些AVI文件結構資料和示例代碼研究了下,現將學習總結及最終完成的可用代碼分享出來,由於本人也是現學現用,如有不恰當或錯誤之處,歡迎提出!

1 AVI文件結構

AVI採用RIFF文件結構方式,RIFF是微軟定義的一種用於管理windows環境中多媒體數據的文件格式,波形音頻wave、MIDI和數字視頻AVI都採用這種格式存儲,構造RIFF文件的基本單元叫做數據塊(Chunk),每個數據塊包含3個部分:

(1)4位元組的數據塊標記(Chunk ID)

(2)4位元組的數據塊大小

(3)數據

整個RIFF文件可以看成一個ID為RIFF的數據塊,RIFF塊包含一系列子塊,其中有一種子塊的ID為LIST,稱為LIST塊,LIST塊中可以再包含一系列子塊,但除了LIST塊的其他所有子塊都不能再包含子塊。

RIFF和LIST塊分別比普通的數據塊多一個被稱為形式類型(Form Type)和列表類型(List Type)的數據域,其組成如下:

(1)4位元組的數據塊標記(Chunk ID)

(2)4位元組的數據塊大小

(3)4位元組的形式類型(對於RIFF塊)或列表類型(對於LIST塊)

(4)數據

AVI文件是最複雜的RIFF文件,它能夠同時存儲音頻和視頻數據(註:本文檔不涉及音頻相關內容,只針對視頻數據進行介紹),AVI文件RIFF塊的形式類型是AVI ,它包含以下3個子塊:

(1)信息塊,ID為hdrl的LIST塊,用於定義AVI文件的數據格式

(2)數據塊,ID為movi的LIST塊,用於存儲音視頻數據

(3)索引塊,ID為idxl的數據塊,用於定義音視頻數據的索引,是可選塊

AVI文件結構如圖1所示

JPEG流封裝AVI視頻

圖1 AVI文件結構

1.1 信息塊

信息塊包含兩個子塊:一個ID為avih的子塊和一個ID為strl的LIST塊。

1.1.1 avih塊

JPEG流封裝AVI視頻

圖2 avih塊結構

avih塊可用如圖2所示的struct avi_avih_chunk結構體定義,圖中已對結構體各變數的含義進行了解釋,以下是對其中幾個變數的補充說明:

(1)max_bytes_per_sec

max_bytes_per_sec用於控制視頻的最大碼率,即每秒傳輸的最大數據量。但實際上,給這個變數賦值並不能影響視頻的碼率,原因如下:設JPEG流圖像總幀數為nframes,視頻幀率為fps,各幀圖像平均大小為len,則封裝的AVI視頻時長、文件大小和視頻碼率分別為

time = nframes / fps

video_size = nframes * len(實際大小還要加上文件頭和文件尾的數據)

rate = video_size / time = fps * len

由此可見,在固定的幀率fps下,視頻碼率完全取決於JPEG各幀圖像的大小,和max_bytes_per_sec的值沒有關係,所以這個變數設為0即可。

(2)flags

flags表示AVI文件的全局屬性,如是否含有索引塊、是否即有音頻數據又有視頻數據等,不進行任何標記時flags值為0,若含有索引塊,則flags值為0x00000010。

(3)init_frames

AVI文件若同時存儲了音頻和視頻數據,則音頻數據和視頻數據是交叉存儲的,init_frames僅在這種情況下使用,對於只有視頻流的情況,該變數的值為0。

(4)width、height

這裡的width和height不是JPEG圖像的寬和高,而是用播放器打開AVI文件時視頻主窗口的寬和高,舉個例子,JPEG圖像大小為1920*1080,width和height分別設為960和540,用QQ影音打開AVI文件,則QQ影音會以960*540的窗口大小進行播放。

1.1.2 strl塊

strl塊由圖3所示的結構體定義,它包含strh和strf兩個子塊。

JPEG流封裝AVI視頻

圖3 strl塊結構

1、strh塊結構

JPEG流封裝AVI視頻

JPEG流封裝AVI視頻

圖4 strh塊結構

圖4所示為strh塊結構定義,下面是對結構體內一些變數含義的補充說明:

(1)codec

codec是一個長度為4的字元數組,用於指定數據流的編碼格式,也就是播放器播放這個流時需要的解碼器,對於JPEG編碼的視頻流,codec數組內容就是"J", "P", "E", "G",而不能隨意指定,否則播放器播放時會無法解碼。

(2)scale、rate

對於視頻流,rate除以scale等於視頻幀率,因此這兩個變數可賦值為scale = 1、rate = fps。

2、strf塊結構

strf塊結構根據strh塊中stream_type是視頻流還是音頻流而有所不同,對於視頻流,strf塊結構如圖5所示,其中bitcount表示每個圖像像素占的位數,其值根據視頻流的實際情況而定,但只能是1、4、8、16、24和32之一,常用的有1(黑白二值化圖像)、8(256階灰度圖)和24(RGB圖像)。

JPEG流封裝AVI視頻

圖5 針對視頻流的strf塊結構

1.2 數據塊

由圖1可知,數據塊是一個ID為movi的LIST列表,也稱為movi塊,在僅有視頻流時,該部分存儲的就是一幀一幀的圖像數據,圖6展示了視頻流movi塊的詳細結構。

JPEG流封裝AVI視頻

圖6 僅有視頻流的movi塊結構

可以看到,movi塊首先是一個固定結構的LIST列表頭,包括塊ID、塊大小和塊類型,其中塊ID固定為LIST,塊類型固定為movi,塊大小為movi塊去掉開頭8位元組後的大小。

然後是movi塊數據,也就是各幀視頻圖像對應的數據塊,每一幀圖像的數據塊都包含三部分:

(1)4位元組ID:可以為00dc或00db,00dc表示壓縮的視頻數據,00db表示未壓縮的視頻數據,根據視頻流的實際情況來選擇賦值。

(2)4位元組frame length:圖像數據長度(單位:位元組),該長度必須是4的整數倍,如果不是,則需要將其修正到4的整數倍,比如frame length原始數據為99,則需將其加到100。

(3)frame data:真正的圖像數據。

1.3 索引塊

索引塊是AVI文件結構的可選部分,它是一個ID等於idxl的數據塊,索引塊提供了movi塊中存儲各幀圖像的數據塊在AVI文件中的位置索引,作用是提高AVI文件的讀寫速度,提高視頻播放時的體驗效果。

JPEG流封裝AVI視頻

圖7 索引塊結構

如圖7所示為索引塊結構,包括塊ID、塊大小和塊數據三部分,其中塊ID固定為idxl,塊大小等於索引塊數據的大小。

索引塊數據是movi塊中存儲各幀圖像數據塊的索引,每一幀圖像的索引都是一個16位元組的數據結構,具體如下:

(1)4位元組ChunkID:即movi塊各幀圖像數據塊的ID,00dc或00db

(2)4位元組ChunkFlag:表示該幀圖像是否是關鍵幀,0x10代表關鍵幀,0x00代表非關鍵幀

(3)4位元組ChunkOffset:圖像數據塊相對於「movi」標示符(圖6紅色箭頭所指處)的偏移量,由圖6可得,各幀圖像索引ChunkOffset的值為:

第一幀圖像索引àChunkOffset1 = 4;

第二幀圖像索引àChunkOffset2 = ChunkOffset1+8+第一幀圖像數據長度

第三幀圖像索引àChunkOffset3 = ChunkOffset2+8+第二幀圖像數據長度

…… (後面各幀圖像索引以此類推,其中各幀圖像數據長度指的是修正到4的整數倍後的長度)

(4)4位元組ChunkLength:修正到4的整數倍後的各幀圖像數據長度

2 JPEG流封裝AVI步驟

JPEG流封裝AVI視頻的本質是按照AVI結構進行文件讀寫,操作流程大體上可分為三個步驟:

步驟1:創建空白AVI文件,設置文件偏移量到數據塊movi標示符後面

(1)創建AVI文件,以二進位寫方式打開

(2)計算文件偏移量offset,等於RIFF文件頭12位元組 + hdrl塊大小 + movi LIST頭12位元組

(3)設置AVI文件偏移量為offset

步驟2:從offset偏移量處開始,向AVI文件中逐幀寫入JPEG數據

(1)將當前JPEG圖像數據長度加到4的整數倍,用length表示

(2)JPEG圖像是壓縮過的圖像數據,故寫入"0", "0", "d", "c"

(3)寫入當前JPEG圖像數據長度length

(4)寫入當前JPEG圖像數據,寫入長度為length

(5)循環上述過程,完成逐幀圖像數據的寫入

步驟3:JPEG數據寫完後,先繼續向後寫索引塊,再定位到文件頭回填各塊數據

(1)寫索引塊

- 先寫塊ID "i", "d", "x", "l"

- 再寫塊大小 16 * nframes

- 最後寫各幀圖像的索引

(2)從文件頭開始,回填各塊數據

- 設置文件偏移量為0

- 按照AVI文件結構,寫入步驟1跳過的各塊數據

需要注意的是,步驟3寫索引塊時需要各幀圖像的數據長度和總幀數,回填各塊數據時也需要總幀數和所有幀的總大小,因此步驟2寫入JPEG數據時需要保存它們的值。


3 代碼分享

我完成的代碼,是以若干張JPEG圖片作為JPEG流,先將圖片數據讀入內存,再寫入AVI文件,共包含五個文件:

1、list.h和list.c,雙向循環鏈表,作用是保存各幀圖像大小,用於寫索引塊

2、Jpeg2AVI.h和Jpeg2AVI.c,用於將JPEG流封裝為AVI視頻

3、main.c,測試程序

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

Eclipse連接SQL Server 2008資料庫以及問題總結
設計模式學習筆記 之「多用組合,少用繼承」 C 代碼
大話數據結構——使用棧實現簡單的四則運算
Object和異常類
移動端主流適配方案

TAG:IT優就業 |