2010-11-17 43 views
9

Tôi đang viết một chương trình iPhone (IOS 4) để quay video trực tiếp từ máy ảnh và xử lý video đó trong thời gian thực.Cách lấy video định dạng YUV từ máy ảnh, hiển thị và xử lý video

Tôi thích chụp ở định dạng kCVPixelFormatType_420YpCbCr8BiPlanarFullRange để xử lý dễ dàng hơn (tôi cần xử lý kênh Y). làm cách nào để hiển thị dữ liệu ở định dạng này? Tôi cho rằng tôi cần phải chuyển đổi nó thành UIImage và sau đó đặt nó vào một số ImageView?

Hiện tại tôi có mã hiển thị dữ liệu kCVPixelFormatType_32BGRA, nhưng tự nhiên nó không hoạt động với kCVPixelFormatType_420YpCbCr8BiPlanarFullRange.

Đây là mã tôi sử dụng ngay bây giờ để chuyển đổi, mọi trợ giúp/mẫu về cách thực hiện tương tự cho kCVPixelFormatType_420YpCbCr8BiPlanarFullRange sẽ được đánh giá cao. (Cũng chỉ trích phương pháp hiện tại của tôi).

// Create a UIImage from sample buffer data 
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
               bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 

    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return (image); 
} 
+0

xuất sắc dụ! Tôi đã tìm kiếm mã này thông qua tất cả apple.com –

Trả lời

6

Trả lời câu hỏi của riêng tôi. này đã giải quyết được vấn đề tôi đã có (mà là để lấy sản lượng YUV, hiển thị nó và xử lý nó), mặc dù nó không hẳn là câu trả lời cho câu hỏi:

Để lấy ra YUV từ camera:

AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init]; 
[videoOut setAlwaysDiscardsLateVideoFrames:YES]; 
[videoOut setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 

Để hiển thị nó như là, sử dụng AVCaptureVideoPreviewLayer, nó không yêu cầu bất kỳ mã nào. (Bạn có thể thấy mẫu FindMyiCon trong gói mẫu WWDC chẳng hạn).

Để xử lý các YUV y kênh (bi-planer trong trường hợp này vì vậy tất cả trong một đoạn duy nhất, bạn cũng có thể sử dụng memcpy thay vì vòng lặp):

- (void)processPixelBuffer: (CVImageBufferRef)pixelBuffer { 

    CVPixelBufferLockBaseAddress(pixelBuffer, 0); 

    int bufferHeight = CVPixelBufferGetHeight(pixelBuffer); 
    int bufferWidth = CVPixelBufferGetWidth(pixelBuffer); 

    // allocate space for ychannel, reallocating as needed. 
    if (bufferWidth != y_channel.width || bufferHeight != y_channel.height) 
    { 
     if (y_channel.data) free(y_channel.data); 
     y_channel.width = bufferWidth; 
     y_channel.height = bufferHeight; 
     y_channel.data = malloc(y_channel.width * y_channel.height);   
    } 

    uint8_t *yc = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); 
    int total = bufferWidth * bufferHeight; 
    for(int k=0;k<total;k++) 
    { 
     y_channel.data[k] = yc[k++]; // copy y channel 
    } 

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 
} 
Các vấn đề liên quan