大家好,今天给各位分享编解码服务器的一些知识,其中也会对视频的编解码进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!
一、视频的编解码***编码篇
四、视频的编解码-编码篇
时间 2016-08-05 10:22:59 Twenty's时间念
原文
主题 iOS开发 MacOS
在此之前我们通常使用的FFmpeg多媒体库,利用CPU来进行视频的编解码,占用CPU资源,效率低下,俗称软编解码.而苹果在2014年的iOS8中,开放了VideoToolbox.framwork框架,此框架使用GPU或专用的处理器来进行编解码,俗称硬编解码.而此框架在此之前只有MAC OS系统中可以使用,在iOS作为私有框架.终于苹果在iOS8.0中得到开放引入.
2014年的WWDC Direct Aess to Video Encoding and Decoding中,苹果介绍了使用videoToolbox硬编解码.
使用硬编解码有几个优点:*提高*能;*增加效率;*延长电量的使用
对于编解码,*Foundation框架只有以下几个功能: 1.解压后显示;
2.压缩到一个文件当中;
而对于Video Toolbox,我们可以通过以下功能获取到数据,进行网络流传输等多种保存: 1.解压为图像的数据结构;
2.压缩为视频图像的容器数据结构.
一、videoToolbox的基本数据
Video Toolbox视频编解码前后需要应用的数据结构进行说明。
CVPixelBuffer:编码前和解码后的图像数据结构。此内容包含一系列的CVPixelBufferPool内容
CMTime、CMClock和CMTimebase:时间戳相关。时间以64-bit/32-bit的形式出现。
pixelBufferAttributes:字典设置.可能包括Width/height、pixel format type、• Compatibility(e.g., OpenGL ES, Core Animation)
CMBlockBuffer:编码后,结果图像的数据结构。
CMVideoFormatDescription:图像存储方式,编*等格式描述。
(CMSampleBuffer:存放编解码前后的视频图像的容器数据结构。
CMClock
CMTimebase:关于CMClock的一个控制视图,包含CMClock、时间映射(Time ming)、速率控制(Rate control)
由二、采集视频数据可知,我们获取到的数据(CMSampleBufferRef)sampleBuffer为未编码的数据;
图1.1
上图中,编码前后的视频图像都封装在CMSampleBuffer中,编码前以CVPixelBuffer进行存储;编码后以CMBlockBuffer进行存储。除此之外两者都包括CMTime、CMVideoFormatDesc.
二、视频数据流编码并上传到服务器
1.将CVPixelBuffer使用VTCompressionSession进行数据流的硬编码。
(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 pressedDataAllocator, CM_NULLABLE VTCompressionOutputCallback outputCallback, void* CM_NULLABLE outputCallbackRefCon, CM_RETURNS_RETAINED_PARAMETER CM_NULLABLE VTCompressionSessionRef* CM_NONNULL pressionSessionOut) __OSX_*AILABLE_STARTING(__MAC_10_8, __IPHONE_8_0);
VTCompressionSession的初始化参数说明:
allocator:分配器,设置NULL为默认分配
width:宽
height:高
codecType:编码类型,如kCMVideoCodecType_H264
encoderSpecification:编码规范。设置NULL由videoToolbox自己选择
sourceImageBufferAttributes:源像素缓冲区属*.设置NULL不让videToolbox创建,而自己创建
pressedDataAllocator:压缩数据分配器.设置NULL,默认的分配
outputCallback:当VTCompressionSessionEncodeFrame被调用压缩一次后会被异步调用.注:当你设置NULL的时候,你需要调用VTCompressionSessionEncodeFrameWithOutputHandler方法进行压缩帧处理,支持iOS9.0以上
outputCallbackRefCon:回调客户定义的参考值.
pressionSessionOut:压缩会话变量。
(2)配置VTCompressionSession
使用VTSessionSetProperty()调用进行配置pression。* kVTCompressionPropertyKey AllowFrameReordering:允许帧重新排序.默认为true* kVTCompressionPropertyKey *erageBitRate:设置需要的平均编码率* kVTCompressionPropertyKey H264EntropyMode:H264的熵编码模式。有两种模式:一种基于上下文的二进制算数编码CABAC和可变长编码VLC.在slice层之上(picture和sequence)使用定长或变长的二进制编码,slice层及其以下使用VLC或CABAC.详情请参考* kVTCompressionPropertyKey RealTime:视频编码压缩是否是实时压缩。可设置CFBoolean或NULL.默认为NULL* kVTCompressionPropertyKey ProfileLevel:对于编码流指定配置和标准.比如kVTProfileLevel H264 Main AutoLevel
配置过VTCompressionSession后,可以可选的调用VTCompressionSessionPrepareToEncodeFrames进行准备工作编码帧。
(3)开始硬编码流入的数据
使用VTCompressionSessionEncodeFrame方法进行编码.当编码结束后调用outputCallback回调函数。
VT_EXPORT OSStatus VTCompressionSessionEncodeFrame( CM_NONNULL VTCompressionSessionRef session, CM_NONNULL CVImageBufferRef imageBuffer, CMTime presentationTimeS*p, CMTime duration,// may be kCMTimeInvalidCM_NULLABLE CFDictionaryRef frameProperties,void* CM_NULLABLE sourceFrameRefCon, VTEncodeInfoFlags* CM_NULLABLE infoFlagsOut) __OSX_*AILABLE_STARTING(__MAC_10_8, __IPHONE_8_0);
presentationTimeS*p:获取到的这个sample buffer数据的展示时间戳。每一个传给这个session的时间戳都要大于前一个展示时间戳.
duration:对于获取到sample buffer数据,这个帧的展示时间.如果没有时间信息,可设置kCMTimeInvalid.
frameProperties:包含这个帧的属*.帧的改变会影响后边的编码帧.
sourceFrameRefCon:回调函数会引用你设置的这个帧的参考值.
infoFlagsOut:指向一个VTEncodeInfoFlags来接受一个编码操作.如果使用异步运行,kVTEncodeInfo_Asynchronous被设置;同步运行,kVTEncodeInfo_FrameDropped被设置;设置NULL为不想接受这个信息.
(4)执行VTCompressionOutputCallback回调函数
typedefvoid(*VTCompressionOutputCallback)(void* CM_NULLABLE outputCallbackRefCon,void* CM_NULLABLE sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CM_NULLABLE CMSampleBufferRef sampleBuffer);
outputCallbackRefCon:回调函数的参考值
sourceFrameRefCon: VTCompressionSessionEncodeFrame函数中设置的帧的参考值
status:压缩的成功为noErr,如失败有错误码
infoFlags:包含编码操作的信息标识
sampleBuffer:如果压缩成功或者帧不丢失,则包含这个已压缩的数据CMSampleBuffer,否则为NULL
(5)将压缩成功的sampleBuffer数据进行处理为基本流NSData上传到服务器
MPEG-4是一套用于音频、视频信息的压缩编码标准.
由图1.1可知,已压缩$$CMSampleBuffer= CMTime(可选)+ CMBlockBuffer+ CMVideoFormatDesc$$。
5.1先判断压缩的数据是否正确
//不存在则代表压缩不成功或帧丢失if(!sampleBuffer)return;if(status!= noErr)return;//返回sampleBuffer中包括可变字典的不可变数组,如果有错误则为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从字面意思理解即为以上的说明,但是网上看到很多都是做为查询是否是视频关键帧,而查询文档看到有此关键帧key值kCMSampleBufferAttachmentKey_ForceKeyFrame存在,因此对此值如若有了解情况者敬请告知详情.
5.2获取CMVideoFormatDesc数据由三、解码篇可知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参数集合中的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并转换成数据
CMBlockBufferRef blockBuffer= CMSampleBufferGetDataBuffer(sampleBuffer); size_t lengthAtOffset,totalLength;char*dataPointer;//接收到的数据展示OSStatus blockBufferStatus= CMBlockBufferGetDataPointer(blockBuffer,0,&lengthAtOffset,&totalLength,&dataPointer);if(blockBufferStatus!= kCMBlockBufferNoErr) { size_t bufferOffset=0;stationstint*CCHeaderLength=4;while(bufferOffset< totalLength- *CCHeaderLength){// Read the NAL unit lengthuint32_t NALUnitLength=0;/**
* void*memcpy(void*dest, const void*src, size_t n);
* 从源src所指的内存的起始位置开始拷贝n个字节到目标dest所指的内存的起始位置中
*/memcpy(&NALUnitLength, dataPointer+ bufferOffset, *CCHeaderLength);//字节从高位反转到低位NALUnitLength= CFSwapInt32BigToHost(NALUnitLength); RT*VideoFrame* frame= [RT*VideoFramenew]; frame.sps= encoder-> sps; frame.pps= encoder-> pps; frame.data= [NSData dataWithBytes:(dataPointer+bufferOffset+*CCHeaderLength) length:NALUnitLength]; bufferOffset+= NALUnitLength+ *CCHeaderLength; } }
此得到的H264数据应用于后面的RTMP协议做推流准备。
二、解码的结构解码的结构是什么
解码的结构是:解(左右结构)码(左右结构)。
解码的结构是:解(左右结构)码(左右结构)。注音是:ㄐ一ㄝˇㄇㄚˇ。词*是:动词。拼音是:jiěmǎ。
解码的具体解释是什么呢,我们通过以下几个方面为您介绍:
一、词语解释【点此查看计划详细内容】
解码jiěmǎ。(1)把数码还原成它所代表的内容;把信号转换成它所代表的信息。
二、国语词典
将电波讯号转换成它所代表的讯息。例如在无线电及通讯方面,经常需要将欲传输的内容加以编码保密,及附载到可发射波上送达远方,接收端便需要一组解码电路,以便解读所收到的讯息。在电子计算机方面,讯号要借由网路或其他介面传送、储存,也需要做适当的编码,待到取用时再解码还原。
三、网络解释
解码解码是一种用特定方法,把数码还原成它所代表的内容或将电脉冲信号、光信号、无线电波等转换成它所代表的信息、数据等的过程。解码是受传者将接受到的符号或代码还原为信息的过程,与编码过程相对应。
关于解码的单词
swipemodecdecode
关于解码的成语
排忧解难解衣卸甲难解难分冰解冻释放心解体半解一知桑落瓦解解甲归田解人颐解甲休兵
关于解码的词语
半解一知冰解冻释解甲归田庖丁解牛解甲休兵明码实价桑落瓦解排忧解难百思不解解人颐
关于解码的造句
1、这是因为编码和解码发生在独立的渲染器中。
2、在对标准研究的基础上,提出了一种便于接收端解码的对象轮播方案。
3、很抱歉,我们的数据库里找不到您提供的多媒体数字信号编解码。不过,我们会努力按您的要求去收索,并可能在以后的时间里加到数据库中。
4、最近发展起来的解码技术即高通量测序极大的缩短了破译基因组的工作时间,也降低了成本。
5、服务器收到后解码函数名和值,再决定如何处理,最后返回一个编码的响应值。
点此查看更多关于解码的详细信息
三、谁能给我解释一下视频解码芯片的功能是什么
1.芯片解码就是有专门的硬件负责视频编码的解码,这就是基本功能了,没什么可说,看字面意思你都能明白。编码方式有很多,当然,专门的解码芯片里集成的集中解码方式可能主要应对几种相对应的解码机制。
2.软件商的解码和芯片的硬件解码其实从最终的实现方式上都是靠处理器运算来解决。只是解码用的处理器不同而已。
软件解码,一般就是靠软件来指挥电脑中的cpu来运算相对应的指令来解码。当然,电脑中的cpu应该算是万用处理器,就是什么都能干,但是什么都不精的那种。因为当初设计的时候用CISC的构架模式,都是复杂指令集的流水线方式。这就造成了误算的概率比较高,所以有些效率低下,如果用cpu来解码视频,有时候会让cpu的负荷很高。不过现代的cpu里面一般已经继承了新的指令集来对应视频等的运算,会一定程度上提高效率。
而解码芯片则是接收视频编码,靠硬件来解码。他的特点是一般都是有固定的结构,用于处理对应的几种视频编码格式。他和cpu的差别在于,他很专,只能做视频解码,而基本做不了别的。
其实用白话说,cpu好比是一把刀,解码芯片是一个带格子的割刀。软件解码,就是软件指挥cpu这把刀去一刀一刀的割出格子。而芯片解码就是用割刀一刀下去割出一堆格子。二者都可以,只是效率的问题。
这样说你能明白了吧?