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.
@ Jan thsi wird Bilder über das Netzwerk senden, aber was ist mit dem Audio? Wie sende ich Audio mit Bildern? – sajwan
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. –