NSData over GameKit 和 EXC_BAD_ACCESS 奇怪的问题
我正在尝试通过 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 类的类验证。
提前致谢!
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:
Is casting data.bytes to a CMSampleBufferRef the right way to go about unpacking NSData?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么要通过转换
NSData
的字节来“解包”(不是解包)您的CMSampleBuffer
?这永远不会起作用,因为 CMSampleBuffer 不是内存中的连续块。在发送之前,您必须自己从
CMSampleBuffer
中检索所有相关数据,将其填充到NSData
对象中,并通过此函数中的数据类型 在另一端重新组合它可能会提示您在打包数据时想要从 CMSampleBuffer 中提取什么内容。
Why are you 'unpacking' (that's not unpacking) your
CMSampleBuffer
by casting the bytes ofNSData
? That's never going to work, becauseCMSampleBuffer
is not a continuous block in memory.You have to retrieve all the relevant data from a
CMSampleBuffer
yourself before sending, stuff it into andNSData
object, and reasemble it on the other side viaThe data types in this function might give you a hint what you want to extract from the
CMSampleBuffer
when packing your data.这可能不是完整的答案,但您对
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 frommalloc
. It seems like a sketchy thing to rely on. (I would say if it's come to callingmalloc_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.)