2010-10-02 17 views
7

Tôi sẽ phát điên với cái này - đã nhìn khắp mọi nơi và thử mọi thứ và mọi thứ tôi có thể nghĩ đến.AVCapture appendSampleBuffer

Làm cho ứng dụng iPhone sử dụng AVFoundation - cụ thể là AVCapture để quay video bằng camera iPhone.

Tôi cần có một hình ảnh tùy chỉnh được phủ lên nguồn cấp dữ liệu video có trong bản ghi.

Cho đến nay tôi có phiên AVCapture được thiết lập, có thể hiển thị nguồn cấp dữ liệu, truy cập vào khung, lưu nó dưới dạng UIImage và marge hình ảnh lớp phủ lên đó. Sau đó chuyển đổi UIImage mới này thành CVPixelBufferRef. để kiểm tra xem bufferRef có đang hoạt động hay không, tôi đã chuyển nó trở lại UIImage và nó vẫn hiển thị ảnh tĩnh.

Sự cố bắt đầu khi tôi cố gắng chuyển đổi CVPixelBufferRef thành CMSampleBufferRef để thêm vào AVCaptureSessions assetWriterInput. CMSampleBufferRef luôn trả về NULL khi tôi cố gắng tạo nó.

Đây là - (void) captureOutput chức năng

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 

UIImage *botImage = [self imageFromSampleBuffer:sampleBuffer]; 
UIImage *wheel = [self imageFromView:wheelView]; 

UIImage *finalImage = [self overlaidImage:botImage :wheel]; 
//[previewImage setImage:finalImage]; <- works -- the image is being merged into one UIImage 

CVPixelBufferRef pixelBuffer = NULL; 
CGImageRef cgImage = CGImageCreateCopy(finalImage.CGImage); 
CFDataRef image = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); 
int status = CVPixelBufferCreateWithBytes(NULL, 
      self.view.bounds.size.width, 
      self.view.bounds.size.height, 
      kCVPixelFormatType_32BGRA, 
      (void*)CFDataGetBytePtr(image), 
      CGImageGetBytesPerRow(cgImage), 
      NULL, 
      0, 
      NULL, 
      &pixelBuffer); 
if(status == 0){ 
    OSStatus result = 0; 

    CMVideoFormatDescriptionRef videoInfo = NULL; 
    result = CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &videoInfo); 
    NSParameterAssert(result == 0 && videoInfo != NULL); 

    CMSampleBufferRef myBuffer = NULL; 
    result = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, 
      pixelBuffer, true, NULL, NULL, videoInfo, NULL, &myBuffer); 
    NSParameterAssert(result == 0 && myBuffer != NULL);//always null :S 

    NSLog(@"Trying to append"); 

    if (!CMSampleBufferDataIsReady(myBuffer)){ 
    NSLog(@"sampleBuffer data is not ready"); 
    return; 
    } 

    if (![assetWriterInput isReadyForMoreMediaData]){ 
    NSLog(@"Not ready for data :("); 
    return; 
    } 

    if (![assetWriterInput appendSampleBuffer:myBuffer]){ 
    NSLog(@"Failed to append pixel buffer"); 
    } 



} 

} 

Một giải pháp tôi tiếp tục nghe về đang sử dụng một AVAssetWriterInputPixelBufferAdaptor mà loại bỏ sự cần thiết phải làm CMSampleBufferRef gói lộn xộn. Tuy nhiên, tôi đã lùng sục các diễn đàn và tài liệu về nhà phát triển và xếp chồng lên nhau và không thể tìm thấy mô tả hoặc ví dụ rõ ràng về cách thiết lập hoặc cách sử dụng nó. Nếu bất cứ ai có một ví dụ làm việc của nó, bạn có thể vui lòng chỉ cho tôi hoặc giúp tôi giải quyết vấn đề trên - đã làm việc về điều này không ngừng trong một tuần và sáng suốt.

Hãy cho tôi biết nếu bạn cần bất kỳ thông tin khác

Cảm ơn trước,

Michael

+0

Xin lỗi vì thiếu định dạng mã - nó xuất hiện tốt trong bản xem trước: S –

Trả lời

6

Bạn cần AVAssetWriterInputPixelBufferAdaptor, đây là mã để tạo ra nó:

// Create dictionary for pixel buffer adaptor 
NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, nil]; 

// Create pixel buffer adaptor 
m_pixelsBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:assetWriterInput sourcePixelBufferAttributes:bufferAttributes]; 

Và mã để sử dụng:

// If ready to have more media data 
if (m_pixelsBufferAdaptor.assetWriterInput.readyForMoreMediaData) { 
    // Create a pixel buffer 
    CVPixelBufferRef pixelsBuffer = NULL; 
    CVPixelBufferPoolCreatePixelBuffer(NULL, m_pixelsBufferAdaptor.pixelBufferPool, &pixelsBuffer); 

    // Lock pixel buffer address 
    CVPixelBufferLockBaseAddress(pixelsBuffer, 0); 

    // Create your function to set your pixels data in the buffer (in your case, fill with your finalImage data) 
    [self yourFunctionToPutDataInPixelBuffer:CVPixelBufferGetBaseAddress(pixelsBuffer)]; 

    // Unlock pixel buffer address 
    CVPixelBufferUnlockBaseAddress(pixelsBuffer, 0); 

    // Append pixel buffer (calculate currentFrameTime with your needing, the most simplest way is to have a frame time starting at 0 and increment each time you write a frame with the time of a frame (inverse of your framerate)) 
    [m_pixelsBufferAdaptor appendPixelBuffer:pixelsBuffer withPresentationTime:currentFrameTime]; 

    // Release pixel buffer 
    CVPixelBufferRelease(pixelsBuffer); 
} 

Và đừng quên phát hành pixel của bạnBufferAdaptor.

+0

Tính năng này có thực sự hoạt động không? Tôi đã thử bằng tay tạo bộ đệm pixel như OP đã làm và thử với một vùng đệm pixel. Khi tôi thử với một vùng đệm pixel như được định nghĩa ở trên, nó hoạt động trong trình mô phỏng nhưng không bao giờ được cấp phát vùng đệm pixel khi chạy trên thiết bị. –

1

Tôi làm điều đó bằng cách sử dụng CMSampleBufferCreateForImageBuffer().

OSStatus ret = 0; 
CMSampleBufferRef sample = NULL; 
CMVideoFormatDescriptionRef videoInfo = NULL; 
CMSampleTimingInfo timingInfo = kCMTimingInfoInvalid; 
timingInfo.presentationTimeStamp = pts; 
timingInfo.duration = duration; 

ret = CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixel, &videoInfo); 
if (ret != 0) { 
    NSLog(@"CMVideoFormatDescriptionCreateForImageBuffer failed! %d", (int)ret); 
    goto done; 
} 
ret = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixel, true, NULL, NULL, 
             videoInfo, &timingInfo, &sample); 
if (ret != 0) { 
    NSLog(@"CMSampleBufferCreateForImageBuffer failed! %d", (int)ret); 
    goto done; 
} 
+0

Bạn có thể chỉ định cách bạn đặt thời gianInfo không? Tôi thấy "pts" và "duration" là những giá trị không đổi? hoặc là những gì .. làm thế nào để bạn thiết lập chúng? – omarojo

+0

Trong trường hợp của tôi nó không hoạt động ... tuy nhiên Lỗi là null .. nhưng khi tôi nhận được CMVideoFormatDescriptionRef .... trở về nil của nó. –