NSData over GameKit 和 EXC_BAD_ACCESS 奇怪的问题

发布于 2024-10-06 09:57:49 字数 1555 浏览 0 评论 0原文

我正在尝试通过 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 变量不知何故丢失了。

有几个问题:

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

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

提前致谢!

I'm trying to stream video data over a peer-to-peer connection created with GameKit. I have a method that receives an NSData object and uses it to draw a video stream onto a CALayer:

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

Here are the first few lines of that method which convert the NSData to CMSampleBufferRefs and begins processing:

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

Now, when I feed the video stream from the local camera into this method as follows, everything works just fine and the video stream displays on screen:

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

But, when I send a stream of those NSData packets over a peer-to-peer connection and receive them in the following fashion, I get an EXC_BAD_ACCESS error:

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

Using the debugger, I learned that the bad access occurs on this line:

CVPixelBufferLockBaseAddress(imageBuffer,0); 

I have no idea why the NSData sent over the network should be any different than the NSData sent from another method on the same device. I have checked that the data received over the network is being received at the same interval and is the same length (336 bytes) as the data produced on the local device. I also checked the retain count of the data object is 1 before it is used. It seems that the imageBuffer variable is somehow getting lost.

A couple of questions:

  1. Is casting data.bytes to a CMSampleBufferRef the right way to go about unpacking NSData?

  2. How do I assert that the data being received is actually a CMSampleBuffer object? I want to protect my code but I'm not sure how to accomplish a class verification for Core Foundation classes.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明媚殇 2024-10-13 09:57:49

为什么要通过转换 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 中提取什么内容。

Why are you 'unpacking' (that's not unpacking) your CMSampleBuffer by casting the bytes of NSData? That's never going to work, because CMSampleBuffer is not a continuous block in memory.

You have to retrieve all the relevant data from a CMSampleBuffer yourself before sending, stuff it into and NSData object, and reasemble it on the other side via

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
);

The data types in this function might give you a hint what you want to extract from the CMSampleBuffer when packing your data.

山田美奈子 2024-10-13 09:57:49

这可能不是完整的答案,但您对 malloc_size 的使用对我来说似乎是一个巨大的危险信号。这似乎是一个不可移植的扩展,不受 ANSI、ISO 或 POSIX 等任何内容的约束,并且我对如果传递的缓冲区不是来自 malloc 时它的行为方式有些怀疑。这似乎是一个粗略的依赖。 (我想说,如果调用 malloc_size ,那么作为 C 编码器,你就已经做错了,因为 C 就是要知道你的缓冲区有多大,而不是依赖于不可移植的 libc 函数为您完成缓冲区大小跟踪工作。)

This is probably not the entire answer, but your use of malloc_size seems like a huge red flag to me. This seems a non-portable extension, not governed by anything like ANSI, ISO or POSIX, and I have some doubts on how it might behave if passed a buffer that didn't come from malloc. It seems like a sketchy thing to rely on. (I would say if it's come to calling malloc_size you're already doing something wrong as a C coder, since C is all about knowing how big your buffers are upfront and not relying on non-portable libc functions to do your buffer-size-tracking work for you.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文