【问题标题】:How to get Bytes from CMSampleBufferRef , To Send Over Network如何从 CMSampleBufferRef 获取字节,通过网络发送
【发布时间】:2011-09-05 13:46:34
【问题描述】:

我正在使用 AVFoundation 框架捕获视频。借助 Apple 文档http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_MediaCapture.html%23//apple_ref/doc/uid/TP40010188-CH5-SW2

现在我做了以下事情

1.创建videoCaptureDevice
2.创建AVCaptureDeviceInput并设置videoCaptureDevice
3.创建AVCaptureVideoDataOutput并实现Delegate
4.Created AVCaptureSession - 将输入设置为 AVCaptureDeviceInput 并将输出设置为 AVCaptureVideoDataOutput

5.在 AVCaptureVideoDataOutput 委托方法中

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

我得到了 CMSamplebuffer 并转换成 UIImage 并测试使用打印 UIImageview

[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

每件事都进展顺利............

我的问题是, 我需要通过 UDP Socket 发送视频帧。即使我尝试了以下一个是坏主意,UIImage 到 NSData 并通过 UDP Pocket 发送。但是视频处理延迟了。主要是因为 UIImage 到 NSDate 的问题

所以请给我解决我的问题

1) 任何方式将 CMSampleBUffer 或 CVImageBuffer 转换为 NSData ??
2)像Audio Queue Service和Queue for Video一样存储UIImage,做UIImage到NSDate 并发送???

如果我落后于错误的算法,请按写入方向引导我

提前致谢

【问题讨论】:

    标签: ios video-capture avfoundation video-processing core-video


    【解决方案1】:

    使用CMSampleBufferGetImageBuffer 从样本缓冲区中获取CVImageBufferRef,然后使用CVPixelBufferGetBaseAddress 从中获取位图数据。这样可以避免不必要地复制图像。

    【讨论】:

    • 感谢您的回复。我已经使用了 CVPixelBufferGetBaseAddress 但我可以将其用作字节吗?并且单独使用它,我可以在接收端绘制图像吗???
    • 是的,这些是字节。其中有 CVPixelBufferGetHeight()*CVPixelBufferGetBytesPerRow()。如果你做对了,你就可以在另一端重建图像。
    • 这对平面格式是否同样有效?还是需要使用 CVPixelBufferGetHeightOfPlane 和 CVPixelBufferGetBytesPerRowOfPlane 代替?
    • 您应该使用平面版本。无需解码 CVPlanarPixelBufferInfo_YCbCrBiPlanar 结构。
    【解决方案2】:

    这是获取缓冲区的代码。此代码假定为平面图像(例如 BGRA)。

    NSData* imageToBuffer( CMSampleBufferRef source) {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(source);
        CVPixelBufferLockBaseAddress(imageBuffer,0);
    
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
        size_t width = CVPixelBufferGetWidth(imageBuffer);
        size_t height = CVPixelBufferGetHeight(imageBuffer);
        void *src_buff = CVPixelBufferGetBaseAddress(imageBuffer);
    
        NSData *data = [NSData dataWithBytes:src_buff length:bytesPerRow * height];
    
        CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
        return [data autorelease];
    }
    

    更有效的方法是使用 NSMutableData 或缓冲池。

    每秒发送一张 480x360 的图像需要 4.1Mbps 的连接(假设有 3 个颜色通道)。

    【讨论】:

    • 感谢您的回复。 CVimagebuffer 到 NSdata 没问题。我有一个小疑问,在接收器中我无法取回需要高度、宽度和每行字节数的 CVimagebuffer、bcoz
    • 如何转换回图像缓冲区?
    • 此代码给出的数据长度为 3686400 。但图像只有 3000
    • 我的意思是当我 NSLog(@"%i",[data length]);然后它总是记录 3686400。
    • 使用上面的代码获取NSData,你将如何使用CGImageCreate返回CVImageBuffer?我看不到链接。还是有别的办法?
    猜你喜欢
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2010-12-06
    • 2011-04-05
    相关资源
    最近更新 更多