音頻編碼實戰(zhàn)

隨著5G時代的到來,音視頻領(lǐng)域?qū)蠓女惒省?/p>

5G讓所有人興奮,用戶期待,因為5G網(wǎng)絡(luò)更快更穩(wěn)定延遲更低。運營商和上下游產(chǎn)業(yè)也期待,大家都想在5G時代分一杯羹。

近幾年抖音快手B站等App的火熱,已經(jīng)說明問題了。隨著WiFi設(shè)施的全面普及,流量費用的進一步下降,使得我們隨時隨地刷視頻成為了可能?;叵肫鹞掖髮W(xué)時代,那個時候流量很貴,貴到什么程度呢?1M流量要10塊錢!大家想一想,1M流量10塊錢,1G流量1萬塊錢,你還敢用4G刷視頻么?4G時代,大家刷短視頻,5G時代,大家刷長視頻。基于這個判斷,音視頻相關(guān)技術(shù)是未來幾年的熱點,除了抖音快手,新的現(xiàn)象級客戶端有可能會出現(xiàn)。

作為移動開發(fā)人員,如何跟上熱點學(xué)習(xí)音視頻技術(shù)呢?

FFmpeg流程?

從本地文件讀取PCM數(shù)據(jù)進行AAC格式編碼,然后將編碼后的AAC數(shù)據(jù)存儲到本地文件。

示例的流程如下所示。

關(guān)鍵函數(shù)說明:

avcodec_find_encoder:根據(jù)指定的AVCodecID查找注冊的編碼器。

avcodec_alloc_context3:為AVCodecContext分配內(nèi)存。

avcodec_open2:打開編碼器。

avcodec_send_frame:將AVFrame非壓縮數(shù)據(jù)給編碼器。

avcodec_receive_packet:獲取到編碼后的AVPacket數(shù)據(jù),收到的packet需要自己釋放內(nèi)存。

av_frame_get_buffer: 為音頻或視頻幀分配新的buffer。在調(diào)用這個函數(shù)之前,必須在AVFame上設(shè)

置好以下屬性:format(視頻為像素格式,音頻為樣本格式)、nb_samples(樣本個數(shù),針對音頻)、

channel_layout(通道類型,針對音頻)、width/height(寬高,針對視頻)。

av_frame_make_writable:確保AVFrame是可寫的,使用av_frame_make_writable()的問題是,在

最壞的情況下,它會在您使用encode再次更改整個輸入frame之前復(fù)制它. 如果frame不可寫,

av_frame_make_writable()將分配新的緩沖區(qū),并復(fù)制這個輸入input frame數(shù)據(jù),避免和編碼器需

要緩存該幀時造成沖突。

av_samples_fill_arrays 填充音頻幀


對于 flush encoder的操作:

編碼器通常的沖洗方法:調(diào)用一次 avcodec_send_frame(NULL)(返回成功),然后不停調(diào)用

avcodec_receive_packet() 直到其返回 AVERROR_EOF,取出所有緩存幀,

2avcodec_receive_packet() 返回 AVERROR_EOF 這一次是沒有有效數(shù)據(jù)的,僅僅獲取到一

個結(jié)束標(biāo)志

PCM樣本格式

PCM(Pulse Code Modulation,脈沖編碼調(diào)制)音頻數(shù)據(jù)是未經(jīng)壓縮的音頻采樣數(shù)據(jù)裸流,它是由模擬信

號經(jīng)過采樣、量化、編碼轉(zhuǎn)換成的標(biāo)準數(shù)字音頻數(shù)據(jù)。

描述PCM數(shù)據(jù)的6個參數(shù):

1. Sample Rate : 采樣頻率。8kHz(電話)、44.1kHz(CD)、48kHz(DVD)。

2. Sample Size : 量化位數(shù)。通常該值為16-bit。

3. Number of Channels : 通道個數(shù)。常用的音頻有立體聲(stereo)和單聲道(mono)兩種類型,立體聲包

含左聲道和右聲道。另外還有環(huán)繞立體聲等其它不太常用的類型。

4. Sign : 表示樣本數(shù)據(jù)是否是有符號位,比如用一字節(jié)表示的樣本數(shù)據(jù),有符號的話表示范圍為-128 ~

127,無符號是0 ~ 255。有符號位16bits數(shù)據(jù)取值范圍為-32768~32767。

5. Byte Ordering : 字節(jié)序。字節(jié)序是little-endian還是big-endian。通常均為little-endian。字節(jié)序說

明見第4節(jié)。

6. Integer Or Floating Point : 整形或浮點型。大多數(shù)格式的PCM樣本數(shù)據(jù)使用整形表示,而在一些對

精度要求高的應(yīng)用方面,使用浮點類型表示PCM樣本數(shù)據(jù)(浮點數(shù) float值域為 [-1.0, 1.0])。

推薦的PCM數(shù)據(jù)播放工具:

ffplay, 使用示例如下:

1 //播放格式為f32le,雙聲道,采樣頻率48000Hz的PCM數(shù)據(jù)

2 ffplay -f f32le -ac 2 -ar 48000 pcm_audio

Audacity:一款免費開源的跨平臺音頻處理軟件。

Adobe Auditon。導(dǎo)入原始數(shù)據(jù),打開的時候需要選擇采樣率、格式和字節(jié)序。

FFmpeg支持的PCM數(shù)據(jù)格式

使?ffmpeg -formats命令,獲取ffmpeg支持的音視頻格式,其中我們可以找到支持的PCM格式。

1 DE alaw PCM A-law

2 DE f32be PCM 32-bit floating-point big-endian

3 DE f32le PCM 32-bit floating-point little-endian

4 DE f64be PCM 64-bit floating-point big-endian

5 DE f64le PCM 64-bit floating-point little-endian

6 DE mulaw PCM mu-law

37 DE s16be PCM signed 16-bit big-endian

8 DE s16le PCM signed 16-bit little-endian

9 DE s24be PCM signed 24-bit big-endian

10 DE s24le PCM signed 24-bit little-endian

11 DE s32be PCM signed 32-bit big-endian

12 DE s32le PCM signed 32-bit little-endian

13 DE s8 PCM signed 8-bit

14 DE u16be PCM unsigned 16-bit big-endian

15 DE u16le PCM unsigned 16-bit little-endian

16 DE u24be PCM unsigned 24-bit big-endian

17 DE u24le PCM unsigned 24-bit little-endian

18 DE u32be PCM unsigned 32-bit big-endian

19 DE u32le PCM unsigned 32-bit little-endian

20 DE u8 PCM unsigned 8-bit

s是有符號,u是無符號,f是浮點數(shù)。

be是大端,le是小端。

FFmpeg中Packed和Planar的PCM數(shù)據(jù)區(qū)別

FFmpeg中音視頻數(shù)據(jù)基本上都有Packed和Planar兩種存儲存式,對于雙聲道音頻來說,

Packed方式為兩個聲道的數(shù)據(jù)交錯存儲;Planar方式為兩個聲道分開存儲。假設(shè)一個L/R為?

個采樣點,數(shù)據(jù)存儲的方式如下所示:

Packed: L R L R L R L R

Planar: L L L L ... R R R R...

packed格式

1 AV_SAMPLE_FMT_U8, ///< unsigned 8 bits

2 AV_SAMPLE_FMT_S16, ///< signed 16 bits

3 AV_SAMPLE_FMT_S32, ///< signed 32 bits

4 AV_SAMPLE_FMT_FLT, ///< float

5 AV_SAMPLE_FMT_DBL, ///< double

只能保存在AVFrame的uint8_t *data[0];

音頻保持格式如下:

LRLRLR...

planar為FFmpeg內(nèi)部存儲音頻使的采樣格式,所有的Planar格式后都有字P標(biāo)識。

1 AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar

2 AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar

3 AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar

4 AV_SAMPLE_FMT_FLTP, ///< float, planar

5 AV_SAMPLE_FMT_DBLP, ///< double, planar

6 AV_SAMPLE_FMT_S64, ///< signed 64 bits

7 AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar

plane 0: LLLLLLLLLLLLLLLLLLLLLLLLLL...

plane 1: RRRRRRRRRRRRRRRRRRRR....

plane 0對于uint8_t *data[0];

plane 1對于uint8_t *data[1];

FFmpeg默認的AAC編碼器不?持AV_SAMPLE_FMT_S16格式的編碼,只支持

AV_SAMPLE_FMT_FLTP,這種格式是按平面存儲,樣點是float類型,所謂平面也就是

每個聲道單獨存儲.如左聲道存儲到data[0]中,右聲道存儲到data[1]中。

FFmpeg音頻解碼后和編碼前的數(shù)據(jù)是存放在AVFrame結(jié)構(gòu)中的。

Packed格式,frame.data[0]或frame.extended_data[0]包含所有的音頻數(shù)據(jù)中。

Planar格式,frame.data[i]或者frame.extended_data[i]表示第i個聲道的數(shù)據(jù)(假設(shè)聲道0是第一?

個), AVFrame.data數(shù)組大小固定為8,如果聲道數(shù)超過8,需要從frame.extended_data獲取聲道數(shù)

據(jù)。

補充說明

Planar模式是ffmpeg內(nèi)部存儲模式,我們實際使用 的音頻文件都是Packed模式的。

FFmpeg解碼不同格式的音頻輸出的音頻采樣格式不是一樣。測試發(fā)現(xiàn),其中AAC解碼輸出的數(shù)據(jù)為浮

點型的 AV_SAMPLE_FMT_FLTP 格式,MP3解碼輸出的數(shù)據(jù)為 AV_SAMPLE_FMT_S16P 格式(使

用的mp3文件為16位深)。具體采樣格式可以查看解碼后的AVFrame中的format成員或編解碼器的

AVCodecContext中的sample_fmt成員。

Planar或者Packed模式直接影響到保存文件時寫文件的操作,操作數(shù)據(jù)的時候一定要先檢測音頻采樣

格式。

PCM字節(jié)序

談到字節(jié)序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列

CPU。PowerPC系列采用big endian方式存儲數(shù)據(jù),而x86系列則采用little endian方式存儲數(shù)據(jù)。那么

究竟什么是big endian,什么又是little endian?

big endian是指低地址存放最高有效字節(jié)(MSB,Most Significant Bit),而little endian則是低地址

存放最低有效字節(jié)(LSB,Least Significant Bit)。

下圖像加以說明。比如數(shù)字0x12345678在兩種不同字節(jié)序CPU中的存儲順序如下所示:

Big Endian

低地址 ?高地址

---------------------------------------------------------------------------

-->

| 12 | 34 | 56 | 78 |

Little Endian

低地址 ?高地址

---------------------------------------------------------------------------

-->

| 78 | 56 | 34 | 12 |

所有網(wǎng)絡(luò)協(xié)議都是采用big endian的方式來傳輸數(shù)據(jù)的。所以也把big endian方式稱之為網(wǎng)絡(luò)字節(jié)序。當(dāng)

兩臺采用不同字節(jié)序的主機通信時,在發(fā)送數(shù)據(jù)之前都必須經(jīng)過字節(jié)序的轉(zhuǎn)換成為往絡(luò)字節(jié)序后再進行傳

輸。

更多音視頻學(xué)習(xí),關(guān)注

個人介紹領(lǐng)取 音視頻資料

音視頻課程學(xué)習(xí)大綱

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 目錄 什么是PCM? PCM數(shù)據(jù)格式 FFmpeg支持的PCM數(shù)據(jù)格式 FFmpeg中Packed和Planar的...
    smallest_one閱讀 47,395評論 1 32
  • 一.聲音的相關(guān)概念 聲音是介質(zhì)振動在聽覺系統(tǒng)中產(chǎn)生的反應(yīng)。聲音總可以被分解為不同頻率不同強度正弦波的疊加(傅里葉變...
    泥孩兒0107閱讀 4,609評論 6 9
  • 聲波 這里為啥講到了聲波,講到了我們的中學(xué)物理上的知識,因為我想大家能從根本理解后面音頻編碼的各種參數(shù)以及原因。當(dāng)...
    第八區(qū)閱讀 8,966評論 0 31
  • //音頻編碼 JNIEXPORT void JNICALL Java_com_tz_dream_ffmpeg_an...
    Jackey_song閱讀 1,692評論 0 1
  • 本篇博客在雷神的結(jié)構(gòu)體介紹基礎(chǔ)上按自己的喜好整理的 后面根據(jù)自己工作中所需有所增改 AVStream 存儲每一個視...
    石丘閱讀 2,616評論 1 10

友情鏈接更多精彩內(nèi)容