Text/Falling Shadow Loyinglin (Jane book author)
Original link: http://www.jianshu.com/p/37784e363b8a
Copyright belongs to the author, please contact the author to obtain authorization, and Mark "book author".
===========================================
Using Videotoolbox hard-coded preface
It is a popular coding layer video compression format, currently the protocol layer in the project has rtmp and HTTP, but the video coding layer is the use of H.
In the process of being familiar with H. A, try to use videotoolbox hard coding and hard decoding of the original code stream for a better understanding of H.
Introduction 1, H.
The video coding layer (video Coding LAYER,VCL) is composed of the network abstraction layer,nal.
There is a built-in NAL network protocol adaptation layer, with NAL to provide the state of the network, so that VCL has better coding flexibility and error correction ability.
See here for an introduction to H.
The code flow structure of H.
Key objects:
- Sequence parameter set SPS: Acts on a series of sequential coded images;
- Image parameter set pps: One or more independent images acting on the encoded video sequence;
2, Videotoolbox
Videotoolbox is a hard-coded and hard-decoded API that is open after iOS8, a set of functions written in C. The use process is as follows:
- 1.
-initVideoToolBox
call Vtcompressionsessioncreate to create the encoding session, and then call Vtsessionsetproperty to set the parameters, Finally call Vtcompressionsessionpreparetoencodeframes to start coding;
- 2, start video recording, get to the camera video frame, incoming
-encode:
, call Vtcompressionsessionencodeframe incoming need to encode the video frame, if return failed, Call Vtcompressionsessioninvalidate to destroy the session and then release the session;
- 3, each frame video encoding will call the pre-set encoding function
didCompressH264
, if the keyframe needs to get cmformatdescriptionref with cmsamplebuffergetformatdescription, and then use
Cmvideoformatdescriptiongeth264parametersetatindex obtain PPS and SPS;
Finally, the first four bytes of all NALU data in each frame are converted to 0x00 00 00 01 Before the file is written;
- 4. Call Vtcompressionsessioncompleteframes to complete the encoding, then destroy the Session:vtcompressionsessioninvalidate and release the session.
Effect Show
It's a decoded image.
Sticker Code
- Create session
int 480 640 ; void *) (self), &encodingsession);
Set session Properties
//set real-time encoded output (avoid delays)Vtsessionsetproperty (encodingsession, Kvtcompressionpropertykey_realtime, kcfbooleantrue); Vtsessionsetproperty (Encodingsession, Kvtcompressionpropertykey_profilelevel, Kvtprofilelevel_h264_baseline_ Autolevel); //Set Keyframe (gopsize) interval intFrameinterval =Ten; Cfnumberref Frameintervalref= Cfnumbercreate (Kcfallocatordefault, Kcfnumberinttype, &frameinterval); Vtsessionsetproperty (Encodingsession, Kvtcompressionpropertykey_maxkeyframeinterval, FRAMEINTERVALREF); //set the desired frame rate intfps =Ten; Cfnumberref Fpsref= Cfnumbercreate (Kcfallocatordefault, Kcfnumberinttype, &fps); Vtsessionsetproperty (Encodingsession, Kvtcompressionpropertykey_expectedframerate, FPSREF); //set the bitrate, the upper limit, the unit is BPS intBitrate = width * Height *3*4*8; Cfnumberref Bitrateref= Cfnumbercreate (Kcfallocatordefault, Kcfnumbersint32type, &bitrate); Vtsessionsetproperty (Encodingsession, Kvtcompressionpropertykey_averagebitrate, BITRATEREF); //set the bitrate, the mean, in units of byte intBitratelimit = width * Height *3*4; Cfnumberref Bitratelimitref= Cfnumbercreate (Kcfallocatordefault, Kcfnumbersint32type, &bitratelimit); Vtsessionsetproperty (Encodingsession, Kvtcompressionpropertykey_dataratelimits, bitRateLimitRef);
Incoming encoded frames
Cvimagebufferref Imagebuffer =// frame time, if not set, causes the timeline to be too long. vtcompressionsessionencodeframe= (encodingsession, Imagebuffer, Presentationtimestamp, kcmtimeinvalid, &flags);
Key frames for SPS and PPS
BOOLKeyframe =! Cfdictionarycontainskey (Cfarraygetvalueatindex (Cmsamplebuffergetsampleattachmentsarray (SampleBuffer,true),0) ), Kcmsampleattachmentkey_notsync); //determines whether the current frame is a keyframe//get SPS & PPS Data if(keyframe) {cmformatdescriptionref format=cmsamplebuffergetformatdescription (Samplebuffer); size_t sparametersetsize, Sparametersetcount; Constuint8_t *Sparameterset; Osstatus StatusCode= Cmvideoformatdescriptiongeth264parametersetatindex (format,0, &sparameterset, &sparametersetsize, &sparametersetcount,0 ); if(StatusCode = =NOERR) { //Found SPS and now check for PPSsize_t pparametersetsize, Pparametersetcount; Constuint8_t *Pparameterset; Osstatus StatusCode= Cmvideoformatdescriptiongeth264parametersetatindex (format,1, &pparameterset, &pparametersetsize, &pparametersetcount,0 ); if(StatusCode = =NOERR) { //Found ppsNSData *sps =[NSData Datawithbytes:sparameterset length:sparametersetsize]; NSData*pps =[NSData Datawithbytes:pparameterset length:pparametersetsize]; if(encoder) {[encoder gotspspps:sps Pps:pps]; } } } }
Write Data
Cmblockbufferref DataBuffer =Cmsamplebuffergetdatabuffer (samplebuffer); size_t length, totallength;Char*Datapointer; Osstatus Statuscoderet= Cmblockbuffergetdatapointer (DataBuffer,0, &length, &totallength, &datapointer); if(Statuscoderet = =NOERR) {size_t Bufferoffset=0; Static Const intAvccheaderlength =4;//The first four bytes of the returned NALU data are not 0001 Startcode, but the frame lengths of the big-endian mode length//cyclic acquisition of NALU data while(Bufferoffset < Totallength-avccheaderlength) {uint32_t Nalunitlength=0; //Read the NAL unit lengthmemcpy (&nalunitlength, Datapointer +Bufferoffset, avccheaderlength); //turn the system end from the big-endianNalunitlength =Cfswapint32bigtohost (nalunitlength); NSData* data = [[NSData alloc] Initwithbytes: (datapointer + Bufferoffset +avccheaderlength) length:nalunitlength]; [Encoder gotencodeddata:data Iskeyframe:keyframe]; //Move to the next NAL unit in the block bufferBufferoffset + = Avccheaderlength +nalunitlength; } }
SummarizeMost of the Videotoolboxdemo code found on the Internet is similar, and more important is to try to implement it yourself.
Learn hard coding and hard decoding, the purpose is to H264 code stream clearer understanding, in fact, we do not touch the development process of H264 real coding and decoding process, so the difficulty is far from the imagination so big.
Here's the code address.
Using Videotoolbox hard-coded h.264< transfer >