最近在玩一個類似小咖秀的項目,所以對AVFoundation有了一些的研究。這是AVFoundation的第一篇,準備先介紹一些AVFoundation中的基礎知識
音頻采樣
大自然中的聲音,他的形態是一種波。我們通過采樣,將這種波量化成數據,記錄下來,如下圖所示:
如上圖所示,采樣的數據并不能完整的還原出原來的波形,只能做到盡量接近原波形。并且采樣率(采樣的次數)越高,波形越接近原波形。不過采樣的次數增多,必然會導致存儲的數據量要增加,所以我們不可能無限提升采樣率。經過長期的研究人們發現,當采樣率等于波形中最高頻率的2倍時,已經足夠將波形還原到可接受的程度了。這個頻率稱為奈奎斯特頻率。人耳能接受的最高頻率為20kHz,所以只要采樣率超過40kHz,就可以呈現出可接受的聲音。目前常見的CD采樣率為44.1kHz。
除了采樣率之外,音頻采樣還有一個重要參數叫做音頻的位元深度。表示用多少位(bit)定義線性維度上的離散度來保存一個音頻樣本。位數越高,離散度越多,表示的聲音越精確(音質越好)。一般來說16bit比較常見,可以表示65536個離散度。
一個音頻文件的體積,有如下算法:體積=采樣率*位元深度*音道數*時間
。
音頻壓縮
對聲音進行采樣、量化過程被稱為脈沖編碼調制(Pulse Code Modulation),直接脈沖編碼調制(Linear Pulse Code Modulation)產生的數據稱為Linear PCM數據,LPCM數據是最原始的音頻數據完全無損,但是他的體積非常大,比如一個44.1kHz,16bit,雙音道的音頻文件,每分鐘的數據量為44.1*16*2*60kbit=10.3M。一個普通5分鐘的音樂就得50M,這個數據量對普通用戶來說是過于龐大的。
為了解決這個問題,誕生了一系列的壓縮算法,其中主要分為有無損壓縮(ALAC、APE、FLAC)和有損壓縮(MP3、AAC、OGG、WMA)兩種。其具體的壓縮算法對應到AVFoundation的CoreAudioTypes.h
中有:
CF_ENUM(AudioFormatID)
{
kAudioFormatLinearPCM = 'lpcm',
kAudioFormatAC3 = 'ac-3',
kAudioFormat60958AC3 = 'cac3',
kAudioFormatAppleIMA4 = 'ima4',
kAudioFormatMPEG4AAC = 'aac ',
kAudioFormatMPEG4CELP = 'celp',
kAudioFormatMPEG4HVXC = 'hvxc',
kAudioFormatMPEG4TwinVQ = 'twvq',
kAudioFormatMACE3 = 'MAC3',
kAudioFormatMACE6 = 'MAC6',
kAudioFormatULaw = 'ulaw',
kAudioFormatALaw = 'alaw',
kAudioFormatQDesign = 'QDMC',
kAudioFormatQDesign2 = 'QDM2',
kAudioFormatQUALCOMM = 'Qclp',
kAudioFormatMPEGLayer1 = '.mp1',
kAudioFormatMPEGLayer2 = '.mp2',
kAudioFormatMPEGLayer3 = '.mp3',
kAudioFormatTimeCode = 'time',
kAudioFormatMIDIStream = 'midi',
kAudioFormatParameterValueStream = 'apvs',
kAudioFormatAppleLossless = 'alac',
kAudioFormatMPEG4AAC_HE = 'aach',
kAudioFormatMPEG4AAC_LD = 'aacl',
kAudioFormatMPEG4AAC_ELD = 'aace',
kAudioFormatMPEG4AAC_ELD_SBR = 'aacf',
kAudioFormatMPEG4AAC_ELD_V2 = 'aacg',
kAudioFormatMPEG4AAC_HE_V2 = 'aacp',
kAudioFormatMPEG4AAC_Spatial = 'aacs',
kAudioFormatAMR = 'samr',
kAudioFormatAMR_WB = 'sawb',
kAudioFormatAudible = 'AUDB',
kAudioFormatiLBC = 'ilbc',
kAudioFormatDVIIntelIMA = 0x6D730011,
kAudioFormatMicrosoftGSM = 0x6D730031,
kAudioFormatAES3 = 'aes3',
kAudioFormatEnhancedAC3 = 'ec-3'
};
色彩二次抽樣
經過大量的研究表明,人的眼睛對亮度非常敏感,但是對色彩信息比較遲鈍。色彩二次抽樣是指在原有的圖片樣本中,二次抽樣,減少對色彩信息的抽樣,而達到減小圖片體積(樣本數減?。?,又不怎么影響圖片質量(眼睛對色彩不敏感)的效果。
視頻數據使用的是YCbCr的顏色模型,YCbCr也稱為YUV。其中Y表示亮度分量,Cb表示藍色分量,Cr表示紅色分量。
常用的YCbCr有4:4:4、4:2:2、4:2:0、4:1:1。
- 4:4:4 亮度和色彩信息的比值為1:1,所有色彩信息都會被抽樣,也就是全彩。
- 4:2:2 亮度和色彩信息的比值為2:1,只有1/2的色彩信息被抽樣
- 4:2:0和4:1:1 亮度和色彩信息比值為4:1,只有1/4的色彩信息被抽樣
對應到AVFoundation的CVImageBuffer.h
中有:
CV_EXPORT const CFStringRef CV_NONNULL kCVImageBufferChromaSubsamplingKey __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_4_0); // CFString/CFNumber with one of the following values
CV_EXPORT const CFStringRef CV_NONNULL kCVImageBufferChromaSubsampling_420 __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_4_0);
CV_EXPORT const CFStringRef CV_NONNULL kCVImageBufferChromaSubsampling_422 __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_4_0);
CV_EXPORT const CFStringRef CV_NONNULL kCVImageBufferChromaSubsampling_411 __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_4_0);
一些特別專業的相機可能會用到4:4:4參數捕捉圖片,大部分情況下會用4:2:2參數,普通的攝像頭(如:iPhone攝像頭)一般都是4:2:0、4:1:1
H.264
跟音頻文件相比,視頻文件體積更大。我們平時使用的視頻文件都是經過壓縮處理的。大部分音視頻都使用編解碼器(codec)來進行壓縮和解壓,iOS中使用的主要編解碼器標準為H.264,H.264對應AVFoundation的AVVideoSettings.h
中:
AVF_EXPORT NSString *const AVVideoCodecKey /* NSString (CMVideoCodecType) */ NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVVideoCodecH264 /* @"avc1" */ NS_AVAILABLE(10_7, 4_0);
H.264通過空間和時間2個維度來壓縮體積:
- 空間:空間上的壓縮獨立于視頻幀,也稱為幀內壓縮。主要通過壓縮圖片的方式(如色彩二次抽樣等)來減小體積,幀內壓縮一般為有損壓縮
- 時間:時間上的壓縮也稱為幀間壓縮。視頻是由連續的幀(圖片)組成。一段視頻中(很多張圖片)有很多不變的冗余元素,通過減小這些冗余元素來達到壓縮的目的,這就是幀間壓縮,幀間壓縮一般為無損壓縮
H.264有3種profile,用于確定編碼過程中幀間壓縮使用的算法:
- BaseLine:這個標準提供了最低效的壓縮,經過這個標準壓縮后的文件體積任然比較大,但是這種算法計算強度最小
- Main:這個標準的計算強度比BaseLine大,但是能達到更高的壓縮效果
- High:這個標準能達到最高質量的壓縮效果,但他的壓縮算法最復雜
H.264除了profile還有一個等級(Level)標準,Level是對自身特性的一些描述(碼率,分辨率,fps等),Level越高,視頻的碼率、分辨率、fps越高。
對應AVfoundation的AVVideoSettings.h
中:
AVF_EXPORT NSString *const AVVideoProfileLevelKey /* NSString, H.264 only, one of: */ NS_AVAILABLE(10_8, 4_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Baseline30 /* Baseline Profile Level 3.0 */ NS_AVAILABLE(10_8, 4_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Baseline31 /* Baseline Profile Level 3.1 */ NS_AVAILABLE(10_8, 4_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Baseline41 /* Baseline Profile Level 4.1 */ NS_AVAILABLE(10_8, 5_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264BaselineAutoLevel /* Baseline Profile Auto Level */ NS_AVAILABLE(10_9, 7_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Main30 /* Main Profile Level 3.0 */ NS_AVAILABLE(10_8, 4_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Main31 /* Main Profile Level 3.1 */ NS_AVAILABLE(10_8, 4_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Main32 /* Main Profile Level 3.2 */ NS_AVAILABLE(10_8, 5_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264Main41 /* Main Profile Level 4.1 */ NS_AVAILABLE(10_8, 5_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264MainAutoLevel /* Main Profile Auto Level */ NS_AVAILABLE(10_9, 7_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264High40 /* High Profile Level 4.0 */ NS_AVAILABLE(10_9, 6_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264High41 /* High Profile Level 4.1 */ NS_AVAILABLE(10_9, 6_0);
AVF_EXPORT NSString *const AVVideoProfileLevelH264HighAutoLevel /* High Profile Auto Level */ NS_AVAILABLE(10_9, 7_0);
一些移動設備(手機、游戲機、PMP)由于性能有限,不支持全部高級視頻壓縮特性和高分辨率圖像,只支持基礎壓縮特性和分辨率低一些的圖像。
視頻碼率(bitRate)
碼率是指單位時間內傳輸的數據位數。視頻體積=視頻碼率*時間
,由此可見固定長度的視頻,碼率是決定大小的唯一因素。視頻碼率決定著視頻的壓縮效果,也決定了視頻是質量。碼率越高,質量越好,體積越大。碼率越低,體積越小,視頻質量也越差。
編碼時,根據碼率可以分為固定碼率(CBR)編碼和可變碼率(VBR)編碼。
- 固定碼率:指編碼器輸出的碼率一直為一個固定值,這種編碼方式計算量小,編碼速度快,但是編碼效果不怎么好。對于畫面變化大的視頻片段,由于碼率限制,導致視頻非常模糊,然而對于畫面變化小的片段,卻會造成碼率浪費。
- 可變碼率:指編碼器的輸出碼率可以根據編碼器的輸入源信號的復雜度自適應的調整,這種方式編碼效果比較好
碼率對應于AVFoundation中AVVideoSettings.h
:
AVF_EXPORT NSString *const AVVideoAverageBitRateKey /* NSNumber (bits per second, H.264 only) */ NS_AVAILABLE(10_7, 4_0);
Reference
AV Foundation 開發秘籍
iOS音頻播放 (一):概述
H.264中profile和level
音頻的位元深度
奈奎斯特頻率