2014-05-16 36 views
7

sto cercando di rispecchiare video ricevuto da webcam su Mac OS X. Vorrei evitare di fare un flip/tranform manuale dopo aver ricevuto il buffer video. Quindi, voglio impostare AVCaptureSession in modo tale che il buffer video ricevuto nel metodo captureOutput di AVCaptureVideoDataOutputSampleBufferDelegate venga specchiato da AVFoundation stesso. Non voglio usare il livello di anteprima.AVFoundation - come specchio di video da webcam - Mac OS X

Su un iMac (10.8.5), per eseguire il mirroring del video, AVCaptureConnection isVideoMirroringSupported viene testato con successo prima di impostare la proprietà videoMirrored. Ma il buffer video ricevuto nel delegato captureOutput non è speculare.

Nota: Il video mirroring su iOS ha avuto successo, quando ho seguito this SO rispondere. Ma non sta aiutando su mac os x.

codice utilizzato è inferiore. Il controllo degli errori è lasciato fuori per questo post.

//create session 
    _session = [[AVCaptureSession alloc] init]; 

    //get capture device 
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    //create sesion input 
    NSError * error; 
    _sessionInput = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error]; 

    //create session output 
    _sessionOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    [_sessionOutput setAlwaysDiscardsLateVideoFrames:YES]; 
    [[_sessionOutput connectionWithMediaType:AVMediaTypeVideo] setEnabled:YES]; 
    NSDictionary *videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 
    [_sessionOutput setVideoSettings:videoSettings]; 

    //serial queue to process video frames 
    dispatch_queue_t videoOutputQueue = dispatch_queue_create("deviceeraQueue", DISPATCH_QUEUE_SERIAL); 
    [_sessionOutput setSampleBufferDelegate:self queue:videoOutputQueue]; 

    //begin session configuration 
    [_session beginConfiguration ]; 

    //input and output for session 
    if([_session canAddInput:_sessionInput]) { 
     [_session addInput:_sessionInput]; 
    } 
    if([_session canAddOutput:_sessionOutput]) { 
     [_session addOutput:_sessionOutput]; 

    } 

    //set video mirroring 
    AVCaptureConnection* avConnection = [_sessionOutput connectionWithMediaType:AVMediaTypeVideo]; 
    if([avConnection isVideoMirroringSupported]) { 
     avConnection.videoMirrored = YES; 
     NSLog(@"Video mirroring Support: YES"); // this line is printed 
    } else { 
     NSLog(@"Video mirroring Support: NO"); 
    } 

    //set session preset  
    [_session setSessionPreset:AVCaptureSessionPreset640x480]; 
    [ _session commitConfiguration ]; 

    ........... 
    ........... 

    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
    { 
    ......... 
    //sampleBuffer is not mirrored video 
    ........ 

di minore rilevanza 1 - anche se C++, ho anche provato a guardare nella implementazione VideoCapture di OpenCV per modo di rispecchiare il video. Ma OpenCV non rispecchia il video da Mac (usa flip). A sinistra è libVlc/V4L.

di minore importanza 2 - In slitta 73 di this presentazione mela 2010 WWDC (3Mb pdf), c'è una menzione che setVideoOrientation non è supportato su 'collegamento AVCaptureVideoDataOutput`. Ma nel 2013, la mela docs viene aggiornata e supporta questo metodo.

risposta

5

È possibile aggiungere una trasformazione sullo strato di anteprima per capovolgere il valore x dei frame, prima di raggiungere la finestra di anteprima.

[[self previewLayer] setTransform:CATransform3DMakeScale(-1, 1, 1)]; 

Quindi è possibile eseguire il video registrato attraverso la sessione di esportazione e fare la stessa trasformazione. In questo modo l'anteprima del video corrisponderà al video registrato finale. Un po 'incisivo, ma ottiene gli stessi risultati.

+0

Grazie. Ma in questione, avevo menzionato la riluttanza a usare il livello di anteprima (nel paragrafo 1) – Kiran

+2

OSX non rispetta la proprietà videoMirrored, probabilmente un bug. L'utilizzo di un livello di anteprima è l'unico modo che ho trovato per ottenere l'effetto. – tansk1

2

Perché incidere quando è molto facile. Basta impostare automaticamente AdjustVideoMirroring di AVCaptureConnection quindi impostarlo manualmente.

aPreviewLayer.connection.automaticallyAdjustsVideoMirroring = NO; 
    aPreviewLayer.connection.videoMirrored = YES; 
+0

Grazie. Ma guarda gentilmente la mia menzione sulla riluttanza al tuo livello di anteprima (nel paragrafo 1 della domanda). Lo stesso è menzionato di nuovo nel mio commento alla risposta precedente. – Kiran

+0

Non penso che sia possibile senza utilizzare il livello di anteprima. Ma puoi certamente ottenere lo stesso effetto, ad esempio ridimensionando. Il ridimensionamento del buffer mediante (x, y, z) = (-1,1,1) otterrebbe l'effetto di mirroring :) –

+0

'Non penso che sia possibile senza utilizzare il livello di anteprima. - Quindi per chiudere la domanda, per Supponiamo che, avremo bisogno di un documento sorgente valido o di un rapporto sui bug accettato da Apple. – Kiran