h.264硬件解码

//  H264HWDecoder.m
//  H264EncoderDecoder
//
//  Created by lujunjie on 2016/11/28.
//  Copyright © 2016年 陆俊杰. All rights reserved.
//

#import "H264HWDecoder.h"

@implementation H264HWDecoder

- (void)dealloc
{
    if(self.decompressionSession != NULL){
        VTDecompressionSessionInvalidate(self.decompressionSession);
        CFRelease(self.decompressionSession);
        self.decompressionSession=NULL;
    }
}
- (int)DecodeH264Frames:(unsigned char *)frame withLength:(int)frameSize
{
    OSStatus status = -1;
    
    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);
    
    if (nalu_type != 7 && _formatDesc == NULL)
    {
        NSLog(@"Video error: Frame is not an I Frame and format description is null");
        return -1;
    }
   
    
    if (nalu_type == 7)
    {
//        NSLog(@"=================================================");
//        for (int i = 0; i<frameSize; i++) {
//            printf(" %x",frame[i]);
//        }
        for (int i = startCodeIndex + 4; i < startCodeIndex + 256; 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);
        
    }
    
    if(nalu_type == 8)
    {
        
        for (int i = _spsSize + 4; i < _spsSize + 128; 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);
        
        if(status != noErr){
            NSLog(@"MVideoFormatDescriptionCreateFromH264ParameterSets ERROR type: %d", (int)status);
        }
        
        
        
        nalu_type = (frame[thirdStartCodeIndex + 4] & 0x1F);
    }
    
    if(nalu_type == 5 )
    {
        
        int offset = _spsSize + _ppsSize;
        blockLength = frameSize - offset;
        data = malloc(blockLength);
        data = memcpy(data, &frame[offset], blockLength);
        
        uint32_t dataLength32 = htonl (blockLength - 4);
        memcpy (data, &dataLength32, sizeof (uint32_t));
        
        
        status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                    blockLength,
                                                    kCFAllocatorNull, NULL,
                                                    0,
                                                    blockLength,
                                                    0, &blockBuffer);
        if(status != noErr){
            NSLog(@"I Frame: CMBlockBufferCreateWithMemoryBlock Error type: %d", (int)status);
        }
        
    }
    
    
    if (nalu_type == 1)
    {
        
        blockLength = frameSize;
        data = malloc(blockLength);
        data = memcpy(data, &frame[0], blockLength);
        
        uint32_t dataLength32 = htonl (blockLength - 4);
        memcpy (data, &dataLength32, sizeof (uint32_t));
        
        status = CMBlockBufferCreateWithMemoryBlock(NULL, data,
                                                    blockLength,
                                                    kCFAllocatorNull, NULL,
                                                    0,
                                                    blockLength,
                                                    0, &blockBuffer);
        if(status != noErr){
            NSLog(@"P Frame: CMBlockBufferCreateWithMemoryBlock Error type: %d", (int)status);
        }
        
    }
    
    if(status == noErr)
    {
        const size_t sampleSize = blockLength;
        status = CMSampleBufferCreate(kCFAllocatorDefault,
                                      blockBuffer, true, NULL, NULL,
                                      _formatDesc, 1, 0, NULL, 1,
                                      &sampleSize, &sampleBuffer);
        if(status != noErr){
            NSLog(@"CMSampleBufferCreate Error type: %d", (int)status);
        }
        
    }
    
    if(status == noErr)
    {
        
        CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
        CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
        CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
        
        if([self.updateDelegate respondsToSelector:@selector(updateDecodedSampleBuffer:)]){
            [self.updateDelegate updateDecodedSampleBuffer:sampleBuffer];
            
            
        }
        
    }
    
    if (data != NULL)
    {
        free (data);
        data = NULL;
    }
    if(sps != NULL)
    {
        free(sps);
        sps = NULL;
    }
    if(pps != NULL)
    {
        free(pps);
        pps = NULL;
    }
    
    
    return 0;
}
@end
原文地址:https://www.cnblogs.com/-ljj/p/6373838.html