真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ios視頻開發(fā)解碼,ios開發(fā)音視頻編解碼

ios 系統(tǒng)中,h.264 視頻流可以硬件解碼嗎

可以的,硬解主要是看硬件(cpu)和系統(tǒng)兩個方面:

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、元江縣網(wǎng)絡(luò)推廣、微信小程序開發(fā)、元江縣網(wǎng)絡(luò)營銷、元江縣企業(yè)策劃、元江縣品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供元江縣建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com

1.iphone4以后的應(yīng)該可以硬解h.264了。如果是手機(jī)里面的視頻,你要下載專門的視頻播放器,播放器里面有硬解播放選項(xiàng)。

2.其實(shí)至少從iPhone4開始,蘋果就是支持硬件解碼了,但是硬解碼API一直是私有API,不開放給開發(fā)者使用,只有越獄才能使用,正常的App如果想提交到AppStore是不允許使用私有API的。從iOS8開始,可能是蘋果想通了,開放了硬解碼和硬編碼API,就是名為 VideoToolbox.framework的API,需要用iOS 8以后才能使用,iOS 7.x上還不行。

iOS 關(guān)于H265/HEVC解碼的

Apple 對 HEVC 標(biāo)準(zhǔn)的態(tài)度就像過山車。Apple 曾非常活躍地參與 HEVC 的開發(fā)。這一標(biāo)準(zhǔn)最終在 2013 年 1 月完成,Apple 也在 2014 年 11 月宣布支持 HEVC 標(biāo)準(zhǔn)。但是幾個月后 Apple 又基于一項(xiàng) Apple 不能接受的版稅條款撤回了這一決定。

時(shí)間快進(jìn)到 2017 年 6 月 5 日,Apple 在 WWDC 大會上宣布:

將在 iOS11 支持 HEVC,首個支持 HEVC 的應(yīng)用是自帶的相機(jī) app。

Mac OS High Sierra 將支持 HEVC

Apple TV 將支持 Amazon。我們可以假定這意味著對超高清的支持,暗示了將支持 HEVC。

WWDC 2017上,Apple已經(jīng)宣布全面支持HEVC。在iOS11中釋出了HEVC的硬件編解碼接口,具體看圖:

對應(yīng)到移動端,iPhone 7、iPhone 7 Plus 支持8bpp硬編;iPhone 6s、iPhone 6s Plus及以上支持硬解;iPhone 5s及以上支持軟解。

關(guān)于HEVC硬解的實(shí)現(xiàn):已經(jīng)在iOS11 beta3上完成了265的硬解,直接參照264的就可以,主要關(guān)注下HEVC格式的語法轉(zhuǎn)換。另外性能也需要持續(xù)關(guān)注,目前測試硬解水平還比較瓶頸。

實(shí)際操作中,查閱了一些資料,顯示iOS端的硬件解碼、編碼,軟件解碼還是有限制的。我本人在集成一些視頻框架的時(shí)候,由于客戶提供部分視頻的是h265/HEVC的編碼,導(dǎo)致部分視頻在播放時(shí)有聲音沒畫面。但是在iPhone 7 iOS11.2系統(tǒng)上一切播放正常。在iPhone 4s\5s\6sp等設(shè)備上無畫面有聲音,系統(tǒng)是10.3.3(包括10.3.3)以下。安卓播放正常。

蘋果在h265/HEVC視頻編碼解碼上是稍微有些遲疑和落后的。

推薦讀者看看這篇文章: 《基于iOS11的HEVC(H.265)硬編碼/硬解碼功能開發(fā)指南》

視頻的編解碼-編碼篇

四、視頻的編解碼-編碼篇

時(shí)間?2016-08-05 10:22:59 Twenty's 時(shí)間念

原文

主題 iOS開發(fā) MacOS

在此之前我們通常使用的FFmpeg多媒體庫,利用CPU來進(jìn)行視頻的編解碼,占用CPU資源,效率低下,俗稱軟編解碼.而蘋果在2014年的iOS8中,開放了VideoToolbox.framwork框架,此框架使用GPU或?qū)S玫奶幚砥鱽磉M(jìn)行編解碼,俗稱硬編解碼.而此框架在此之前只有MAC OS系統(tǒng)中可以使用,在iOS作為私有框架.終于蘋果在iOS8.0中得到開放引入.

2014年的WWDC Direct Access to Video Encoding and Decoding 中,蘋果介紹了使用videoToolbox硬編解碼.

使用硬編解碼有幾個優(yōu)點(diǎn): * 提高性能; * 增加效率; * 延長電量的使用

對于編解碼,AVFoundation框架只有以下幾個功能: 1. 直接解壓后顯示;

2. 直接壓縮到一個文件當(dāng)中;

而對于Video Toolbox,我們可以通過以下功能獲取到數(shù)據(jù),進(jìn)行網(wǎng)絡(luò)流傳輸?shù)榷喾N保存: 1. 解壓為圖像的數(shù)據(jù)結(jié)構(gòu);

2. 壓縮為視頻圖像的容器數(shù)據(jù)結(jié)構(gòu).

一、videoToolbox的基本數(shù)據(jù)

Video Toolbox視頻編解碼前后需要應(yīng)用的數(shù)據(jù)結(jié)構(gòu)進(jìn)行說明。

CVPixelBuffer:編碼前和解碼后的圖像數(shù)據(jù)結(jié)構(gòu)。此內(nèi)容包含一系列的CVPixelBufferPool內(nèi)容

CMTime、CMClock和CMTimebase:時(shí)間戳相關(guān)。時(shí)間以64-bit/32-bit的形式出現(xiàn)。

pixelBufferAttributes:字典設(shè)置.可能包括Width/height、pixel format type、? Compatibility (e.g., OpenGL ES, Core Animation)

CMBlockBuffer:編碼后,結(jié)果圖像的數(shù)據(jù)結(jié)構(gòu)。

CMVideoFormatDescription:圖像存儲方式,編解碼器等格式描述。

(CMSampleBuffer:存放編解碼前后的視頻圖像的容器數(shù)據(jù)結(jié)構(gòu)。

CMClock

CMTimebase: 關(guān)于CMClock的一個控制視圖,包含CMClock、時(shí)間映射(Time mapping)、速率控制(Rate control)

由二、采集視頻數(shù)據(jù)可知,我們獲取到的數(shù)據(jù)(CMSampleBufferRef)sampleBuffer為未編碼的數(shù)據(jù);

圖1.1

上圖中,編碼前后的視頻圖像都封裝在CMSampleBuffer中,編碼前以CVPixelBuffer進(jìn)行存儲;編碼后以CMBlockBuffer進(jìn)行存儲。除此之外兩者都包括CMTime、CMVideoFormatDesc.

二、視頻數(shù)據(jù)流編碼并上傳到服務(wù)器

1.將CVPixelBuffer使用VTCompressionSession進(jìn)行數(shù)據(jù)流的硬編碼。

(1)初始化VTCompressionSession

VT_EXPORT OSStatus VTCompressionSessionCreate(? ? CM_NULLABLE CFAllocatorRef? ? ? ? ? ? ? ? ? ? ? ? ? allocator,? ? int32_t? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? width,? ? int32_t? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? height,? ? CMVideoCodecType? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? codecType,? ? CM_NULLABLE CFDictionaryRef? ? ? ? ? ? ? ? ? ? ? ? encoderSpecification,? ? CM_NULLABLE CFDictionaryRef? ? ? ? ? ? ? ? ? ? ? ? sourceImageBufferAttributes,? ? CM_NULLABLE CFAllocatorRef? ? ? ? ? ? ? ? ? ? ? ? ? compressedDataAllocator,? ? CM_NULLABLE VTCompressionOutputCallback? ? ? ? ? ? outputCallback,? ? void * CM_NULLABLE? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? outputCallbackRefCon,? ? CM_RETURNS_RETAINED_PARAMETER CM_NULLABLE VTCompressionSessionRef * CM_NONNULL compressionSessionOut)? ? __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_8_0);

VTCompressionSession的初始化參數(shù)說明:

allocator:分配器,設(shè)置NULL為默認(rèn)分配

width: 寬

height: 高

codecType: 編碼類型,如kCMVideoCodecType_H264

encoderSpecification: 編碼規(guī)范。設(shè)置NULL由videoToolbox自己選擇

sourceImageBufferAttributes: 源像素緩沖區(qū)屬性.設(shè)置NULL不讓videToolbox創(chuàng)建,而自己創(chuàng)建

compressedDataAllocator: 壓縮數(shù)據(jù)分配器.設(shè)置NULL,默認(rèn)的分配

outputCallback: 當(dāng)VTCompressionSessionEncodeFrame被調(diào)用壓縮一次后會被異步調(diào)用.注:當(dāng)你設(shè)置NULL的時(shí)候,你需要調(diào)用VTCompressionSessionEncodeFrameWithOutputHandler方法進(jìn)行壓縮幀處理,支持iOS9.0以上

outputCallbackRefCon: 回調(diào)客戶定義的參考值.

compressionSessionOut: 壓縮會話變量。

(2)配置VTCompressionSession

使用VTSessionSetProperty()調(diào)用進(jìn)行配置compression。 * kVTCompressionPropertyKey AllowFrameReordering: 允許幀重新排序.默認(rèn)為true * kVTCompressionPropertyKey AverageBitRate: 設(shè)置需要的平均編碼率 * kVTCompressionPropertyKey H264EntropyMode:H264的 熵編碼 模式。有兩種模式:一種基于上下文的二進(jìn)制算數(shù)編碼CABAC和可變長編碼VLC.在slice層之上(picture和sequence)使用定長或變長的二進(jìn)制編碼,slice層及其以下使用VLC或CABAC. 詳情請參考 * kVTCompressionPropertyKey RealTime: 視頻編碼壓縮是否是實(shí)時(shí)壓縮??稍O(shè)置CFBoolean或NULL.默認(rèn)為NULL * kVTCompressionPropertyKey ProfileLevel: 對于編碼流指定配置和標(biāo)準(zhǔn) .比如kVTProfileLevel H264 Main AutoLevel

配置過VTCompressionSession后,可以可選的調(diào)用VTCompressionSessionPrepareToEncodeFrames進(jìn)行準(zhǔn)備工作編碼幀。

(3)開始硬編碼流入的數(shù)據(jù)

使用VTCompressionSessionEncodeFrame方法進(jìn)行編碼.當(dāng)編碼結(jié)束后調(diào)用outputCallback回調(diào)函數(shù)。

VT_EXPORT OSStatus? VTCompressionSessionEncodeFrame(? ? ? CM_NONNULL VTCompressionSessionRef? session,? ? CM_NONNULL CVImageBufferRef? ? ? ? imageBuffer,? ? CMTime? ? ? ? ? ? ? ? ? ? ? ? ? ? ? presentationTimeStamp,? ? CMTime? ? ? ? ? ? ? ? ? ? ? ? ? ? ? duration,// may be kCMTimeInvalidCM_NULLABLE CFDictionaryRef? ? ? ? frameProperties,void* CM_NULLABLE? ? ? ? ? ? ? ? ? sourceFrameRefCon,? ? VTEncodeInfoFlags * CM_NULLABLE? ? infoFlagsOut )? ? __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_8_0);

presentationTimeStamp: 獲取到的這個sample buffer數(shù)據(jù)的展示時(shí)間戳。每一個傳給這個session的時(shí)間戳都要大于前一個展示時(shí)間戳.

duration: 對于獲取到sample buffer數(shù)據(jù),這個幀的展示時(shí)間.如果沒有時(shí)間信息,可設(shè)置kCMTimeInvalid.

frameProperties: 包含這個幀的屬性.幀的改變會影響后邊的編碼幀.

sourceFrameRefCon: 回調(diào)函數(shù)會引用你設(shè)置的這個幀的參考值.

infoFlagsOut: 指向一個VTEncodeInfoFlags來接受一個編碼操作.如果使用異步運(yùn)行,kVTEncodeInfo_Asynchronous被設(shè)置;同步運(yùn)行,kVTEncodeInfo_FrameDropped被設(shè)置;設(shè)置NULL為不想接受這個信息.

(4)執(zhí)行VTCompressionOutputCallback回調(diào)函數(shù)

typedefvoid(*VTCompressionOutputCallback)(void* CM_NULLABLE outputCallbackRefCon,void* CM_NULLABLE sourceFrameRefCon,? ? ? ? OSStatus status,? ? ? ? VTEncodeInfoFlags infoFlags,? ? ? ? CM_NULLABLE CMSampleBufferRef sampleBuffer );

outputCallbackRefCon: 回調(diào)函數(shù)的參考值

sourceFrameRefCon: VTCompressionSessionEncodeFrame函數(shù)中設(shè)置的幀的參考值

status: 壓縮的成功為noErr,如失敗有錯誤碼

infoFlags: 包含編碼操作的信息標(biāo)識

sampleBuffer: 如果壓縮成功或者幀不丟失,則包含這個已壓縮的數(shù)據(jù)CMSampleBuffer,否則為NULL

(5)將壓縮成功的sampleBuffer數(shù)據(jù)進(jìn)行處理為基本流NSData上傳到服務(wù)器

MPEG-4是一套用于音頻、視頻信息的壓縮編碼標(biāo)準(zhǔn).

由 圖1.1 可知,已壓縮 $$CMSampleBuffer = CMTime(可選) + CMBlockBuffer + CMVideoFormatDesc$$。

5.1 先判斷壓縮的數(shù)據(jù)是否正確

//不存在則代表壓縮不成功或幀丟失if(!sampleBuffer)return;if(status != noErr)return;//返回sampleBuffer中包括可變字典的不可變數(shù)組,如果有錯誤則為NULLCFArrayRefarray=? CMSampleBufferGetSampleAttachmentsArray(sampleBuffer,true);if(!array)return;? CFDictionaryRef dic = CFArrayGetValueAtIndex(array,0);if(!dic)return;//issue 3:kCMSampleAttachmentKey_NotSync:沒有這個鍵意味著同步, yes: 異步. no:同步BOOL keyframe = !CFDictionaryContainsKey(dic, kCMSampleAttachmentKey_NotSync);//此代表為同步

而對于 issue 3 從字面意思理解即為以上的說明,但是網(wǎng)上看到很多都是做為查詢是否是視頻關(guān)鍵幀,而查詢文檔看到有此關(guān)鍵幀key值kCMSampleBufferAttachmentKey_ForceKeyFrame存在,因此對此值如若有了解情況者敬請告知詳情.

5.2 獲取CMVideoFormatDesc數(shù)據(jù)由 三、解碼篇 可知CMVideoFormatDesc 包括編碼所用的profile,level,圖像的寬和高,deblock濾波器等.具體包含 第一個NALU的SPS (Sequence Parameter Set)和 第二個NALU的PPS (Picture Parameter Set).

//if (keyframe !encoder - sps) {? ? //獲取sample buffer 中的 CMVideoFormatDesc? ? CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);? ? //獲取H264參數(shù)集合中的SPS和PPS? ? const uint8_t * sparameterSet;size_t sparameterSetSize,sparameterSetCount ;? OSStatus statusCode =? ? CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, sparameterSet, sparameterSetSize, sparameterSetCount,0);if (statusCode == noErr) {? ? ? ? size_t pparameterSetSize, pparameterSetCount;? ? ? ? const uint8_t *pparameterSet;OSStatus statusCode =? ? CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, pparameterSet, pparameterSetSize, pparameterSetCount,0);if (statusCode == noErr) {? ? ? ? ? ? encoder-sps = [NSData dataWithBytes:sparameterSetlength:sparameterSetSize];encoder-pps = [NSData dataWithBytes:pparameterSetlength:pparameterSetSize];}? ? }}

5.3 獲取CMBlockBuffer并轉(zhuǎn)換成數(shù)據(jù)

CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);? ? size_t? lengthAtOffset,totalLength;char*dataPointer;//接收到的數(shù)據(jù)展示OSStatus blockBufferStatus = CMBlockBufferGetDataPointer(blockBuffer,0, lengthAtOffset, totalLength, dataPointer);if(blockBufferStatus != kCMBlockBufferNoErr)? ? {? ? ? ? size_t bufferOffset =0;staticconstintAVCCHeaderLength =4;while(bufferOffset totalLength -? AVCCHeaderLength) {// Read the NAL unit lengthuint32_t NALUnitLength =0;/**

*? void *memcpy(void *dest, const void *src, size_t n);

*? 從源src所指的內(nèi)存地址的起始位置開始拷貝n個字節(jié)到目標(biāo)dest所指的內(nèi)存地址的起始位置中

*/memcpy(NALUnitLength, dataPointer + bufferOffset, AVCCHeaderLength);//字節(jié)從高位反轉(zhuǎn)到低位NALUnitLength = CFSwapInt32BigToHost(NALUnitLength);? ? ? ? ? ? RTAVVideoFrame * frame = [RTAVVideoFramenew];? ? ? ? ? ? frame.sps = encoder - sps;? ? ? ? ? ? frame.pps = encoder - pps;? ? ? ? ? ? frame.data = [NSData dataWithBytes:(dataPointer+bufferOffset+AVCCHeaderLength) length:NALUnitLength];? ? ? ? ? ? bufferOffset += NALUnitLength + AVCCHeaderLength;? ? ? ? }? ? }

此得到的H264數(shù)據(jù)應(yīng)用于后面的RTMP協(xié)議做推流準(zhǔn)備。

iOS硬編解碼相關(guān)知識

實(shí)現(xiàn)直接、簡單,參數(shù)調(diào)整方便,升級易,但CPU負(fù)載重,性能較硬編碼低,低碼率下質(zhì)量通常比硬編碼要好一點(diǎn)。

性能高,低碼率下通常質(zhì)量低于軟編碼器,但部分產(chǎn)品在GPU硬件平臺移植了優(yōu)秀的軟編碼算法(如X264)的,質(zhì)量基本等同于軟編碼。

蘋果在iOS 8.0系統(tǒng)之前,沒有開放系統(tǒng)的硬件編碼解碼功能,不過Mac OS系統(tǒng)一直有,被稱為Video ToolBox的框架來處理硬件的編碼和解碼,終于在iOS 8.0(即 WWDC 2014 513 )后,蘋果將該框架引入iOS系統(tǒng)。

H.264是新一代的編碼標(biāo)準(zhǔn),以高壓縮高質(zhì)量和支持多種網(wǎng)絡(luò)的流媒體傳輸著稱,在編碼方面,我理解的理論依據(jù)是:參照一段時(shí)間內(nèi)圖像的統(tǒng)計(jì)結(jié)果表明,在相鄰幾幅圖像畫面中,一般有差別的像素只有10%以內(nèi)的點(diǎn),亮度差值變化不超過2%,而色度差值的變化只有1%以內(nèi)。所以對于一段變化不大圖像畫面,我們可以先編碼出一個完整的圖像幀A,隨后的B幀就不編碼全部圖像,只寫入與A幀的差別,這樣B幀的大小就只有完整幀的1/10或更?。幀之后的C幀如果變化不大,我們可以繼續(xù)以參考B的方式編碼C幀,這樣循環(huán)下去。這段圖像我們稱為一個序列(序列就是有相同特點(diǎn)的一段數(shù)據(jù)),當(dāng)某個圖像與之前的圖像變化很大,無法參考前面的幀來生成,那我們就結(jié)束上一個序列,開始下一段序列,也就是對這個圖像生成一個完整幀A1,隨后的圖像就參考A1生成,只寫入與A1的差別內(nèi)容。

需要注意的是:

一個序列的第一個圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖像都是 I 幀圖像。H.264 引入 IDR 圖像是為了解碼的重同步,當(dāng)解碼器解碼到 IDR 圖像時(shí),立即將參考幀隊(duì)列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集,開始一個新的序列。這樣,如果前一個序列出現(xiàn)重大錯誤,在這里可以獲得重新同步的機(jī)會。IDR圖像之后的圖像永遠(yuǎn)不會使用IDR之前的圖像的數(shù)據(jù)來解碼。

一個序列就是一段內(nèi)容差異不太大的圖像編碼后生成的一串?dāng)?shù)據(jù)流。當(dāng)運(yùn)動變化比較少時(shí),一個序列可以很長,因?yàn)檫\(yùn)動變化少就代表圖像畫面的內(nèi)容變動很小,所以就可以編一個I幀,然后一直P幀、B幀了。當(dāng)運(yùn)動變化多時(shí),可能一個序列就比較短了,比如就包含一個I幀和3、4個P幀。

I、B、P各幀是根據(jù)壓縮算法的需要,是人為定義的,它們都是實(shí)實(shí)在在的物理幀。一般來說,I幀的壓縮率是7(跟JPG差不多),P幀是20,B幀可以達(dá)到50??梢娛褂肂幀能節(jié)省大量空間,節(jié)省出來的空間可以用來保存多一些I幀,這樣在相同碼率下,可以提供更好的畫質(zhì)。

說明:

I幀:紅色;P幀:藍(lán)色;B幀:綠色。

1、分組:把幾幀圖像分為一組(GOP,也就是一個序列),為防止運(yùn)動變化,幀數(shù)不宜取多。

2、定義幀:將每組內(nèi)各幀圖像定義為三種類型,即I幀、B幀和P幀;

3、預(yù)測幀:以I幀做為基礎(chǔ)幀,以I幀預(yù)測P幀,再由I幀和P幀預(yù)測B幀;

4、數(shù)據(jù)傳輸:最后將I幀數(shù)據(jù)與預(yù)測的差值信息進(jìn)行存儲和傳輸。

5、幀內(nèi)(Intraframe)壓縮也稱為空間壓縮(Spatial compression)。

當(dāng)壓縮一幀圖像時(shí),僅考慮本幀的數(shù)據(jù)而不考慮相鄰幀之間的冗余信息,這實(shí)際上與靜態(tài)圖像壓縮類似。幀內(nèi)一般采用有損壓縮算法,由于幀內(nèi)壓縮是編碼一個完整的圖像,所以可以獨(dú)立的解碼、顯示。幀內(nèi)壓縮一般達(dá)不到很高的壓縮,跟編碼jpeg差不多。

6、幀間(Interframe)壓縮。

相鄰幾幀的數(shù)據(jù)有很大的相關(guān)性,或者說前后兩幀信息變化很小的特點(diǎn)。也即連續(xù)的視頻其相鄰幀之間具有冗余信息,根據(jù)這一特性,壓縮相鄰幀之間的冗余量就可以進(jìn)一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時(shí)間壓縮(Temporal compression),它通過比較時(shí)間軸上不同幀之間的數(shù)據(jù)進(jìn)行壓縮。幀間壓縮一般是無損的。幀差值(Frame differencing)算法是一種典型的時(shí)間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數(shù)據(jù)量。

7、有損(Lossy)壓縮和無損(Lossy less)壓縮。

無損壓縮也即壓縮前和解壓縮后的數(shù)據(jù)完全一致。多數(shù)的無損壓縮都采用RLE行程編碼算法。

有損壓縮意味著解壓縮后的數(shù)據(jù)與壓縮前的數(shù)據(jù)不一致。在壓縮的過程中要丟失一些人眼和人耳所不敏感的圖像或音頻信息,而且丟失的信息不可恢復(fù)。幾乎所有高壓縮的算法都采用有損壓縮,這樣才能達(dá)到低數(shù)據(jù)率的目標(biāo)。丟失的數(shù)據(jù)率與壓縮比有關(guān),壓縮比越小,丟失的數(shù)據(jù)越多,解壓縮后的效果一般越差。此外,某些有損壓縮算法采用多次重復(fù)壓縮的方式,這樣還會引起額外的數(shù)據(jù)丟失。

DTS主要用于視頻的解碼,在解碼階段使用.

PTS主要用于視頻的同步和輸出.

在display的時(shí)候使用.在沒有B frame的情況下.DTS和PTS的輸出順序是一樣的。

下面給出一個GOP為15的例子,其解碼的參照frame及其解碼的順序都在里面:

如上圖:

I frame 的解碼不依賴于任何的其它的幀.而p frame的解碼則依賴于其前面的I frame或者P frame.B frame的解碼則依賴于其前的最近的一個I frame或者P frame 及其后的最近的一個P frame.

在iOS中,與視頻相關(guān)的Framework庫有5個,從頂層開始分別是 AVKit - AVFoundation - VideoToolbox - Core Media - Core Video

其中VideoToolbox可以將視頻解壓到 CVPixelBuffer ,也可以壓縮到 CMSampleBuffer 。

但是我們常用的是 CMSampleBuffer .

編碼前和解碼后的圖像數(shù)據(jù)結(jié)構(gòu)(未壓縮光柵圖像緩存區(qū)-Uncompressed Raster Image Buffer)

存放CVPixelBuffer

CFDictionary對象,可能包含了視頻的寬高,像素格式類型(32RGBA, YCbCr420),是否可以用于OpenGL ES等相關(guān)信息

時(shí)間戳相關(guān)。時(shí)間以 64-big/32-bit形式出現(xiàn)。 分子是64-bit的時(shí)間值,分母是32-bit的時(shí)標(biāo)(time scale)

時(shí)間戳相關(guān)。時(shí)間以 64-big/32-bit形式出現(xiàn)。 分子是64-bit的時(shí)間值,分母是32-bit的時(shí)標(biāo)(time scale)。它封裝了時(shí)間源,其中CMClockGetHostTimeClock()封裝了mach_absolute_time()

時(shí)間戳相關(guān)。時(shí)間以 64-big/32-bit形式出現(xiàn)。CMClock上的控制視圖。提供了時(shí)間的映射:CMTimebaseSetTime(timebase, kCMTimeZero); 速率控制:

CMTimebaseSetRate(timebase, 1.0);

編碼后,結(jié)果圖像的數(shù)據(jù)結(jié)構(gòu)

編解碼前后的視頻圖像均封裝在CMSampleBuffer中,如果是編碼后的圖像,以CMBlockBuffe方式存儲;解碼后的圖像,以CVPixelBuffer存儲。

存放編解碼前后的視頻圖像的容器數(shù)據(jù)結(jié)構(gòu)。如圖所示,編解碼前后的視頻圖像均封裝在CMSampleBuffer中,如果是編碼后的圖像,以CMBlockBuffer方式存儲;解碼后的圖像,以CVPixelBuffer存儲。CMSampleBuffer里面還有另外的時(shí)間信息CMTime和視頻描述信息CMVideoFormatDesc。

實(shí)現(xiàn)步驟如下:

需要從H.264的碼流里面提取出以上的三個信息。最后組合成CMSampleBuffer,提供給硬解碼接口來進(jìn)行解碼工作。

在H.264的語法中,有一個最基礎(chǔ)的層,叫做Network Abstraction Layer, 簡稱為NAL。H.264流數(shù)據(jù)正是由一系列的NAL單元(NAL Unit, 簡稱NAUL)組成的。

H264的碼流由NALU單元組成,一個NALU可能包含有:

2)H.264屬性合集-FormatDesc(包含 SPS和PPS),即流數(shù)據(jù)中,屬性集合可能是這樣的:

經(jīng)過處理之后,在Format Description中則是:

需要注意的是:

要從基礎(chǔ)的流數(shù)據(jù)將SPS和PPS轉(zhuǎn)化為Format Desc中的話,需要調(diào)用 CMVideoFormatDescriptionCreateFromH264ParameterSets() 方法。

3)NALU header

對于流數(shù)據(jù)來說,一個NAUL的Header中,可能是0x00 00 01或者是0x00 00 00 01作為開頭(兩者都有可能,下面以0x00 00 01作為例子)。0x00 00 01因此被稱為開始碼(Start code).

總結(jié)以上知識,我們知道H264的碼流由NALU單元組成,NALU單元包含視頻圖像數(shù)據(jù)和H264的參數(shù)信息。其中視頻圖像數(shù)據(jù)就是CMBlockBuffer,而H264的參數(shù)信息則可以組合成FormatDesc。具體來說參數(shù)信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set).如下圖顯示了一個H.264碼流結(jié)構(gòu):

(實(shí)際測試時(shí),加入time信息后,有不穩(wěn)定的圖像,不加入time信息反而沒有,需要進(jìn)一步研究,這里建議不加入time信息)

根據(jù)上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可選的時(shí)間信息,使用CMSampleBufferCreate接口得到CMSampleBuffer數(shù)據(jù)這個待解碼的原始的數(shù)據(jù)。如下圖所示的H264數(shù)據(jù)轉(zhuǎn)換示意圖。

顯示的方式有兩種:

1)、將CMSampleBuffers提供給系統(tǒng)的AVSampleBufferDisplayLayer 直接顯示

使用方式和其它CALayer類似。該層內(nèi)置了硬件解碼功能,將原始的CMSampleBuffer解碼后的圖像直接顯示在屏幕上面,非常的簡單方便。

2)、利用OPenGL渲染

通過VTDecompression接口來,將CMSampleBuffer解碼成圖像,將圖像通過UIImageView或者OpenGL上顯示。

初始化VTDecompressionSession,設(shè)置解碼器的相關(guān)信息。初始化信息需要CMSampleBuffer里面的FormatDescription,以及設(shè)置解碼后圖像的存儲方式。demo里面設(shè)置的CGBitmap模式,使用RGB方式存放。編碼后的圖像經(jīng)過解碼后,會調(diào)用一個回調(diào)函數(shù),將解碼后的圖像交個這個回調(diào)函數(shù)來進(jìn)一步處理。我們就在這個回調(diào)里面,將解碼后的圖像發(fā)給control來顯示,初始化的時(shí)候要將回調(diào)指針作為參數(shù)傳給create接口函數(shù)。最后使用create接口對session來進(jìn)行初始化。

上所述的回調(diào)函數(shù)可以完成CGBitmap圖像轉(zhuǎn)換成UIImage圖像的處理,將圖像通過隊(duì)列發(fā)送到Control來進(jìn)行顯示處理。

調(diào)用VTDecompresSessionDecodeFrame接口進(jìn)行解碼操作。解碼后的圖像會交由以上兩步驟設(shè)置的回調(diào)函數(shù),來進(jìn)一步的處理。

攝像頭采集,iOS系統(tǒng)提供了AVCaptureSession來采集攝像頭的圖像數(shù)據(jù)。設(shè)定好session的采集解析度。再設(shè)定好input和output即可。output設(shè)定的時(shí)候,需要設(shè)置delegate和輸出隊(duì)列。在delegate方法,處理采集好的圖像。

圖像輸出的格式,是未編碼的CMSampleBuffer形式。

1)初始化VTCompressionSession

VTCompressionSession初始化的時(shí)候,一般需要給出width寬,height長,編碼器類型kCMVideoCodecType_H264等。然后通過調(diào)用VTSessionSetProperty接口設(shè)置幀率等屬性,demo里面提供了一些設(shè)置參考,測試的時(shí)候發(fā)現(xiàn)幾乎沒有什么影響,可能需要進(jìn)一步調(diào)試。最后需要設(shè)定一個回調(diào)函數(shù),這個回調(diào)是視頻圖像編碼成功后調(diào)用。全部準(zhǔn)備好后,使用VTCompressionSessionCreate創(chuàng)建session

2)提取攝像頭采集的原始圖像數(shù)據(jù)給VTCompressionSession來硬編碼

攝像頭采集后的圖像是未編碼的CMSampleBuffer形式,利用給定的接口函數(shù)CMSampleBufferGetImageBuffer從中提取出CVPixelBufferRef,使用硬編碼接口VTCompressionSessionEncodeFrame來對該幀進(jìn)行硬編碼,編碼成功后,會自動調(diào)用session初始化時(shí)設(shè)置的回調(diào)函數(shù)。

3)利用回調(diào)函數(shù),將因編碼成功的CMSampleBuffer轉(zhuǎn)換成H264碼流,通過網(wǎng)絡(luò)傳播。

相關(guān)資料傳送:

iOS8系統(tǒng)H264視頻硬件編解碼說明

簡單談?wù)動簿幋a和軟編碼

I,P,B幀和PTS,DTS的關(guān)系


新聞名稱:ios視頻開發(fā)解碼,ios開發(fā)音視頻編解碼
文章鏈接:http://weahome.cn/article/dsdjses.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部