AVCaptureVideoDataOutputSampleBufferDelegate 注意点

AVCaptureVideoDataOutputSampleBufferDelegate 中需要注意对sampleBuffer的使用。如果想将sampleBuffer保留住以便后面使用的话,这里会出现一些问题。如果sampleBuffer时间太长,那么着的delegate就可能会被停止调用的哦。一般你会发现怎么就只有13帧啊。这个在文档中有明确的说明。但是普通的copy根本不起作用。createCopy只是拷贝了一点基本的属性,但是对于数据只是做了retain操作。所以唯一的办法就是将data进行copy了,然后使用create进行。可以参考一下这个代码。但是这里又会有一个问题,那就是内存超级的大,所以这个对于video来说要谨慎使用了。


- (CMSampleBufferRef)CMSampleBufferCreateCopyWithDeep:(CMSampleBufferRef)sampleBuffer{
    
    CFRetain(sampleBuffer);
    
    CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
    //CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
    
    CMItemCount timingCount;
    CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, 0, nil, &timingCount);
    CMSampleTimingInfo* pInfo = malloc(sizeof(CMSampleTimingInfo) * timingCount);
    CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, timingCount, pInfo, &timingCount);
    
    CMItemCount sampleCount = CMSampleBufferGetNumSamples(sampleBuffer);
    
    CMItemCount sizeArrayEntries;
    CMSampleBufferGetSampleSizeArray(sampleBuffer, 0, nil, &sizeArrayEntries);
    size_t *sizeArrayOut = malloc(sizeof(size_t) * sizeArrayEntries);
    CMSampleBufferGetSampleSizeArray(sampleBuffer, sizeArrayEntries, sizeArrayOut, &sizeArrayEntries);
    
    //CFArrayRef attachArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer,NO);
    
    //buffer-level attachments
    
    //Exif
 
    CMSampleBufferRef sout = nil;
    

    if(dataBuffer){
         
        CMSampleBufferCreate(kCFAllocatorDefault, dataBuffer, YES, nil,nil, formatDescription, sampleCount, timingCount, pInfo, sizeArrayEntries, sizeArrayOut, &sout);
    }else{
        
        CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);        
        CVImageBufferRef cvimgRef = CMSampleBufferGetImageBuffer(sampleBuffer);
        CVPixelBufferLockBaseAddress(cvimgRef,0);
        
        uint8_t *buf=(uint8_t *)CVPixelBufferGetBaseAddress(cvimgRef);
        size_t size = CVPixelBufferGetDataSize(cvimgRef);
        void * data = nil;
        if(buf){
            data = malloc(size);
            memcpy(data, buf, size);
        }
        
        size_t width = CVPixelBufferGetWidth(cvimgRef);
        size_t height = CVPixelBufferGetHeight(cvimgRef);
        OSType pixFmt = CVPixelBufferGetPixelFormatType(cvimgRef);
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(cvimgRef);
        
        
        CVPixelBufferRef pixelBufRef = NULL;
        CMSampleTimingInfo timimgInfo = kCMTimingInfoInvalid;
        CMSampleBufferGetSampleTimingInfo(sampleBuffer, 0, &timimgInfo);
        
        OSStatus result = 0;
        CVPixelBufferCreateWithBytes(kCFAllocatorDefault, width, height, pixFmt, data, bytesPerRow, NULL, NULL, NULL, &pixelBufRef);
        
        CMVideoFormatDescriptionRef videoInfo = NULL;
        
        result = CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBufRef, &videoInfo);
        
        CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBufRef, true, NULL, NULL, videoInfo, &timimgInfo, &sout);
        
        CMItemCount sizeArrayEntries;
        CMSampleBufferGetSampleSizeArray(sout, 0, nil, &sizeArrayEntries);
        size_t *sizeArrayOut = malloc(sizeof(size_t) * sizeArrayEntries);
        CMSampleBufferGetSampleSizeArray(sout, sizeArrayEntries, sizeArrayOut, &sizeArrayEntries);
        
        free(sizeArrayOut);
        
        if(!CMSampleBufferIsValid(sout)){
            NSLog(@"");
        }
    }
    
 
    free(pInfo);
    free(sizeArrayOut);
    CFRelease(sampleBuffer);
    
    return sout;
    

}


阅读更多

没有更多推荐了,返回首页