當前位置:成語大全網 - 新華字典 - 視頻編碼和解碼-編碼文章

視頻編碼和解碼-編碼文章

四、視頻編碼和解碼-編碼

時間?二十年代的閱讀

original/si-Shi-pin-de-bian-Jie-ma-bian-ma-pian/

主題iOS開發MacOS

在此之前,我們通常使用的FFmpeg多媒體庫都是使用CPU進行視頻編解碼,占用CPU資源,效率低下,俗稱軟編解碼。2014年,蘋果開放了VideoToolbox.framwork框架,使用GPU或者專用處理器進行編解碼,俗稱硬編解碼。在此之前,這個框架只能在MAC OS系統中使用,在iOS8中是私有框架。最後,

在WWDC直接訪問視頻編碼和解碼2014,蘋果公司推出了使用視頻工具箱進行硬編碼和解碼。

使用硬編解碼器有幾個優點:*提高性能;*提高效率;*擴大電力的使用。

對於編解碼,AVFoundation框架只有以下功能:1。直接解壓後顯示;

2.直接壓縮成文件;

至於視頻工具箱,我們可以通過以下函數獲取數據,並通過網絡流式保存:1。將其解壓縮成圖像的數據結構;

2.壓縮成視頻圖像的容器數據結構。

壹、videoToolbox的基本數據

描述了視頻工具箱中視頻編解碼前後需要應用的數據結構。

CVPixelBuffer:編碼前和解碼後的圖像數據結構。該內容包含壹系列CVPixelBufferPool內容。

CMTime、CMClock和CMTimebase:時間戳相關性。時間以64位/32位的形式出現。

PixelBufferAttributes:字典設置。它可能包括寬度/高度、像素格式類型、?兼容性(例如,OpenGL ES、核心動畫)

CMBlockBuffer:編碼後生成圖像的數據結構。

CMVideoFormatDescription:圖像存儲模式、編解碼器和其他格式描述。

(CMSampleBuffer:用於存儲編碼和解碼前後的視頻圖像的容器數據結構。

CMClock

CMTimebase:關於CMClock的控制視圖,包括CMClock、時間映射和速率控制。

從第二個我們可以知道,我們獲得的數據(CMSampleBufferRef)sample buffer data;

圖1.1

上圖中,編碼前後的視頻圖像封裝在CMSampleBuffer中,編碼前存儲在CVPixelBuffer中;編碼後存儲在CMBlockBuffer中。此外,兩者都包括CMTime和CMVideoFormatDesc。

第二,視頻數據流被編碼並上傳到服務器。

1.使用VTCompressionSession硬編碼CVPixelBuffer數據流。

(1)初始化VTCompressionSession

VT _ EXPORT OS status vtcompressionsession create(CM _ NULLABLE CFAllocatorRef?allocator,int32_t width,int32_t height,CMVideoCodecType codecType,CM _ NULLABLE CFDictionaryRef encoder specification,CM _ NULLABLE CFDictionaryRef sourceImageBufferAttributes,CM_NULLABLE CFAllocatorRef?compressedDataAllocator,CM _ NULLABLE VTCompressionOutputCallback output callback,void * CM_NULLABLE?outputCallbackRefCon,CM _ RETURNS _ RETAINED _ PARAMETER CM _ NULLABLE vtcompressionref * CM _ NONNULL compression session out)_ OSX _可用_起始(__MAC_10_8,_ _ IPHONE _ 8 _ 0);

VTCompressionSession初始化參數描述:

分配器:分配器,將NULL設置為默認分配。

寬度:寬度

高度:高

CodecType:編碼類型,如kCMVideoCodecType _ H264。

EncoderSpecification:編碼規範。設置NULL是由videoToolbox自己選擇的。

SourceImageBufferAttributes:源像素緩沖區屬性。設置NULL防止創建videToolbox,而是自己創建。

壓縮數據分配器。設置為空,默認分配。

OutputCallback:當調用VTCompression會話EncodeFrame壓縮壹次時,將異步調用。註意:設置NULL時,需要調用vt compression Session encode frame HoutButtHandler方法壓縮幀,支持iOS9.0以上版本。

OutputCallbackRefCon:回調自定義參考值。

CompressionSessionOut:壓縮會話變量。

(2)配置VTCompressionSession

使用VTSessionSetProperty()調用來配置壓縮。* KvtCompressionPropertyKey AllowFramereOrdering:允許幀重新排序。默認值為true * KvtCompressionPropertyKey平均比特率:設置所需的平均編碼速率* KvtCompressionPropertyKey H264熵編碼模式:H264熵編碼模式。有兩種模式:基於上下文的二進制算術編碼CABAC和變長編碼VLC。切片層(圖片和序列)以上使用定長或變長二進制編碼,切片層以下使用VLC或CABAC。詳見* kvt compression property key real time:視頻編碼壓縮是實時的嗎?您可以設置CFBoolean或NULL。默認值為null * KVTCompression PropertyKey配置文件級別:指定編碼流的配置和標準。例如KVTProfilelevel H264主自動級別。

配置VTCompressionSession後,可以選擇調用VTCompression Sessions Prepareto對幀進行編碼以進行準備。

(3)開始對輸入數據進行硬編碼。

使用vtCompression會話EncodeFrame方法進行編碼。編碼完成後,調用outputCallback回調函數。

VT_EXPORT OSStatus?VTCompressionSessionEncodeFrame(?CM _ NONNULL vtcompression session ref?session,CM _ NONNULL CVImageBufferRef image buffer,CMTime?presentationTimeStamp,CMTime?持續時間,//可能是kcmtimenivalidcm _ NULLABLE CFDictionaryRef frame properties,void* CM_NULLABLE?sourceFrameRefCon,VTEncodeInfoFlags * CM _ NULLABLE infoflags out)_ OSX _可用_首發(__MAC_10_8,_ _ IPHONE _ 8 _ 0);

PresentationTimeStamp:獲取的這個樣本緩沖區數據的顯示時間戳。傳遞給該會話的每個時間戳都大於前壹個演示時間戳。

持續時間:獲得的樣本緩沖數據的這壹幀的顯示時間。如果沒有時間信息,可以設置kCMTimeInvalid。

FrameProperties:包含此框架的屬性。幀的改變將影響隨後的編碼幀。

SourceFrameRefCon:回調函數會引用妳設置的這個幀的參考值。

InfoFlagsOut:指向壹個VTEncodeInfoFlags來接受編碼操作。如果使用異步操作,則設置kVTEncodeInfo _ Asynchronous同步操作,設置kVTEncodeInfo _ FrameDropped將NULL設置為不接受此信息。

(4)執行VTCompressionOutputCallback回調函數。

typedefvoid(* VTCompressionOutputCallback)(void * CM _ NULLABLE outputCallbackRefCon,void * CM _ NULLABLE sourceFrameRefCon,OS status status status,VTEncodeInfoFlags infoFlags,CM _ NULLABLE CMSampleBufferRef sample buffer);

OutputCallbackRefCon:回調函數的引用值

sourceframefcon:vt compression Sessions encode frame函數中設置的幀的參考值。

狀態:壓縮成功是noErr,失敗有錯誤碼。

InfoFlags:包含編碼操作的信息標識符。

SampleBuffer:如果壓縮成功或者幀沒有丟失,則包含此壓縮數據CMSampleBuffer,否則為NULL。

(5)將成功壓縮的sampleBuffer數據處理成基本流NSData並上傳到服務器。

MPEG-4是壹套用於音頻和視頻信息的壓縮編碼標準。

從圖1.1可以看出$$CMSampleBuffer = CMTime(可選)+cmblock buffer+cmideoformat desc $ $已經被壓縮。

5.1首先判斷壓縮後的數據是否正確。

//如果不存在,說明壓縮不成功或者丟幀,如果(!sampleBuffer)返回;如果(狀態!= noErr)返回;//返回sampleBuffer中包含可變字典的不可變數組,或者nullcfarrayrearray =?cmsamplebuffergetsampleattachmentsaray(sample buffer,true);如果(!數組)返回;?CFDictionaryRef DIC = CFArrayGetValueAtIndex(array,0);如果(!dic)返回;//issue 3:kcmsampletachmentkey _ not sync:沒有這個鍵,表示同步,是:異步。否:同步布爾關鍵幀=!CFDictionaryContainsKey(dic,kcmsampletachmentkey _ NotSync);//這表示同步。

對於問題3,字面意思就是上面的解釋,但是很多都是用在網上查詢是否是視頻關鍵幀,查詢文檔看到這個關鍵幀鍵值kcmsampleBufferAttachmentKey _ Force key frame是存在的,所以如果知道這個值的話,請告知詳情。

5.2獲取cmvideoformattesc的數據從第三部分我們可以知道,cmvideoformattesc包括圖像的輪廓、層次、寬高、去塊濾鏡等。具體包括第壹NALU的SPS(序列參數集)和第二NALU的PPS(畫面參數集)。

//if(關鍵幀& amp& amp!編碼器->;Sps) {//在samplebuffer中獲取cmvedeoformattesc cmformatdescriptoref format = cmsamplebuffergetformatdescription(sample buffer);//獲取H264參數集中的SPS和PPS const uint8 _ t * sparameterSetsize_t sparameterSetSize,sparameterSetCount?OS status status code = cmvideoformattescriptiongeth 264 parametersetandix(format,0,& ampspara meterset & amp;sparameterSetSize & amp;sparameterSetCount,0);if(status code = = noErr){ size _ t pparameterSetSize,pparameterSetCountconst uint8 _ t * pparameterSetOS status status code = cmvideoformatedescriptiongeth 264 parametersetandix(format,1,& amp參數集。pparameterSetSize。pparameterSetCount,0);if(status code = = noErr){ encoder-& gt;SPs =[ns data dataWithBytes:sparameterSetlength:sparameterSetSize];編碼器->;PPS =[ns data dataWithBytes:pparameterSetlength:pparameterSetSize];} }}

5.3獲取CMBlockBuffer並將其轉換為數據

CMBlockBufferRef block buffer = CMSampleBufferGetDataBuffer(sample buffer);size_t?lengthAtOffset,totalLengthchar * dataPointer//接收到的數據顯示OS狀態block buffer Status = cmBlockBufferGetDataPointer(block buffer,0,&;長度偏移量。總長度。data pointer);if(blockBufferStatus!= kCMBlockBufferNoErr){ size _ t buffer offset = 0;staticconstantavccheaderlength = 4;while(buffer offset & lt;總長度?AVCCHeaderLength) {//讀取NAL單位長度uint 32 _ t NALUnitLength = 0;/**

*?void *memcpy(void *dest,const void *src,size _ t n);

*?從源src指向的內存地址的起始位置復制n個字節到目標dest指向的內存地址的起始位置。

*/memcpy(& amp;NALUnitLength,dataPointer + bufferOffset,AVCCHeaderLength);//字節從高位到低位反轉nalunitlength = cfswapint 32 bigthost(nalunitlength);RTAVVideoFrame * frame =[RTAVVideoFramenew];frame . SPs = encoder-& gt;spsframe . PPS = encoder-& gt;ppsframe . data =[ns data dataWithBytes:(data pointer+buffer offset+AVCCHeaderLength)length:NALUnitLength];buffer offset+= NALUnitLength+AVCCHeaderLength;} }

所獲得的H264數據被應用於以下RTMP協議,以為推流做準備。