NSData over GameKit 和 EXC_BAD_ACCESS 奇怪的问题

Posted

技术标签:

【中文标题】NSData over GameKit 和 EXC_BAD_ACCESS 奇怪的问题【英文标题】:NSData over GameKit and EXC_BAD_ACCESS strange problem 【发布时间】:2010-12-05 06:58:30 【问题描述】:

我正在尝试通过使用 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 字节)相同。在使用之前,我还检查了 data 对象的保留计数是否为 1。 imageBuffer 变量似乎丢失了。

几个问题:

    data.bytes 转换为 CMSampleBufferRef 是否是解包 NSData 的正确方法?

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

提前致谢!

【问题讨论】:

【参考方案1】:

为什么要通过转换 NSData 的字节来“解包”(不是解包)CMSampleBuffer?这永远行不通,因为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 中提取什么。

【讨论】:

您能提供任何示例或教程吗?谢谢【参考方案2】:

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

【讨论】:

老实说,我对 C 的了解并不多,我试图拼凑我能做的工作,其中包括复制代码和猜测诸如 malloc_size 之类的东西。是否有可靠的方法来检查 CMSampleBuffer 的大小?

以上是关于NSData over GameKit 和 EXC_BAD_ACCESS 奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 GameKit 崩溃通过蓝牙发送数据

iPhone 到 iPhone 传输的 GameKIt 的替代品

使用 GameKit 通过 NSDictionary 在 iPhone 之间传输 CoreData 数据

OpenGL ES glReadPixels exc_bad_access

EXC_BAD_ACCESS 在多个设备上使用 iCloud

从 GameCenter 发送和接收数据:Swift