聲音的渲染在iOS平臺(tái)上會(huì)直接使用AudioUnit(AUGraph)
之類的API接口,Android平臺(tái)則使用 OpenSL ES或者AudioTrack這兩類接口裹纳。而對(duì)于視頻畫(huà)面的渲染,筆者會(huì)為大家介紹一種跨平臺(tái)的渲染技術(shù)紧武,即OpenGL ES
剃氧。
一 AudioUnit介紹與實(shí)踐
在iOS平臺(tái)上,所有的音頻框架底層都是基于AudioUnit
實(shí)現(xiàn)的阻星。較高層次的音頻框架包括:Media Player
朋鞍、AV Foundation
、OpenAL
和Audio Toolbox
妥箕,這些框架都封裝了AudioUnit
滥酥,然后提供了更高層次的API(功能更少,職責(zé)更單一的接口)畦幢。
1.1 認(rèn)識(shí)AudioSession
音頻會(huì)話(AudioSession
)坎吻, 其用于管理與獲取iOS設(shè)備音頻的硬件信息,并且是以單例的形式存在宇葱。
1.2 構(gòu)建AudioUnit
在創(chuàng)建并啟用音頻會(huì)話之后瘦真,就可以構(gòu)建AudioUnit了。構(gòu)建 AudioUnit的時(shí)候需要指定類型(Type)
黍瞧、子類型(subtype)
以及廠商 (Manufacture)
吗氏。
那么如何使用這個(gè)描述來(lái)構(gòu)造真正的AudioUnit
呢?有兩種方式雷逆。
- 裸創(chuàng)建方式
- AUGraph創(chuàng)建方式
1.3 AudioUnit的通用參數(shù)設(shè)置
輸入端一般是指麥克風(fēng),輸出端一般是指揚(yáng)聲器(Speaker)或者耳機(jī)污尉。
1.4 AudioUnit的分類
-
Effect Unit
類型是kAudioUnitType_Effect膀哲,主要提供聲音特效處理的功能往产。 -
Mixer Units
類型是kAudioUnitType_Mixer,主要提供Mix多路聲音的功能某宪。 -
I/O Units
類型是kAudioUnitType_Output仿村,它的用途就像其分類的名字一樣,主要提供的就是I/O的功能兴喂。 -
Format Converter Units
類型是kAudioUnitType_FormatConverter蔼囊,主要用于提供格式轉(zhuǎn)換的功能。 -
Generator Units
類型是kAudioUnitType_Generator衣迷,在開(kāi)發(fā)中我們經(jīng)常使用它來(lái)提供播放器的功能畏鼓。
1.5 構(gòu)造一個(gè)AUGraph
AUGraph
的方式將聲音采集、聲音處理以及聲音輸出的整個(gè)過(guò)程管理起來(lái)壶谒。
二 視頻渲染
2.1 OpenGL ES 介紹
OpenGL(Open Graphics Library)定義了一個(gè)跨編程語(yǔ)言云矫、跨平臺(tái) 編程的專業(yè)圖形程序接口。
在iOS平臺(tái)上使用EAGL
提供本地平臺(tái)對(duì)OpenGL ES
的實(shí)現(xiàn)汗菜。
OpenGL
主要是做圖形圖像處理的庫(kù)让禀,尤其是在移動(dòng)設(shè)備上進(jìn)行圖形圖像處理,它的性能優(yōu)勢(shì)更能體現(xiàn)出來(lái)陨界。
GLSL
(OpenGL Shading Language)是OpenGL的著色器語(yǔ)言巡揍。
2.2 OpenGL ES的實(shí)踐
而在顯卡中,這些像素點(diǎn)可以組織成幀緩沖區(qū)
(FrameBuffer)的形式菌瘪,幀緩沖區(qū)保存了圖形硬件為了控制屏幕上所有像素的顏色和強(qiáng)度所需要的全部信息腮敌。
渲染管線分為以下幾個(gè)階段。
- 階段一 指定幾何對(duì)象
- 階段二 頂點(diǎn)處理
- 階段三 圖元組裝
- 階段四 柵格化操作
- 階段五 片元處理
- 階段六 幀緩沖操作
glFinish和glFlush
因此每次寫(xiě)完繪圖代碼麻车,需要讓其 立即完成效果時(shí)缀皱,開(kāi)發(fā)者都需要在代碼后面添加glFlush()或 glFinish()函數(shù)。
2.3 上下文環(huán)境搭建
EGL
是雙
緩沖的工作模式动猬,即有一個(gè)Back Frame Buffer
和一個(gè)Front Frame Buffer
啤斗。
iOS平臺(tái)不允許直接渲染到屏幕上,因此要使用renderBuffer
來(lái)代替赁咙。
在iOS平臺(tái)上不允許開(kāi)發(fā)者使用OpenGL ES
直接渲染屏幕钮莲,必須使 用FrameBuffer
與RenderBuffer
來(lái)進(jìn)行渲染。
若要使用EAGL
彼水,則必須先創(chuàng)建一個(gè)RenderBuffer
崔拥,然后讓OpenGL ES
渲染到該RenderBuffer
上去。 而該RenderBuffer
則需要綁定到一個(gè)CAEAGLLayer
上面去凤覆,這樣開(kāi)發(fā)者 最后調(diào)用EAGLContext
的presentRenderBuffer
方法链瓦,就可以將渲染結(jié)果輸出到屏幕
上去了。
實(shí)際上,在調(diào)用這個(gè)方法時(shí)慈俯,EAGL
也會(huì)執(zhí)行類似于前面的swapBuffer
過(guò)程渤刃,將OpenGL ES
渲染的結(jié)果繪制到物理屏幕上去(View
的Layer
)。
2.4 OpenGL ES中的紋理
OpenGL
中的紋理可以用來(lái)表示圖像贴膘、照片卖子、視頻畫(huà)面等數(shù)據(jù)。
但是在OpenGL ES
的操作過(guò)程中必須告訴OpenGL ES
具體操作的是哪一個(gè)紋理對(duì)象刑峡。
一般在視頻的渲染與處理的時(shí)候使用GL_LINEAR
這種過(guò)濾方式洋闽。
OpenGL
的大部分紋理一般都只接受RGBA
類型的數(shù)據(jù),所以我們需要對(duì)PNG
這種壓縮格式進(jìn)行解碼操作突梦。
項(xiàng)目源碼地址 - OpenGLRenderer