2012-04-07 9 views
0

UPDATE - Ich habe einige Fehler in dem Code unten behoben und die Bilder werden auf dem anderen Gerät angezeigt, aber ich habe ein anderes Problem. Während die Videoaufnahme geöffnet ist, sendet das "Master" -Gerät Daten kontinuierlich, manchmal erscheint diese Aufnahme auf dem "Slave" -Gerät und in einer sehr kurzen Zeit blinkt das Bild "leer" und wiederholt dies alle Zeit für eine kurze Zeit. Irgendeine Idee dazu?IOS Empfangen von Video vom Netzwerk

Ich arbeite an einer App, die Live-Kamera-Capture und Live-Mikrofon-Capture an ein anderes Gerät im Netzwerk senden muss.

Ich habe die Verbindung zwischen Geräten mit einem TCP-Server und veröffentlichen Sie es mit Bonjour, das funktioniert wie ein Charme.

Der wichtigste Teil ist zum Senden und Empfangen von Video und Audio von "Master" -Gerät und Rendern auf "Slave" -Gerät.

Als erstes ist hier ein Stück Code, wo der App, die Kamera-Probenpuffer und Transformation in UIImage erhalten:

@implementation AVCaptureManager (AVCaptureVideoDataOutputSampleBufferDelegate) 

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 
    NSData *data = UIImageJPEGRepresentation(image, 0.2); 

    [self.delegate didReceivedImage:image]; 
    [self.delegate didReceivedFrame:data]; 

    [pool drain]; 
    }); 
} 


- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    size_t bytesPerRow = width * 4; 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    CGContextRef context = CGBitmapContextCreate(
               baseAddress, 
               width, 
               height, 
               8, 
               bytesPerRow, 
               colorSpace, 
               kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little 
               ); 

    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 

    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 
    CGImageRelease(quartzImage); 
    CGColorSpaceRelease(colorSpace); 
    CGContextRelease(context); 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 

    return image; 
} 

@end 

Die Meldung "[self.delegate didReceivedImage: Bild];" dient nur dazu, die Bilderfassung auf dem Master-Gerät zu testen, und dieses Bild funktioniert auf dem Aufnahmegerät.

Der nächste Schritt ist, wie ich es senden zu vernetzen:

- (void) sendData:(NSData *)data 
{ 
    if(_outputStream && [_outputStream hasSpaceAvailable]) 
    { 
    NSInteger bytesWritten = [_outputStream write:[data bytes] maxLength:[data length]]; 

    if(bytesWritten < 0) 
     NSLog(@"[ APP ] Failed to write message"); 

    } 
} 

Schau, ich bin mit Runloop Ströme zu schreiben und zu lesen, ich denke, das als offen besser ist und schließt ständig Bächen.

Als nächstes ich die „NSStreamEventHasBytesAvailable“ Ereignis auf dem Slave-Gerät empfangen, wo das Stück Code, das handhaben ist:

case NSStreamEventHasBytesAvailable: 
     /*I can't to start a case without a expression, why not?*/ 
     NSLog(@"[ APP ] stream handleEvent NSStreamEventHasBytesAvailable"); 
     NSUInteger bytesRead; 
     uint8_t buffer[BUFFER_SIZE]; 

     while ([_inputStream hasBytesAvailable]) 
     { 
     bytesRead = [_inputStream read:buffer maxLength:BUFFER_SIZE]; 
     NSLog(@"[ APP ] bytes read: %i", bytesRead); 

     if(bytesRead) 
      [data appendBytes:(const void *)buffer length:sizeof(buffer)]; 
     } 


     [_client writeImageWithData:data]; 

     break; 

Der Wert BUFFER_SIZE ist 32768. ich denke, die während der Block nicht notwendig ist, , aber ich benutze es, weil, wenn ich nicht alle verfügbaren Bytes bei der ersten Iteration lesen kann, ich in der nächsten einlesen kann.

Also, das ist der Punkt, kommt der Strom richtig, aber das Bild auf NSData serialisiert scheint beschädigt werden, in den nächsten, ich Daten senden nur an den Client ...

[_client writeImageWithData:data]; 

... und erstellen ein UIImage mit Daten in Client-Klasse einfach so ...

[camPreview setImage:[UIImage imageWithData:data]]; 

im camPreview (ja ist ein UIImageView), ich habe ein Bild nur auf dem Bildschirm, um den Platzhalter angezeigt werden, wenn ich die imagem von Netzwerk erhalten und an camPreview übergeben, wird der Platzhalter leer.

Andere denken, ist über den Ausgang, wenn ich die Einnahme beginnen, erste Teile, wo ich Daten empfangen, erhalte ich diese Nachricht aus dem System:

Error: ImageIO: JPEG Corrupt JPEG data: 28 extraneous bytes before marker 0xbf

Error: ImageIO: JPEG Unsupported marker type 0xbf

Nach einiger wenig Zeit, ich nicht mehr diese Nachrichten bekommen.

Der Punkt ist, finden Sie die Ursache des Bildes nicht auf dem "Slave" -Gerät angezeigt werden.

Danke.

+0

@ Jan thsi wird Bilder über das Netzwerk senden, aber was ist mit dem Audio? Wie sende ich Audio mit Bildern? – sajwan

+0

re: Kann einen Fall ohne einen Ausdruck nicht starten. Sie müssen die Anweisungen in Ihrem Fall mit geschweiften Klammern, z. Fall 1: {...} Es ist ein esoterisches C-Ding. –

Antwort

0

Ich bin nicht sicher, wie oft Sie Bilder senden, aber selbst wenn es nicht sehr oft ist, würde ich nach den SOI- und EOI-Markierungen in den JPEG-Daten suchen, um sicherzustellen, dass Sie alle Daten haben. Hier ist ein post Ich fand schnell

+0

Ich sende Daten kontinuierlich, während die Videoaufnahme geöffnet ist. –

0

Ich fand eine answer, JPEG-Format vor dem Rendern zu überprüfen.

Dies löste mein Problem und jetzt kann ich Video-Capture von einem "Master" iOS-Gerät zu einem "Slave" iOS-Gerät anzeigen.

+0

Ich arbeite an der gleichen Sache und wenn ich ein Bild erhalte, scheint es beschädigt zu sein. Ich sende ein fortlaufendes Bild wie du. In meinem Fall komme ich nie aus while inputStream.hasBytesAvailable {function. –

+0

macht mir nichts, ich bin in der Lage, die Daten zu streamen, aber es ist zu langsam. –

Verwandte Themen