1

我正在尝试通过使用 GameKit 创建的对等连接流式传输视频数据。我有一个接收 NSData 对象并使用它将视频流绘制到 CALayer 上的方法:

- (void)recieveVideoFromData:(NSData *)data;

这是该方法的前几行,它将 NSData 转换为 CMSampleBufferRefs 并开始处理:

CMSampleBufferRef imgData = (CMSampleBufferRef)data.bytes;
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(imgData); 
CVPixelBufferLockBaseAddress(imageBuffer,0); 

现在,当我将本地摄像头的视频流按如下方式输入此方法时,一切正常,视频流显示在屏幕上:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 
    NSData *data = [[NSData alloc] initWithBytes:sampleBuffer length:malloc_size(sampleBuffer)];
    [self recieveVideoFromData:data]; 
}

但是,当我通过对等连接发送这些 NSData 数据包流并以下列方式接收它们时,我收到 EXC_BAD_ACCESS 错误:

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
    [self recieveVideoFromData:data];
}

使用调试器,我了解到错误访问发生在这一行:

CVPixelBufferLockBaseAddress(imageBuffer,0); 

我不知道为什么通过网络发送的 NSData 应该与从同一设备上的另一种方法发送的 NSData 不同。我检查了通过网络接收的数据是否以相同的时间间隔接收,并且与本地设备上生成的数据的长度相同(336 字节)。在使用之前,我还检查了数据对象的保留计数是否为 1。似乎imageBuffer变量不知何故丢失了。

几个问题:

  1. data.bytes转换为CMSampleBufferRef是解压 NSData 的正确方法吗?

  2. 如何断言正在接收的数据实际上是一个 CMSampleBuffer 对象?我想保护我的代码,但我不确定如何为 Core Foundation 类完成类验证。

提前致谢!

4

2 回答 2

1

你为什么要CMSampleBuffer通过转换字节来“解包”(这不是解包)你的NSData?这永远不会起作用,因为CMSampleBuffer它不是内存中的连续块。

您必须在发送之前从自己那里检索所有相关数据,CMSampleBuffer将其填充到NSData对象中,然后通过

OSStatus CMSampleBufferCreate (
    CFAllocatorRef allocator,
    CMBlockBufferRef dataBuffer,
    Boolean dataReady,
    CMSampleBufferMakeDataReadyCallback makeDataReadyCallback,
    void *makeDataReadyRefcon,
    CMFormatDescriptionRef formatDescription,
    CMItemCount numSamples,
    CMItemCount numSampleTimingEntries,
    const CMSampleTimingInfo *sampleTimingArray,
    CMItemCount numSampleSizeEntries,
    const size_t *sampleSizeArray,
    CMSampleBufferRef *sBufOut
);

CMSampleBuffer此函数中的数据类型可能会提示您在打包数据时要从中提取什么。

于 2011-02-20T10:27:06.943 回答
0

这可能不是完整的答案,但你malloc_size对我的使用似乎是一个巨大的危险信号。这似乎是一个不可移植的扩展,不受 ANSI、ISO 或 POSIX 之类的约束,我对如果传递一个不是来自malloc. 这似乎是一个粗略的依赖。(我想说,如果要调用malloc_sizeC 编码器,您已经在做错事了,因为 C 就是要预先知道缓冲区有多大,而不是依赖不可移植的 libc 函数来进行缓冲区大小跟踪为你工作。)

于 2010-12-05T07:12:45.950 回答