Ⅰ android音視頻開發——H264的基本概念
ffmpeg常用命令
封裝格式 。
編碼的本質就是壓縮數據
音頻編碼的作用: 將音頻采樣數據( PCM 等)壓縮成音頻碼流,從而降低音頻的數據量。 常用的音頻編碼方式有以下幾種:
H264壓縮技術主要採用了以下幾種方法對視頻數據進行壓縮。包括:
經過壓縮後的幀分為:I幀,P幀和B幀:
除了I/P/B幀外,還有圖像序列GOP。
組成碼流的結構中,包含了以下幾個部分,從大到小依次是:
H264視頻序列,圖像,片組,片,NALU,宏塊,像素
H264功能分為兩層:
1.H264視頻序列包括一系列的NAL單元,每個NAL單元包含一個RBSP。
2.一個原始的H.264由 N個NALU單元組成
3.NALU單元由[StartCode][NALU Header][NALU Payload]三部分組成
5.NAL Header
由三部分組成forbidden_bit(1bit)(禁止位),nal_reference_bit(2bits)(優先順序,,值越大,該NAL越重要),nal_unit_type(5bits)(類型)
nal_unit_type
6.NAL的解碼單元的流程如下
Ⅱ h264協議幀頭數據解析
原文出自 http://blog.csdn.net/season_hangzhou/article/details/51123979
h264常見的幀頭數據為:
00 00 00 01 67 (SPS) :SPS即Sequence Paramater Set,又稱作序列參數集。SPS中保存了一組編碼視頻序列(Coded video sequence)的全局參數。所謂的編碼視頻序列即原始視頻的一幀一幀的像素數據經過編碼之後的結構組成的序列。而每一幀的編碼後數據所依賴的參數保存於圖像參數集中。一般情況SPS和PPS的NAL Unit通常位於整個碼流的起始位置。但在某些特殊情況下,在碼流中間也可能出現這兩種結構,主要原因可能為:
1:解碼器需要在碼流中間開始解碼;
2:編碼器在編碼的過程中改變了碼流的參數(如圖像解析度等);
00 00 00 01 68 (PPS) :除了序列參數集SPS之外,H.264中另一重要的參數集合為圖雀殲像參數集Picture Paramater Set(PPS)。通常情況下,PPS類似於SPS,在H.264的裸碼流中單獨保存在一個NAL Unit中,只是PPS NAL Unit的nal_unit_type值為8;而在封裝格式中,PPS通常與SPS一起,保存在視頻文件的文件頭中。
00 00 00 01 65 ( IDR 幀) : I幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀數據就可以完成(因為包含完整畫面)
00 00 00 01 61 (P幀) :P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面數據,只有與前一幀的畫面差別的數據)
start code有兩種,四個位元組的「00 00 00 01」和三個位元組的「00 00 01」都是。
H264幀由NALU頭和NALU主體組成頃則沖。
NALU頭由一個位元組組成,它的語法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
F: 1個比特.
forbidden_zero_bit. 在 H.264 規范中規定了這一位必須為 0.
NRI: 2個比特.
nal_ref_idc. 取00~11,似乎指示這個NALU的重要性,如00的NALU解碼器可以丟棄它而不影響圖像的回放,0~3,取值越大,表示當前NAL越重要,需要優先受到保護。如果當前NAL是屬於參考幀的片,或是序列參數集,或是圖像參數集這些重要的單位時,本句法元素必需大於0。
Type: 5個比特.
nal_unit_type. 這個NALU單元的類型,1~12由H.264使用,24~31由H.264以外的應用使用,簡述如下:
0 沒有定義
1-23 NAL單元 單個 NAL 單元包
1 不分區,非IDR圖像的片
2 片分區A
3 片分區B
4 片分區C
5 IDR圖像中的片
6 補充增強信息單元(SEI)
7 SPS
8 PPS
9 序列結束
10 序列結束
11 碼流借宿
12 盯鉛 填充
13-23 保留
24 STAP-A 單一時間的組合包
25 STAP-B 單一時間的組合包
26 MTAP16 多個時間的組合包
27 MTAP24 多個時間的組合包
28 FU-A 分片的單元
29 FU-B 分片的單元
30-31 沒有定義
Ⅲ Android如何實現h264硬編碼
使用Android中的StageFright框架調用御纖衫睜OpenMAX進行硬體編碼,OMX部分由硬體廠商鎮塌仿實現,無需關注,看好StageFright的調用方法即可
Ⅳ android mediacodec編碼h264 怎樣調節gop
簡單地說。軟解碼是用軟體方式進行解碼,需要佔用CPU資源,速度相當較慢。硬解碼直接用硬體方式解決,不佔用CPU資源,速度相對較快。
mov和mp4是兩種不同的封裝格式,裡面的h.264都是一樣的
單位用的是視盈,幾年來一直很穩定。推薦你聯系視盈黃國耀。一三七,一一一四,六六九一。
僅轉換可以使用命令,把任一mp4轉換成ts
ffmpeg -i input.mp4 -c -bsf h264_mp4toannexb output.ts 很高興為您解答!
有不明白的可以追問!如果您認可我的回答。
1. 簡單介紹
首先激瞎喊是捕獲,這里採用了DirectShow的方式,對它進行了一定程度的封裝,包括音視頻。好處是直接使用native api,你可以做想做的任何修改,壞處是,不能跨平台,採集音視頻這種應用,linux平台也是需要滴呀。有跨平台的做法,對視頻,可以使用OpenCV,對音頻,可以使用OpenAL或PortAudio等,這樣就行了。
編碼可以選擇的餘地比較大,對視頻來講,有H264, MPEG-4, WebM/VP8, Theora等,音頻有Speex, AAC, Ogg/Vorbis等,它們都有相應的開源項目方案,我採用的是x264進行H264編碼,libfaac進行aac編碼,之後是否更改編碼方案,等具體項目需求再說了。這里提一下WebM,Google牽頭的項目,完全開放和自由,使用VP8和Vorbis編碼,webm(mkv)封裝,有多家巨頭支持,目的是想要取代當前的H264視頻編碼,號稱比後者更加優秀,我沒有測試過實際效果。不過有商業公司牽頭就是不一樣,各項支持明野都很全面,有時間了關注一下。
2. 邏輯和流程
基本的思想是實現dshow ISampleGrabberCB介面,通過回調來保存每一個buffer。除了界面線程和dshow自己的線程之外,我們啟動了兩個線程,AudioEncoderThread和VideoEncoderThread,分別從SampleGrabber中取出數據,調用編碼器進行編碼,編碼後的文件可以直接輸出。看圖:
程序是用VS2010構建的,看張工程截圖:
Base下面的是對系統API的一些簡單封裝,主要是線程和鎖。我這里簡單也封裝的了一下dshow的捕獲過程,包括graph builder的創建,filter的連接等。directshow是出了名的難用,沒辦法,難用也得用。因為是VS2010,調用的Windows SDK 7.1中的dshow,沒有qedit.h這個文件,而它正式定義ISampleGrabberCB的。不急,系統中還是有qedit.dll的,我們要做的就是從Windows SDK 6.0中,把它拷過來,然後在stdafx.h中加入這幾行代碼,就可以了
1 #pragma include_alias( "dxtrans.h", "qedit.h" )
2 #define __IDxtCompositor_INTERFACE_DEFINED__
3 #define __IDxtAlphaSetter_INTERFACE_DEFINED__
4 #define __IDxtJpeg_INTERFACE_DEFINED__
5 #define __IDxtKey_INTERFACE_DEFINED__
6 #include "qedit.h"
3. 音視頻編碼
相關文件:
Encoder下就是音視頻編碼相關的代碼。X264Encoder封裝了調用x264編碼器的神州操作,FAACEncoder封裝了調用libfaac編碼器的操作,VideoEncoderThread和AudioEncoderThread負責主要的流程。下面我把關鍵代碼貼出來,大家可以參考一下。
A. 視頻編碼線程
主要流程是首先初始化x264編碼器,然後開始循環調用DSVideoGraph,從SampleGrabber中取出視頻幀,調用x264進行編碼,流程比較簡單,調用的頻率就是你想要獲取的視頻幀率。要注意的一點是,x264進行編碼比較耗時,在計算線程Sleep時間時,要把這個過程消耗的時間算上,以免採集的視頻幀率錯誤。
B. 音頻編碼線程
主要流程和視頻編碼線程相同,也是初始化FAAC編碼器,然後循環調用DSAudioGraph,從SampleGrabber中取出視頻幀,調用faac進行編碼。和視頻不同的是,音頻的sample的頻率是非常快的,所以幾乎要不斷的進行採集,但前提是SampleGrabber中捕獲到新數據了才行,不然你的程序cpu就100%了,下面代碼中IsBufferAvailaber()就是做這個檢測的。
調用faac進行編碼的時候,有點需要注意,大家特別注意下,不然編碼出來的音頻會很不正常,搞不好的話會很頭疼的。先看下faac.h的相關介面
1 faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, unsigned int numChannels,2 unsigned long *inputSamples, unsigned long *maxOutputBytes);3 4 int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput,5 unsigned char *outputBuffer, unsigned int bufferSize);
faacEncEncode第三個參數指的是傳入的sample的個數,這個值要和調用faacEncOpen返回的inputSamples相等。要做到這點,就要在dshow中設置好buffsize,公式是:
BufferSize = aac_frame_len * channels * wBytesPerSample aac_frame_len = 1024
h.264是一種視頻壓縮標准了,有專門的庫對它進行壓縮解壓的。
我對opencv還算是比較熟悉的,它沒有h264之類的庫
不能啊,不同格式的,H264跟DVD不一樣啊
音頻編輯器
1、運行Set-up.exe,會彈出「遇到了以下問題」彈窗,選擇忽略;
2、之後會初始化安裝程序,請不要進行任何操作,稍等片刻;
3、有安裝和試用兩種選擇,請點擊試用
4、安裝需要Adobe ID登錄驗證,沒有的話選擇"獲取Adobe ID"注冊一個,只需有郵箱和密碼即可(您也可以選擇斷開網路連接,選擇「以後再登錄」),同樣也能繼續安裝;這里為您演示登陸安裝。
5、接受協議後,選擇安裝的語言和安裝的目錄。
6、之後只需耐心等待,軟體需要組件已自帶,無需另外安裝,這樣就等安裝完Adobe Premiere Pro CC 2015。
7、安裝完畢點擊立即啟動,啟動後不是進入軟體而是試用版界面,點擊開始試用;
8、打開Premiere Pro CC 2015,選擇新建項目才算是進入軟體。
PS:若是不事先進入一次軟體直接破解會導致軟體無法打開。
Premiere Pro CC 2015::3322./soft/201507311409.
需要調用av_parser_parse
進行幀查找分解後再送入解碼器解碼。
編碼是不一樣的,H.264採用的幀內編碼和幀間預測編碼技術 比MPEG-2的都要先進,因此壓縮效率更高
Ⅳ 哪位高手做過ffmpeg在android下的運用.小弟我只想調用解碼H264的幀
用NDK把ffmpeg 編譯成動態庫SO 文件
再android工程利用JNI生成介面調用這個靜態庫。
試過videolan的東西么?
olvaffe/ffmpeg/ffmpeg-android/commits/android
Ⅵ android mediarecorder錄制的MP4文件,怎麼組成H264文件播放起來
Android(java方法)上實現mp4的分割和拼接 (二)
這節談一下如何在android上實現mp4文件的高效率切割。
業務需求舉例:把一段2分鍾的mp4文件切割出00:42 至 01:16這段時間的視頻,要求足夠短的執行時間和盡量少的誤差。
分析:mp4Parser只能在關鍵幀切割,比如,在00:40和00:45分別存在一個可切割關鍵幀,那麼切割視頻的頭和尾,都應該選擇短切割。然後獲取到誤差的視頻短,如果這個誤差大於0.5S,用FFmpeg進行一幀一幀編解碼切割文件。這樣最多會有三段mp4文件,再次將這三段mp4拼接起來就可以了。
下面直接上關鍵代碼,這些代碼在PC上新建一個java工程也可以實現。
1.切割文件方法:
/**
Ⅶ H264之幀編碼——透析(I幀+P幀+B幀編碼)原理與流程
在H.264壓縮標准中I幀、P幀、B幀⽤於表⽰傳輸的視頻畫⾯。在視頻壓縮中,每幀都代表著一幅靜止的圖像。在實際的視頻壓縮編碼時,會採取各種演算法減少數據的容量,其中IPB幀就是最常見的一種演算法。
I‑frame (Intra-coded picture): 即完整的一張圖片
P‑frame (Predicted picture): 與前面一張圖片的區別的區域
B‑frame (Bidirectional predicted picture):與前面以及後面的圖片的區別區域
I幀⼜稱幀內編碼幀,又稱全幀壓縮編碼幀,是⼀種⾃帶全部信息的獨⽴幀,⽆需參考其他圖像便可獨⽴進⾏解碼,可以簡單理解為⼀張靜態畫⾯。視頻序列中的第⼀個幀始終都是I幀,因為它是關鍵幀。I幀通常是每個GOP(MPEG所使用的一種視頻壓縮技術)的第一個幀,經過適度地壓縮,作為隨機訪問的參考點,可以當成靜態圖像。
現在有一段影片如下:
該影片總共是20張圖片組成的,每一張完整的圖片我們都可以叫做I幀。假如每知祥晌張JPEG的圖片大小為100KB,那麼傳輸兩張圖片即為100 * 20 = 2000KB
要知道這個還不到幾秒的影片就2M了,要是幾個小時的那還得了,所以就有了影片壓縮的演算法
1.它是一個全幀壓縮編碼幀。它將全幀圖像信息進行JPEG壓縮編碼及傳輸;
2.解碼時僅用I幀的數據就可重構完整圖像;
3.I幀描述了圖像背景和運動主體的詳情;
4.I幀不需要參考其他畫面而生成;
5.I幀是P幀和B幀的參考幀(其質量直接影響到同組中以後各幀的質量);
6.I幀是幀組GOP的基礎幀(第一幀),在一組中只有一個I幀;
7.I幀不需要考慮運動矢量;
8.I幀所佔數據的信息量比較大。
P幀⼜稱幀間預測編碼幀,又稱前向預測編碼幀,需要參考前⾯的I幀才能進⾏編碼。表⽰的是當前幀畫⾯與前⼀幀(前⼀幀可能是I幀也可能是P幀)的差別。解碼時需要⽤之前緩存的畫⾯疊加上本幀定義的差別,⽣成最終畫⾯。
與I幀相⽐,P幀通常占⽤更少的數據位,但不⾜是,由於P幀對前⾯的P和I參考幀有著復雜的依耐性,因此對傳輸錯誤⾮常敏感。通常將圖像序列中前面已經編碼幀的時間冗餘信息充分去除來壓縮傳輸數據量的編碼圖像,也稱為預測幀。通過觀察,我們可以看出,實際上每一幀之間其實只有一部分細微的差別而已,如下圖提取了6幀
當傳輸完第一幀以後,第二幀其實我們只需要傳輸一部分,然後由另外一端進行圖片演算法來進行組合
用這種方式,在傳輸第二幀的時候,還不到原來的1/10,只需要傳輸第一幀的100KB,後續的都是按照這種方式傳輸部分,這種只傳輸部分的圖片,就是P幀了。最後整個影片的大小即為100KB + 10KB * 19 = 290 KB,比原來縮小了很多。
1.P幀是I幀後面相隔1~2幀的編碼幀;
2.P幀採用運動補償的方法傳送它與前面的I或P幀的差值及運動矢量(預測誤差);
3.解碼時必須將I幀中的預測值與預測誤差求和後才能重構完整的P幀圖像;
4.P幀屬於前向預測的幀間編碼。它只參考前面最靠近它的I幀或P幀宴並;
5.P幀可以是其後面P幀的參考幀,也可以是其前後的B幀的參考幀;
6.由於P幀是參考幀,它可能造成解碼錯誤的擴散;
7.由於是差值傳送,P幀的壓縮比較高。
B幀⼜稱雙向預測編碼幀,又稱雙向預測內插編碼幀,也就是B幀記錄的是本幀與前後幀的差別。也就是說要解碼B幀,不僅要取得之前的緩存畫⾯,還要解碼之後的畫⾯,通過前後畫⾯的與本幀數據的疊加取得最終的畫⾯。B幀壓縮率⾼,但是對解碼性能要求較⾼。既考慮源圖像序列前面的已編碼幀,又顧及源圖像序列後面的已編碼幀之間的時間冗餘信息搭鋒,來壓縮傳輸數據量的編碼圖像,也稱為雙向預測幀。B幀其實就是與前後兩張圖片的區別。如果理解了P幀和I幀,這個就很好理解了。
B幀比P幀更小,更節省空間
假設現在有三張圖片,如下圖:
在經過編碼後,會變成如下:
1.B幀是由前面的I或P幀和後面的P幀來進行預測的;
2.B幀傳送的是它與前面的I或P幀和後面的P幀之間的預測誤差及運動矢量;
3.B幀是雙向預測編碼幀;
4.B幀壓縮比最高,因為它只反映丙參考幀間運動主體的變化情況,預測比較准確;
5.B幀不是參考幀,不會造成解碼錯誤的擴散。
(1) 進行幀內預測,決定所採用的幀內預測模式。
(2) 像素值減去預測值,得到殘差。
(3) 對殘差進行變換和量化。
(4) 變長編碼和算術編碼。
(5) 重構圖像並濾波,得到的圖像作為其它幀的參考幀。
(1) 進行運動估計,計算採用幀間編碼模式的率失真函數(節)值。P幀只參考前面的幀,B 幀可參考後面的幀。
(2) 進行幀內預測,選取率失真函數值最小的幀內模式與幀間模式比較,確定採用哪種編碼模式。
(3) 計算實際值和預測值的差值。
(4) 對殘差進行變換和量化。
(5) 熵編碼,如果是幀間編碼模式,編碼運動矢量
Android音視頻工程師必備《全套音視頻入門到精通手冊》
I幀只需考慮本幀;P幀記錄的是與前⼀幀的差別;B幀記錄的是前⼀幀及後⼀幀的差別,能節約更多的空間,視頻⽂件⼩了,但相對來說解碼的時候就⽐較⿇煩。因為在解碼時,不僅要⽤之前緩存的畫⾯,⽽且要知道下⼀個I或者P的畫⾯,對於不⽀持B幀解碼的播放器容易卡頓。
Ⅷ 哪位高手做過ffmpeg在android下的運用.小弟我只想調用解碼h264的幀
樓主你好!根據你的描述,讓我來給你回答!
用NDK把ffmpeg 編譯成動態庫SO 文件
再android工程利用JNI生成介面調用這個靜態庫。
希望能幫到你,如果滿意,請記得採納哦~~~
Ⅸ Android -- 音視頻基礎知識
幀,是視頻的一個基本概念,表示一張畫面,如上面的翻頁動畫書中的一頁,就是一幀。一個視頻就是由許許多多幀組成的。
幀率,即單位時間內幀的數量,單位為:幀/秒 或fps(frames per second)。一握指秒內包含多少張圖片,圖片越多,畫面越順滑,過渡越自然。 幀率的一般以下幾個典型值:
24/25 fps:1秒 24/25 幀,一般的電影幀率。
30/60 fps:1秒 30/60 幀,游戲的幀率,30幀可以接受,60幀會感覺更加流暢逼真。
85 fps以上人眼基本無法察覺出來了,所以更高的幀率在視頻里沒有太大意義。
這里我們只講常用到的兩種色彩空間。
RGB的顏色模式應該是我們最熟悉的一種,在現在的電子設備中應用廣泛。通過R G B三種基礎色,可以混合出所有的顏色。
這里著重講一下YUV,這種色彩空間並不是我們熟悉的。這是一種亮度與色度分離的色彩格式。
早期的電慧談視都是黑白的,即只有亮度值,即Y。有了彩色電視以後,加入了UV兩種色度,形成現在的YUV,也叫YCbCr。
Y:亮度,就是灰度值。除了表示亮度信號外,還含有較多的綠色通道量。
U:藍色通道與亮度的差值。
V:紅色通道與亮度的差值。
音頻數據的承載方式最常用的是 脈沖編碼調制 ,即 PCM 。
在自然界中,聲音是連續不斷的,是一種模擬信號,那怎樣才能把聲音保存下來呢?那就是把聲音數字化,即轉換為數字信號。
我們知道聲音是一種波,有自己的振幅和頻率,那麼要保存聲音,就要保存聲音在各個時間點上的振幅。
而數字信號並不能連續保存所有時間點的振幅,事實上,並不需要保存連續的信號,就可以還原到人耳可接受的聲音。
根據奈奎斯特采樣定理:為了不失真地恢復模擬信號,采樣頻率應該不小於模擬信號頻譜中最高頻率的2倍。
根據以上分析,PCM的採集步驟分為以下步驟:
采樣率,即采樣的頻率。
上面提到,采樣率要大於原聲波頻率的2倍,人耳能聽到的最高頻率為20kHz,所以為了滿足人耳的聽覺要求,采樣率至少為40kHz,通常為44.1kHz,更高的通常為48kHz。
采樣位數,涉及到上面提到的振段碧配幅量化。波形振幅在模擬信號上也是連續的樣本值,而在數字信號中,信號一般是不連續的,所以模擬信號量化以後,只能取一個近似的整數值,為了記錄這些振幅值,采樣器會採用一個固定的位數來記錄這些振幅值,通常有8位、16位、32位。
位數越多,記錄的值越准確,還原度越高。
最後就是編碼了。由於數字信號是由0,1組成的,因此,需要將幅度值轉換為一系列0和1進行存儲,也就是編碼,最後得到的數據就是數字信號:一串0和1組成的數據。
整個過程如下:
聲道數,是指支持能不同發聲(注意是不同聲音)的音響的個數。 單聲道:1個聲道
雙聲道:2個聲道
立體聲道:默認為2個聲道
立體聲道(4聲道):4個聲道
碼率,是指一個數據流中每秒鍾能通過的信息量,單位bps(bit per second)
碼率 = 采樣率 * 采樣位數 * 聲道數
這里的編碼和上面音頻中提到的編碼不是同個概念,而是指壓縮編碼。
我們知道,在計算機的世界中,一切都是0和1組成的,音頻和視頻數據也不例外。由於音視頻的數據量龐大,如果按照裸流數據存儲的話,那將需要耗費非常大的存儲空間,也不利於傳送。而音視頻中,其實包含了大量0和1的重復數據,因此可以通過一定的演算法來壓縮這些0和1的數據。
特別在視頻中,由於畫面是逐漸過渡的,因此整個視頻中,包含了大量畫面/像素的重復,這正好提供了非常大的壓縮空間。
因此,編碼可以大大減小音視頻數據的大小,讓音視頻更容易存儲和傳送。
視頻編碼格式有很多,比如H26x系列和MPEG系列的編碼,這些編碼格式都是為了適應時代發展而出現的。
其中,H26x(1/2/3/4/5)系列由ITU(International Telecommunication Union)國際電傳視訊聯盟主導
MPEG(1/2/3/4)系列由MPEG(Moving Picture Experts Group, ISO旗下的組織)主導。
當然,他們也有聯合制定的編碼標准,那就是現在主流的編碼格式H264,當然還有下一代更先進的壓縮編碼標准H265。
H264是目前最主流的視頻編碼標准,所以我們後續的文章中主要以該編碼格式為基準。
H264由ITU和MPEG共同定製,屬於MPEG-4第十部分內容。
我們已經知道,視頻是由一幀一幀畫面構成的,但是在視頻的數據中,並不是真正按照一幀一幀原始數據保存下來的(如果這樣,壓縮編碼就沒有意義了)。
H264會根據一段時間內,畫面的變化情況,選取一幀畫面作為完整編碼,下一幀只記錄與上一幀完整數據的差別,是一個動態壓縮的過程。
在H264中,三種類型的幀數據分別為
I幀:幀內編碼幀。就是一個完整幀。
P幀:前向預測編碼幀。是一個非完整幀,通過參考前面的I幀或P幀生成。
B幀:雙向預測內插編碼幀。參考前後圖像幀編碼生成。B幀依賴其前最近的一個I幀或P幀及其後最近的一個P幀。
全稱:Group of picture。指一組變化不大的視頻幀。
GOP的第一幀成為關鍵幀:IDR
IDR都是I幀,可以防止一幀解碼出錯,導致後面所有幀解碼出錯的問題。當解碼器在解碼到IDR的時候,會將之前的參考幀清空,重新開始一個新的序列,這樣,即便前面一幀解碼出現重大錯誤,也不會蔓延到後面的數據中。
DTS全稱:Decoding Time Stamp。標示讀入內存中數據流在什麼時候開始送入解碼器中進行解碼。也就是解碼順序的時間戳。
PTS全稱:Presentation Time Stamp。用於標示解碼後的視頻幀什麼時候被顯示出來。
前面我們介紹了RGB和YUV兩種圖像色彩空間。H264採用的是YUV。
YUV存儲方式分為兩大類:planar 和 packed。
planar如下:
packed如下:
上面說過,由於人眼對色度敏感度低,所以可以通過省略一些色度信息,即亮度共用一些色度信息,進而節省存儲空間。因此,planar又區分了以下幾種格式:YUV444、 YUV422、YUV420。
YUV 4:4:4采樣,每一個Y對應一組UV分量。
YUV 4:2:2采樣,每兩個Y共用一組UV分量。
YUV 4:2:0采樣,每四個Y共用一組UV分量。
其中,最常用的就是YUV420。
YUV420屬於planar存儲方式,但是又分兩種類型:
YUV420P:三平面存儲。數據組成為YYYYYYYYUUVV(如I420)或YYYYYYYYVVUU(如YV12)。
YUV420SP:兩平面存儲。分為兩種類型YYYYYYYYUVUV(如NV12)或YYYYYYYYVUVU(如NV21)
原始的PCM音頻數據也是非常大的數據量,因此也需要對其進行壓縮編碼。
和視頻編碼一樣,音頻也有許多的編碼格式,如:WAV、MP3、WMA、APE、FLAC等等,音樂發燒友應該對這些格式非常熟悉,特別是後兩種無損壓縮格式。
但是,我們今天的主角不是他們,而是另外一個叫AAC的壓縮格式。
AAC是新一代的音頻有損壓縮技術,一種高壓縮比的音頻壓縮演算法。在MP4視頻中的音頻數據,大多數時候都是採用AAC壓縮格式。
AAC格式主要分為兩種:ADIF、ADTS。
ADIF:Audio Data Interchange Format。音頻數據交換格式。這種格式的特徵是可以確定的找到這個音頻數據的開始,不需進行在音頻數據流中間開始的解碼,即它的解碼必須在明確定義的開始處進行。這種格式常用在磁碟文件中。
ADTS:Audio Data Transport Stream。音頻數據傳輸流。這種格式的特徵是它是一個有同步字的比特流,解碼可以在這個流中任何位置開始。它的特徵類似於mp3數據流格式。
ADIF數據格式:
ADTS 一幀 數據格式(中間部分,左右省略號為前後數據幀):
AAC內部結構也不再贅述,可以參考AAC 文件解析及解碼流程
細心的讀者可能已經發現,前面我們介紹的各種音視頻的編碼格式,沒有一種是我們平時使用到的視頻格式,比如:mp4、rmvb、avi、mkv、mov...
沒錯,這些我們熟悉的視頻格式,其實是包裹了音視頻編碼數據的容器,用來把以特定編碼標准編碼的視頻流和音頻流混在一起,成為一個文件。
例如:mp4支持H264、H265等視頻編碼和AAC、MP3等音頻編碼。
我們在一些播放器中會看到,有硬解碼和軟解碼兩種播放形式給我們選擇,但是我們大部分時候並不能感覺出他們的區別,對於普通用戶來說,只要能播放就行了。
那麼他們內部究竟有什麼區別呢?
在手機或者PC上,都會有CPU、GPU或者解碼器等硬體。通常,我們的計算都是在CPU上進行的,也就是我們軟體的執行晶元,而GPU主要負責畫面的顯示(是一種硬體加速)。
所謂軟解碼,就是指利用CPU的計算能力來解碼,通常如果CPU的能力不是很強的時候,一則解碼速度會比較慢,二則手機可能出現發熱現象。但是,由於使用統一的演算法,兼容性會很好。
硬解碼,指的是利用手機上專門的解碼晶元來加速解碼。通常硬解碼的解碼速度會快很多,但是由於硬解碼由各個廠家實現,質量參差不齊,非常容易出現兼容性問題。
MediaCodec 是Android 4.1(api 16)版本引入的編解碼介面,是所有想在Android上開發音視頻的開發人員繞不開的坑。
由於Android碎片化嚴重,雖然經過多年的發展,Android硬解已經有了很大改觀,但實際上各個廠家實現不同, 還是會有一些意想不到的坑。
相對於FFmpeg,Android原生硬解碼還是相對容易入門一些,所以接下來,我將會從MediaCodec入手,講解如何實現視頻的編解碼,以及引入OpenGL實現對視頻的編輯,最後才引入FFmpeg來實現軟解,算是一個比較常規的音視頻開發入門流程吧。
Ⅹ Android 音視頻01 --- H264的基本原理01
H264壓縮技術主要採用了以下幾種方法對視頻數據進行壓縮。包括:
解決的是空域數據冗餘問題。
解決的是時域數據冗徐問題
將空間上的相關性變為頻域上無關的數據然後進行量化。
經過壓縮後的幀分為:I幀,P幀和B幀:
關鍵幀,採用幀內壓縮技術。
向前參考幀,在壓縮時,只參考前面已經處理的幀。採用幀音壓縮技術。
雙向參考幀,在壓縮時,它即參考前而的幀,又參考它後面的幀。採用幀間壓縮技術。
除了I/P/B幀外,還有圖像序列GOP。
H264的基本原理其實非常簡單,下我們就簡單的描述一下H264壓縮數據的過程。通過攝像頭採集到的視頻幀(按每秒 30 幀算),被送到 H264 編碼器的緩沖區中。編碼器先要為每一幅圖片劃分宏塊。
劃分好宏塊後,計算宏塊的象素值。以此類推,計算一幅圖像中每個宏塊的像素值。
對於視頻數據主要有兩類數據冗餘,一類是時間上的數據冗餘,另一類是空間上的數據冗餘。其中時間上的數據冗餘是最大的。為什麼說時間上的冗餘是最大的呢?假設攝像頭每秒抓取30幀,這30幀的數據大部分情況下都是相關聯的。也有可能不止30幀的的數據,可能幾十幀,上百幀的數據都是關聯特別密切的。
H264編碼器會按順序,每次取出兩幅相鄰的幀進行宏塊比較,計算兩幀的相似度。如下圖:
在H264編碼器中將幀分組後,就要計算幀組內物體的運動矢量了。
H264編碼器首先按順序從緩沖區頭部取出兩幀視頻數據,然後進行宏塊掃描。當發現其中一幅圖片中有物體時,就在另一幅圖的鄰近位置(搜索窗口中)進行搜索。如果此時在另一幅圖中找到該物體,那麼就可以計算出物體的運動矢量了。
運動矢量計算出來後,將相同部分(也就是綠色部分)減去,就得到了補償數據。我們最終只需要將補償數據進行壓縮保存,以後在解碼時就可以恢復原圖了。壓縮補償後的數據只需要記錄很少的一點數據。
我們把運動矢量與補償稱為 幀間壓縮技術 ,它解決的是視頻幀在時間上的數據冗餘。除了幀間壓縮,幀內也要進行數據壓縮,幀內數據壓縮解決的是空間上的數據冗餘。
人眼對圖象都有一個識別度,對低頻的亮度很敏感,對高頻的亮度不太敏感。所以基於一些研究,可以將一幅圖像中人眼不敏感的數據去除掉。這樣就提出了幀內預測技術。
一幅圖像被劃分好宏塊後,對每個宏塊可以進行 9 種模式的預測。找出與原圖最接近的一種預測模式。然後,將原始圖像與幀內預測後的圖像相減得殘差值。再將我們之前得到的預測模式信息一起保存起來,這樣我們就可以在解碼時恢復原圖了,經過幀內與幀間的壓縮後,雖然數據有大幅減少,但還有優化的空間。
可以將殘差數據做整數離散餘弦變換,去掉數據的相關性,進一步壓縮數據。
上面的幀內壓縮是屬於有損壓縮技術。也就是說圖像被壓縮後,無法完全復原。而CABAC屬於無損壓縮技術。
無損壓縮技術大家最熟悉的可能就是哈夫曼編碼了,給高頻的詞一個短碼,給低頻詞一個長碼從而達到數據壓縮的目的。MPEG-2中使用的VLC就是這種演算法,我們以 A-Z 作為例子,A屬於高頻數據,Z屬於低頻數據。看看它是如何做的。
CABAC也是給高頻數據短碼,給低頻數據長碼。同時還會根據上下文相關性進行壓縮,這種方式又比VLC高效很多。
制定了相互傳輸的格式,將宏快 有組織,有結構,有順序的形成一系列的碼流。這種碼流既可 通過 InputStream 網路流的數據進行傳輸,也可以封裝成一個文件進行保存,主要作用是為了傳輸。
組成H264碼流的結構中 包含以下幾部分 ,從大到小排序依次是:
H264視頻序列,圖像,片組,片,NALU,宏塊 ,像素。
NAL層:(Network Abstraction Layer,視頻數據網路抽象層) : 它的作用是H264隻要在網路上傳輸,在傳輸的過程每個包乙太網是1500位元組,而H264的幀往往會大於1500位元組,所以要進行拆包,將一個幀拆成多個包進行傳輸,所有的拆包或者組包都是通過NAL層去處理的。
VCL層:(Video Coding Layer,視頻數據編碼層) : 對視頻原始數據進行壓縮
起始碼0x 00 00 00 01 或者 0x 00 00 01 作為 分隔符 。
兩個 0x 00 00 00 01之間的位元組數據 是表示一個NAL Unit。
I 幀的特點:
1.分組:把幾幀圖像分為一組(GOP,也就是一個序列),為防止運動變化,幀數不宜取多。
2.定義幀:將每組內各幀圖像定義為三種類型,即I幀、B幀和P幀;
3.預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
4.數據傳輸:最後將I幀數據與預測的差值信息進行存儲和傳輸。
1.更高的編碼效率:同H.263等標準的特率效率相比,能夠平均節省大於50%的碼率。
2.高質量的視頻畫面:H.264能夠在低碼率情況下提供高質量的視頻圖像,在較低帶寬上提供高質量的圖像傳輸是H.264的應用亮點。
3.提高網路適應能力:H.264可以工作在實時通信應用(如視頻會議)低延時模式下,也可以工作在沒有延時的視頻存儲或視頻流伺服器中。
4.採用混合編碼結構:同H.263相同,H.264也使用採用DCT變換編碼加DPCM的差分編碼的混合編碼結構,還增加了如多模式運動估計、幀內預測、多幀預測、基於內容的變長編碼、4x4二維整數變換等新的編碼方式,提高了編碼效率。
5.H.264的編碼選項較少:在H.263中編碼時往往需要設置相當多選項,增加了編碼的難度,而H.264做到了力求簡潔的「回歸基本」,降低了編碼時復雜度。
6.H.264可以應用在不同場合:H.264可以根據不同的環境使用不同的傳輸和播放速率,並且提供了豐富的錯誤處理工具,可以很好的控制或消除丟包和誤碼。
7.錯誤恢復功能:H.264提供了解決網路傳輸包丟失的問題的工具,適用於在高誤碼率傳輸的無線網路中傳輸視頻數據。
8.較高的復雜度:264性能的改進是以增加復雜性為代價而獲得的。據估計,H.264編碼的計算復雜度大約相當於H.263的3倍,解碼復雜度大約相當於H.263的2倍。
H.264的目標應用涵蓋了目前大部分的視頻服務,如有線電視遠程監控、交互媒體、數字電視、視頻會議、視頻點播、流媒體服務等。H.264為解決不同應用中的網路傳輸的差異。定義了兩層:視頻編碼層(VCL:Video Coding Layer)負責高效的視頻內容表示,網路提取層(NAL:Network Abstraction Layer)負責以網路所要求的恰當的方式對數據進行打包和傳送。