6

Wie können wir den Kamera-Feed effizient von einem iOS-Gerät auf ein anderes über Bluetooth oder WLAN in iOS 7 übertragen? Unten ist Code für Dampfpuffer.So dampfen Sie die Kamera von einem iOS-Gerät mit einem anderen über die Multi-Peer-Konnektivität

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
     didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    // Create a UIImage from the sample buffer data 
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 


} 

    // Create a UIImage from sample buffer data 
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
     bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return (image); 
} 

hier können wir Bild bekommen, die von iOS-Kamera aufgenommen wird.

Können wir Beispielpufferinformationen direkt an ein anderes Gerät mit Multi-Peer senden oder gibt es eine effiziente Möglichkeit, die Daten auf andere iOS-Geräte zu übertragen?

Vielen Dank.

+0

Multipeer Connectivity klingt wie eine gültige Option. Aber Sie müssen die Leistung überprüfen. Das Senden unkomprimierter Bilder erfordert wahrscheinlich zu viel Bandbreite, sodass Sie wahrscheinlich einen echten Videostream erstellen müssen, um Live-Aufnahmen übertragen zu können. – allprog

+0

Edits müssen 6 Zeichen lang sein, wenn wir also keinen Füller haben, wird dieser Post den Feed ewig dämpfen –

+0

Gute Frage Sandipbhai, Upvoted .. – NSPratik

Antwort

0

Ich habe den Weg, es zu tun, können wir Multi-Peer-Konnektivität verwenden, um komprimierte Bilder zu streamen, so dass es wie Streaming der Kamera aussehen wird.

Ein Peer, der den Stream senden wird wird diese Methode code.In captureOutput Delegate verwenden:

 NSData *imageData = UIImageJPEGRepresentation(cgBackedImage, 0.2); 

    // maybe not always the correct input? just using this to send current FPS... 
    AVCaptureInputPort* inputPort = connection.inputPorts[0]; 
    AVCaptureDeviceInput* deviceInput = (AVCaptureDeviceInput*) inputPort.input; 
    CMTime frameDuration = deviceInput.device.activeVideoMaxFrameDuration; 
    NSDictionary* dict = @{ 
          @"image": imageData, 
          @"timestamp" : timestamp, 
          @"framesPerSecond": @(frameDuration.timescale) 
          }; 
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict]; 


    [_session sendData:data toPeers:_session.connectedPeers withMode:MCSessionSendDataReliable error:nil]; 

Und auf der Empfangsseite:

- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID { 

// NSLog(@"(%@) Read %d bytes", peerID.displayName, data.length); 

    NSDictionary* dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
    UIImage* image = [UIImage imageWithData:dict[@"image"] scale:2.0]; 
    NSNumber* framesPerSecond = dict[@"framesPerSecond"]; 


} 

Wir Wert FPS bekommen und dementsprechend Wir können Parameter für die Verwaltung unserer Streaming-Bilder festlegen.

Ich hoffe, es wird helfen.

Vielen Dank.

+0

Sandip hast du versucht, die Audiodateien zwischen zwei iPhone-Geräten mit Multi-Peer zu streamen? –

0

Hier ist der beste Weg, es zu tun (und ich, warum am Ende erklären):

Auf dem iOS-Gerät die Bilddaten zu senden:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

    CVPixelBufferLockBaseAddress(imageBuffer,0); 
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 


    UIImage *image = [[UIImage alloc] initWithCGImage:newImage scale:1 orientation:UIImageOrientationUp]; 
    CGImageRelease(newImage); 
    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace); 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 

    if (image) { 
     NSData *data = UIImageJPEGRepresentation(image, 0.7); 
     NSError *err; 
     [((ViewController *)self.parentViewController).session sendData:data toPeers:((ViewController *)self.parentViewController).session.connectedPeers withMode:MCSessionSendDataReliable error:&err]; 
    } 
} 

Auf dem iOS-Gerät die Bilddaten empfangen :

typedef struct { 
    size_t length; 
    void *data; 
} ImageCacheDataStruct; 

- (void)session:(nonnull MCSession *)session didReceiveData:(nonnull NSData *)data fromPeer:(nonnull MCPeerID *)peerID 
{ 
    dispatch_async(self.imageCacheDataQueue, ^{ 
     dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); 
     const void *dataBuffer = [data bytes]; 
     size_t dataLength = [data length]; 
     ImageCacheDataStruct *imageCacheDataStruct = calloc(1, sizeof(imageCacheDataStruct)); 
     imageCacheDataStruct->data = (void*)dataBuffer; 
     imageCacheDataStruct->length = dataLength; 

     __block const void * kMyKey; 
     dispatch_queue_set_specific(self.imageDisplayQueue, &kMyKey, (void *)imageCacheDataStruct, NULL); 

     dispatch_sync(self.imageDisplayQueue, ^{ 
      ImageCacheDataStruct *imageCacheDataStruct = calloc(1, sizeof(imageCacheDataStruct)); 
      imageCacheDataStruct = dispatch_queue_get_specific(self.imageDisplayQueue, &kMyKey); 
      const void *dataBytes = imageCacheDataStruct->data; 
      size_t length = imageCacheDataStruct->length; 
      NSData *imageData = [NSData dataWithBytes:dataBytes length:length]; 
      UIImage *image = [UIImage imageWithData:imageData]; 
      if (image) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [((ViewerViewController *)self.childViewControllers.lastObject).view.layer setContents:(__bridge id)image.CGImage]; 
        dispatch_semaphore_signal(self.semaphore); 
       }); 
      } 
     }); 
    }); 
} 

Der Grund für die Semaphore und die separaten GCD Warteschlangen einfach: wollen Sie den Rahmen in gleichen Zeitabständen angezeigt werden soll. Sonst scheint das Video zuerst zu verlangsamen, kurz bevor es schneller als normal beschleunigt wird, um aufzuholen. Mein Schema stellt sicher, dass jeder Frame im selben Tempo nacheinander abgespielt wird, unabhängig von Netzbandbreitenengpässen.