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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值