IOS 視頻硬解碼

</pre>硬解碼</h1><h1></h1><h3><span style="font-weight:normal">解碼主要需要以下三個函數</span></h3><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px"><span style="font-weight:normal">VTDecompressionSessionCreate 創建解碼 session</span></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px"><span style="font-weight:normal">VTDecompressionSessionDecodeFrame 解碼一個frame</span></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px"><span style="font-weight:normal">VTDecompressionSessionInvalidate 銷燬解碼 session</span></p><div><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial"><span style="font-size:18px">首先要創建 decode session,方法如下:</span></p><div class="highlight" style="font-family:Arial; font-size:14px"><pre style="white-space:pre-wrap; word-wrap:break-word"><code class="language-c">        <span class="n">OSStatus</span> <span class="n">status</span> <span class="o">=</span> <span class="n">VTDecompressionSessionCreate</span><span class="p">(</span><span class="n">kCFAllocatorDefault</span><span class="p">,</span>
                                              <span class="n">decoderFormatDescription</span><span class="p">,</span>
                                              <span class="nb">NULL</span><span class="p">,</span> <span class="n">attrs</span><span class="p">,</span>
                                              <span class="o">&</span><span class="n">callBackRecord</span><span class="p">,</span>
                                              <span class="o">&</span><span class="n">deocderSession</span><span class="p">);</span></code>

其中 decoderFormatDescription 是 CMVideoFormatDescriptionRef 類型的視頻格式描述,這個需要用H.264的 sps 和 pps數據來創建,調用以下函數創建decoderFormatDescription

CMVideoFormatDescriptionCreateFromH264ParameterSets

需要注意的是,這裏用的 sps和pps數據是不包含“00 00 00 01”的start code的


sps pps的獲取(重點)

如果是通過ffmpeg的av_read_frame函數來獲取的H264數據,sps和pps是存儲在extradata中的

while (av_read_frame(pFormatCtx, &packet)>= 0) {
        if (packet.stream_index == streamNo) {
            NSLog(@"video pkt->pts = %lld,pkt->dts =%d", packet.pts,packet.dts);

            NSLog(@"=========dddd=========");
            [_h264Decoder decodeFrame:packet.data withSize:packet.size withExtraData:pFormatCtx->streams[streamNo]->codec->extradata withExtraDataSize:pFormatCtx->streams[streamNo]->codec->extradata_size];
        }
}

如果是通過tcp或udp協議傳輸的H264數據,需要根據收到的數據包分析提取相應的sps,pps,關鍵幀,非關鍵幀
<pre name="code" class="objc"><span style="font-size:14px;">-(void) decodeFrame:(uint8_t *)frame
           withSize:(uint32_t)frameSize
      withExtraData:(uint8_t *)extraData
  withExtraDataSize:(uint32_t)extraDataSize
{
    
    NSData *h264Data = [NSData dataWithBytes:frame length:frameSize];
   // NSLog(@"h264Data =%@",h264Data);
    
    
    OSStatus status;
    int startCodeSPSIndex = 0;
    int startCodePPSIndex = 0;
    int spsLength = 0;
    int ppsLength = 0;
    NSData *spsData = nil;
    NSData *ppsData = nil;
    int nalu_type = 0;
    
    NSData *extra = [NSData dataWithBytes:extraData length:extraDataSize];
    NSLog(@"extra =%@",extra);
    if (_formatDesc == NULL) {
        for (int i = 0; i < extraDataSize; i++) {
            if (i >= 3) {
                if (extraData[i] == 0x01 && extraData[i-1] == 0x00 && extraData[i-2] == 0x00 && extraData[i-3] == 0x00) {
                    if (startCodeSPSIndex == 0) {
                        startCodeSPSIndex = i;
                    }
                    if (i > startCodeSPSIndex) {
                        startCodePPSIndex = i;
                    }
                }
            }
        }
        
        spsLength = startCodePPSIndex - startCodeSPSIndex - 4;
        ppsLength = extraDataSize - (startCodePPSIndex + 1);
        nalu_type = ((uint8_t) extraData[startCodeSPSIndex + 1] & 0x1F);
        if (nalu_type == 7) {
            spsData = [NSData dataWithBytes:&(extraData[startCodeSPSIndex + 1]) length: spsLength];
        }
        
        nalu_type = ((uint8_t) extraData[startCodePPSIndex + 1] & 0x1F);
        if (nalu_type == 8) {
            ppsData = [NSData dataWithBytes:&(extraData[startCodePPSIndex + 1]) length: ppsLength];
        }
        
        
        const uint8_t* const parameterSetPointers[2] = { (const uint8_t*)[spsData bytes], (const uint8_t*)[ppsData bytes] };
        const size_t parameterSetSizes[2] = { [spsData length], [ppsData length] };
        status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault, 2, parameterSetPointers, parameterSetSizes, 4, &_formatDesc);
    }
    if((status == noErr) && (_decompressionSession == NULL))
    {
        [self createDecompSession];
    }
    
    int startCodeIndex = 0;

    int fouthStartCodeIndex = 0;
    
    long blockLength = 0;
    uint8_t *data = NULL;
    uint8_t *pps = NULL;
    uint8_t *sps = NULL;
    
    CMSampleBufferRef sampleBuffer = NULL;
    CMBlockBufferRef blockBuffer = NULL;
    for (int i = 0; i < startCodeIndex + frameSize; i++)
    {
        if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01 )
        {
            nalu_type = (frame[i + 4] & 0x1F);
            if (nalu_type == 5)
            {
                fouthStartCodeIndex = i;
                blockLength = frameSize - fouthStartCodeIndex;
                data = malloc(blockLength);
                data = memcpy(data, &frame[fouthStartCodeIndex], blockLength);
                NSData *type5 = [NSData dataWithBytes:data length:blockLength];
                
                uint32_t dataLength32 = htonl (blockLength - 4);
                memcpy (data, &dataLength32, sizeof (uint32_t));
                
                
                
                status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                            blockLength,
                                                            kCFAllocatorNull, NULL,
                                                            0,
                                                            blockLength,
                                                            0, &blockBuffer);
                
                NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
                break;
            }
            if (nalu_type == 1)
            {
                
                fouthStartCodeIndex = i;
                blockLength = frameSize - fouthStartCodeIndex;
                data = malloc(blockLength);
                data = memcpy(data, &frame[fouthStartCodeIndex], blockLength);
                NSData *type1 = [NSData dataWithBytes:data length:blockLength];
                
                uint32_t dataLength32 = htonl (blockLength - 4);
                memcpy (data, &dataLength32, sizeof (uint32_t));
                
                
                status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                            blockLength,
                                                            kCFAllocatorNull, NULL,
                                                            0,
                                                            blockLength,
                                                            0, &blockBuffer);
                
                NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
                break;
            }
        }
    }

//
//
//    CFMutableDictionaryRef atoms = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
//    CFMutableDictionarySetData(atoms, CFSTR ("avcC"), (uint8_t *)extraData, extraDataSize);
//    CFMutableDictionaryRef extensions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
//    CFMutableDictionarySetObject(extensions, CFSTR ("SampleDescriptionExtensionAtoms"), (CFTypeRef *) atoms);
//    
//    CMVideoFormatDescriptionCreate(NULL, format_id, width, height, extensions, &videoFormatDescr);
    
    /*
    
    OSStatus status;
    
    uint8_t *data = NULL;
    uint8_t *pps = NULL;
    uint8_t *sps = NULL;
    
    int startCodeIndex = 0;
    int secondStartCodeIndex = 0;
    int thirdStartCodeIndex = 0;
    
    long blockLength = 0;
    
    CMSampleBufferRef sampleBuffer = NULL;
    CMBlockBufferRef blockBuffer = NULL;
    
    int nalu_type = (frame[startCodeIndex + 4] & 0x1F);
    NSLog(@"nalu_type = %d",nalu_type);
    
    if (nalu_type != 7 && _formatDesc == NULL)
    {
        NSLog(@"Video error: Frame is not an I Frame and format description is null");
        return;
    }
    
    if (nalu_type == 7)
    {
        // 去掉起始頭0x00 00 00 01   有的爲0x00 00 01
        for (int i = startCodeIndex + 4; i < startCodeIndex + 440; i++)
        {
            if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01)
            {
                secondStartCodeIndex = i;
                _spsSize = secondStartCodeIndex;
                break;
            }
        }
        
        nalu_type = (frame[secondStartCodeIndex + 4] & 0x1F);
    }
    NSLog(@"nalu_type = %d",nalu_type);
    if(nalu_type == 8)
    {
        for (int i = _spsSize + 4; i < _spsSize + 600; i++)
        {
            if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01)
            {
                thirdStartCodeIndex = i;
                _ppsSize = thirdStartCodeIndex - _spsSize;
                break;
            }
        }
        
        sps = malloc(_spsSize - 4);
        pps = malloc(_ppsSize - 4);
        
        memcpy (sps, &frame[4], _spsSize-4);
        memcpy (pps, &frame[_spsSize+4], _ppsSize-4);
        
        uint8_t*  parameterSetPointers[2] = {sps, pps};
        size_t parameterSetSizes[2] = {_spsSize-4, _ppsSize-4};
        
        status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault, 2,
                                                                     (const uint8_t *const*)parameterSetPointers,
                                                                     parameterSetSizes, 4,
                                                                     &_formatDesc);
        
        
        nalu_type = (frame[thirdStartCodeIndex + 4] & 0x1F);
    }
    NSLog(@"nalu_type = %d",nalu_type);
    if((status == noErr) && (_decompressionSession == NULL))
    {
        [self createDecompSession];
    }
    
    
    
    if(nalu_type == 5)
    {
        
        int offset = _spsSize + _ppsSize;
        blockLength = frameSize - offset;
        data = malloc(blockLength);
        data = memcpy(data, &frame[offset], blockLength);
        NSData *type5 = [NSData dataWithBytes:data length:blockLength];
        
        uint32_t dataLength32 = htonl (blockLength - 4);
        memcpy (data, &dataLength32, sizeof (uint32_t));
        
        
        status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                    blockLength,
                                                    kCFAllocatorNull, NULL,
                                                    0,
                                                    blockLength,
                                                    0, &blockBuffer);
        
        NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
    }
    
    if (nalu_type == 1)
    {
        blockLength = frameSize;
        data = malloc(blockLength);
        data = memcpy(data, &frame[0], blockLength);
        NSData *type1 = [NSData dataWithBytes:data length:blockLength];
        
        uint32_t dataLength32 = htonl (blockLength - 4);
        memcpy (data, &dataLength32, sizeof (uint32_t));
        
        status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                    blockLength,
                                                    kCFAllocatorNull, NULL,
                                                    0,
                                                    blockLength,
                                                    0, &blockBuffer);
    }
    */
    
    ////////////////////////////////////////////
    /*
    int fouthStartCodeIndex = 0;
    for (int i = startCodeIndex + 4; i < startCodeIndex + frameSize; i++)
    {
        if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01 )
        {
            nalu_type = (frame[i + 4] & 0x1F);
            if (nalu_type == 5)
            {
                fouthStartCodeIndex = i;
                blockLength = frameSize - fouthStartCodeIndex;
                data = malloc(blockLength);
                data = memcpy(data, &frame[fouthStartCodeIndex], blockLength);
                NSData *type5 = [NSData dataWithBytes:data length:blockLength];
                
                uint32_t dataLength32 = htonl (blockLength - 4);
                memcpy (data, &dataLength32, sizeof (uint32_t));
                
                
                status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                            blockLength,
                                                            kCFAllocatorNull, NULL,
                                                            0,
                                                            blockLength,
                                                            0, &blockBuffer);
                
                NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
                break;
            }
            if (nalu_type == 1)
            {
                fouthStartCodeIndex = i;
                blockLength = frameSize - fouthStartCodeIndex;
                data = malloc(blockLength);
                data = memcpy(data, &frame[fouthStartCodeIndex], blockLength);
                NSData *type1 = [NSData dataWithBytes:data length:blockLength];
                
                uint32_t dataLength32 = htonl (blockLength - 4);
                memcpy (data, &dataLength32, sizeof (uint32_t));
                
                
                status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                            blockLength,
                                                            kCFAllocatorNull, NULL,
                                                            0,
                                                            blockLength,
                                                            0, &blockBuffer);
                
                NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
                break;
            }
        }
    }
    */
    ////////////////////////////////////////////
    
    
    
    if(status == noErr)
    {
        const size_t * samplesizeArrayPointer;
        size_t sampleSizeArray= blockLength;
        samplesizeArrayPointer = &sampleSizeArray;
        
//        int32_t timeSpan = 1000000;
//        CMTime PTime = CMTimeMake(0, timeSpan);
//        CMSampleTimingInfo timingInfo;
//        timingInfo.presentationTimeStamp = PTime;
//        timingInfo.duration =  kCMTimeZero;
//        timingInfo.decodeTimeStamp = kCMTimeInvalid;
        
        int32_t timeSpan = 90000;
        CMSampleTimingInfo timingInfo;
        frameCount++;
        NSDate *currentTime = [NSDate date];

        timingInfo.presentationTimeStamp = CMTimeMake(frameCount, timeSpan);
        timingInfo.duration =  CMTimeMake(3000, timeSpan);
        timingInfo.decodeTimeStamp = kCMTimeInvalid;
        
        status = CMSampleBufferCreate(kCFAllocatorDefault, blockBuffer, true, NULL, NULL, _formatDesc, 1, 1, &timingInfo, 0, samplesizeArrayPointer, &sampleBuffer);
        
//        const size_t sampleSize = blockLength;
//        status = CMSampleBufferCreate(kCFAllocatorDefault,
//                                      blockBuffer, true, NULL, NULL,
//                                      _formatDesc, 1, 0, NULL, 1,
//                                      &sampleSize, &sampleBuffer);
        
        NSLog(@"\t\t SampleBufferCreate: \t %@", (status == noErr) ? @"successful!" : @"failed...");
    }
    
    if(status == noErr)
    {
        CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
        CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
        CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
        
        [self render:sampleBuffer];
    }
    
    
    if (NULL != blockBuffer) {
        CFRelease(blockBuffer);
        blockBuffer = NULL;
    }
    
    [self relaseData:data];
    [self relaseData:pps];
    [self relaseData:sps];
    
    [self.delegate startDecodeData];
}
</span>



下面通過一段數據來分析
1.sps pps 

Printing description of extra:

<00000001 6742c01e d903c568 40000003 00400000 0c03c58b 92000000 0168cb8c b2>

sps 爲<6742c01e d903c568 40000003 00400000 0c03c58b 92>
pps 爲<68cb8cb2>
2.關鍵幀和非關鍵幀

<00000001 0605ffff 86dc45e9 bde6d948 b7962cd8 20d923ee ef783236 34202d20 636f7265 20313132 20723138 33342061 35313831 3661202d 20482e32 36342f4d 5045472d 34204156 4320636f 64656320 2d20436f 70796c65 66742032 3030332d 32303130 202d2068 7474703a 2f2f7777 772e7669 64656f6c 616e2e6f 72672f78 3236342e 68746d6c 202d206f 7074696f 6e733a20 63616261 633d3020 7265663d 33206465 626c6f63 6b3d313a 303a3020 616e616c 7973653d 3078313a 30783131 31206d65 3d686578 20737562 6d653d37 20707379 3d312070 73795f72 643d312e 30303a30 2e303020 6d697865 645f7265 663d3120 6d655f72 616e6765 3d313620 6368726f 6d615f6d 653d3120 7472656c 6c69733d 31203878 38646374 3d302063 716d3d30 20646561 647a6f6e 653d3231 2c313120 66617374 5f70736b 69703d31 20636872 6f6d615f 71705f6f 66667365 743d2d32 20746872 65616473 3d363420 736c6963 65645f74 68726561 64733d30 206e723d 30206465 63696d61 74653d31 20696e74 65726c61 6365643d 3020636f 6e737472 61696e65 645f696e 7472613d 30206266 72616d65 733d3020 77656967 6874703d 30206b65 79696e74 3d343820 6b657969 6e745f6d 696e3d32 35207363 656e6563 75743d34 3020696e 7472615f 72656672 6573683d 30207263 5f6c6f6f 6b616865 61643d34 30207263 3d616272 206d6274 7265653d 31206269 74726174 653d3835 20726174 65746f6c 3d312e30 2071636f 6d703d30 2e363020 71706d69 6e3d3130 2071706d 61783d35 31207170 73746570 3d342076 62765f6d 61787261 74653d37 36382076 62765f62 75667369 7a653d33 30303020 69705f72 6174696f 3d312e34 31206171 3d313a31 2e303020 6e616c5f 6872643d 6e6f6e65 00800000 00016588 840f7241 38a00023 3f272727 27272727 27272727 2727275d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 d75d75d7 5d75d75d 75d75d75 e0>

這一段是獲取到的H264數據,可以看出是不包含sps和pps數據的,

for (int i =0; i < startCodeIndex + frameSize; i++)

    {

        if (frame[i] ==0x00 && frame[i+1] ==0x00 && frame[i+2] ==0x00 && frame[i+3] ==0x01 )

        {

            nalu_type = (frame[i + 4] &0x1F);

nalu_type(非常重要)

<code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: inherit;"><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">NSString</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">*</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">const</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> naluTypesStrings</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">[]</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">=</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">{</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"0: Unspecified (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"1: Coded slice of a non-IDR picture (VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">    </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">// P frame</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"2: Coded slice data partition A (VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"3: Coded slice data partition B (VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"4: Coded slice data partition C (VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"5: Coded slice of an IDR picture (VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">      </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">// I frame</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"6: Supplemental enhancement information (SEI) (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"7: Sequence parameter set (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">         </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">// SPS parameter</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"8: Picture parameter set (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">          </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">// PPS parameter</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"9: Access unit delimiter (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"10: End of sequence (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"11: End of stream (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"12: Filler data (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"13: Sequence parameter set extension (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"14: Prefix NAL unit (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"15: Subset sequence parameter set (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"16: Reserved (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"17: Reserved (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"18: Reserved (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"19: Coded slice of an auxiliary coded picture without partitioning (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"20: Coded slice extension (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"21: Coded slice extension for depth view components (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"22: Reserved (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"23: Reserved (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"24: STAP-A Single-time aggregation packet (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"25: STAP-B Single-time aggregation packet (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"26: MTAP16 Multi-time aggregation packet (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"27: MTAP24 Multi-time aggregation packet (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"28: FU-A Fragmentation unit (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"29: FU-B Fragmentation unit (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"30: Unspecified (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
    </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">@</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"31: Unspecified (non-VCL)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">,</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">
</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">};</span></code>
我們只需要處理nalu_type爲5,1,7,8的情況,比如

         

 if (nalu_type == 1)
            {
                
                fouthStartCodeIndex = i;
                blockLength = frameSize - fouthStartCodeIndex;
                data = malloc(blockLength);
                data = memcpy(data, &frame[fouthStartCodeIndex], blockLength);
                NSData *type1 = [NSData dataWithBytes:data length:blockLength];
                
                uint32_t dataLength32 = htonl (blockLength - 4);
                memcpy (data, &dataLength32, sizeof (uint32_t));
                
                
                status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                            blockLength,
                                                            kCFAllocatorNull, NULL,
                                                            0,
                                                            blockLength,
                                                            0, &blockBuffer);
                
                NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed...");
                break;
            }

以上是我遇到過問題的地方,具體其他細節,比如H264數據格式,sps,pps作用,NUL單元,參考另外一篇文章http://blog.csdn.net/dongtinghong/article/details/50788490






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章