开发者

NSData over GameKit and EXC_BAD_ACCESS strange problem

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 sa开发者_如何学Gome 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!


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜