下面是音視頻開發面試題精選:
- 1、談談 iOS 音視頻采集相關接口和數據結構的設計?
- 2、如何降低處理音視頻鏈路中的內存峰值?
- 3、OpenGL 如何實現二分屏效果?
- 4、使用 OpenGL 繪制時對于二維坐標需要注意什么?
1、談談 iOS 音視頻采集相關接口和數據結構的設計?
1)整體框架
通常我們通過 AVCaptureSession 相關的 API 來進行音視頻的采集,其中主要組件分為 Input、Output、Session 幾個部分:
- Input:AVCaptureDeviceInput,以 Device 作為輸入,分為:視頻采集設備、音頻采集設備,可以同時添加多個 Input。
- Output:可以指定圖片、視頻文件、音視頻裸幀數據等作為輸出,可以同時添加多個 Output。
- kCVPixelFormatType_32BGRA
- kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange(nv12 420v)
- kCVPixelFormatType_420YpCbCr8BiPlanarFullRange(nv12 420f)
- AVCaptureStillImageOutput 圖片
- AVCaptureMovieFileOutput 視頻文件
- AVCaptureAudioDataOutput 音頻裸幀
- AVCaptureVideoDataOutput 視頻裸幀,目前支持三種格式的輸出:
- AVCaptureSession 主要負責管理各個 Input、Output 以及它們的內部鏈路組合。
可以通過如下代碼獲取視頻輸出支持的格式:
AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init];
NSArray<NSNumber *> *types = [videoOut availableVideoCVPixelFormatTypes];
NSLog(@"type count: %ld", types.count); // 3 種
for (NSNumber *type in types) {NSLog(@"type: %@", type);
}
2)視頻采集
對于視頻采集,一般直接使用 AVCaptureSession 的 API 即可,需要注意的是:相機(前后置一樣)吐出的視頻幀,默認是橫屏模式的 (橫屏,Home 鍵在右邊,也就是順時針旋轉 90 度就變成 Home 鍵在下邊的正常豎屏狀態),跟 Android 略有差異。
視頻采集時會有一個 10 多幀的緩存,當我們沒有及時歸還相機吐出的視頻幀,導致采集吐幀的這個緩存空了,就會導致相機不吐幀。
3)音頻采集
對于音頻采集,除了可以使用 AVCaptureSession 來進行音頻采集外,還可以使用 AudioUnit。
使用 AVCaptureSession 可以和視頻采集在一起處理,也可以單獨創建新的 AVCaptureSession 進行音頻采集。
- 優點:由系統根據 AVAudioSession 自動處理音頻采集的開始和暫停,也就是系統中斷不用做特殊處理。
- 缺點:沒有辦法設置音頻采樣格式,所以在線路切換時,比如:從正常揚聲器切到藍牙耳機,采樣率可能會發生變化,這是就要進行重采樣,是采樣率保持一致。
使用 AudioUnit 音頻采集:
- 優點:更底層,更高效;在創建 unit 后,可以直接設置音頻采集格式(如:通道數等)。
- 缺點:需要自己處理音頻中斷等情況。
2、如何降低處理音視頻鏈路中的內存峰值?
音視頻處理鏈路中的內存峰值一般是視頻數據導致的,要降低內存峰值一般可以從兩個方面入手:
- 降低采集參數:
- 降低采集視頻分辨率
- 降低采集視頻幀率
- 降低并發任務數量:
- 將任務分優先級,按照優先級串行執行,這樣既能降低內存峰值,也會降低 CPU 峰值
3、OpenGL 如何實現二分屏效果?
以紋理 y 坐標中間分屏為例,代碼如下:
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D inputTexture;void main()
{float y;if (varyTextCoord.y >= 0.0 && varyTextCoord.y <= 0.5) {y = varyTextCoord.y + 0.25;} else {y = varyTextCoord.y - 0.25;}gl_FragColor = texture2D(inputTexture, vec2(varyTextCoord.x, y));
}
4、使用 OpenGL 繪制時對于二維坐標需要注意什么?
1)搞清楚頂點坐標與紋理坐標
- 頂點坐標是左下角是 (-1, -1),右上角是 (1, 1);
- 紋理坐標是左下角是 (0, 0),右上角是 (1, 1),也就是 (0, 0) 對應圖片的左下角,(1, 1) 對應著圖片的右上角;
- 頂點坐標與紋理坐標一一對應,默認設置的紋理坐標是平鋪滿整個頂點坐標的,所以在設置 fill、fit 模式時,只用設置頂點坐標即可。
GLfloat vertexes[] =
{-1.0, -1.0, //左下1.0, -1.0, //右下-1.0, 1.0, //左上1.0, 1.0 //右上
};GLfloat textures[] = {0.0f, 0.0f, //左下1.0f, 0.0f, //右下0.0f, 1.0f, //左上1.0f, 1.0f //右上
};
2)FBO 與 glViewport
首先繪制前 FBO 需要綁定了一個尺寸一致的 texture,繪制的內容會被繪制到這張 texture 上,這個就是 RTT,如果 FBO 為 0 則是屏幕繪制,否則是離屏繪制,可以將 FBO 看作畫板,texture 看做這張畫布。
一般我們會將 viewport 設置為: (0, 0, FBO.width, FBO.height),這樣繪制會占滿整個 FBO,而頂點的的4個頂點是與 viewport 的4個頂點一一對應的,當然紋理也是一樣對應的。
viewport 的 frame 和 FBO 不一致時,就會只在 viewport 的那塊區域進行繪制對應的內容,也就是將輸入的紋理在 viewport 的 frame 上進行繪制。
粉絲福利, 免費領取C++音視頻學習資料包+學習路線大綱、技術視頻/代碼,內容包括(音視頻開發,面試題,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,編解碼,推拉流,srs)↓↓↓↓↓↓見下面↓↓文章底部點擊免費領取↓↓