2010-09-29 6 views
11


Aquí está el problema. Estoy usando AVCaptureVideoDataOutput para obtener marcos de video de la cámara y hacer videos de ellos con AVAssetWriter. Está funcionando bien, pero el video que recibo está boca abajo porque la orientación predeterminada del dispositivo para mi aplicación es horizontal, no es correcto como se establece por defecto en AVCaptureVideoDataOutput. Estoy tratando de cambiar la orientación en la clase AVCaptureConnection, pero isVideoOrientationSupported es siempre falso, ¿de alguna manera es posible solucionarlo?Cómo cambiar la orientación del video para AVCaptureVideoDataOutput

Aquí hay un código:

AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput 
      deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] 
      error:nil]; 
/*We setupt the output*/ 
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init]; 
captureOutput.alwaysDiscardsLateVideoFrames = YES; 
captureOutput.minFrameDuration = CMTimeMake(1.0, 24.0); //Uncomment it to specify a minimum duration for each video frame 
[captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 

// Set the video output to store frame in BGRA (It is supposed to be faster) 
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey; 
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; 



NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 
[captureOutput setVideoSettings:videoSettings]; 


/*And we create a capture session*/ 
self.captureSession = [[AVCaptureSession alloc] init]; 
self.captureSession.sessionPreset = AVCaptureSessionPresetLow; 
/*We add input and output*/ 
if ([self.captureSession canAddInput:captureInput]) 
{ 
    [self.captureSession addInput:captureInput]; 
} 
if ([self.captureSession canAddOutput:captureOutput]) 
{ 
    [self.captureSession addOutput:captureOutput]; 
} 

/*We add the preview layer*/ 
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession: self.captureSession]; 

if ([self.prevLayer isOrientationSupported]) 
{ 
    [self.prevLayer setOrientation:AVCaptureVideoOrientationLandscapeLeft]; 
} 

self.prevLayer.frame = self.view.bounds; 

self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
[self.view.layer addSublayer: self.prevLayer]; 

AVCaptureConnection *videoConnection = NULL; 

[self.captureSession beginConfiguration]; 

for (AVCaptureConnection *connection in [captureOutput connections]) 
{ 
    for (AVCaptureInputPort *port in [connection inputPorts]) 
    { 
    if ([[port mediaType] isEqual:AVMediaTypeVideo]) 
    { 
    videoConnection = connection; 

    } 
    } 
} 
    if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false** 
    { 
     [videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft]; 
    } 

[self.captureSession commitConfiguration]; 

[self.captureSession startRunning]; 

UPD: imaginó que al exportar vídeo, la AVAssetExportSession pierde información preferredTransform.

+0

Steve, ¿lo hiciste funcionar? Quería saber cómo usaste el AVAssetWriter con esto. Quiero poder transmitir video desde el iphone. – nickfox

+0

Espero que ayude. http://pastebin.com/RVEqWnyN – Steve

+0

Cuando utiliza la URL que obtiene: ¡Es posible que el "Pastebin" haya caducado o se haya eliminado! –

Respuesta

10

Me encontré con el mismo problema y hurgué en el AVCamDemo de la WWDC. No sé por qué (todavía) pero si consulta su videoConnection justo después de crear todas las entradas/salidas/conexiones, entonces ambos sonVideoOrientationSupported y supportsVideoOrientation return NO.

Sin embargo, si consulta supportsVideoOrientation o isVideoOrientationSupported en algún momento posterior (después de que la GUI se configure, por ejemplo), entonces devolverá SÍ. Por ejemplo, lo consulto justo después de que el usuario haga clic en el botón de grabación justo antes de llamar a [[self movieFileOutput] startRecordingToOutputFileURL ...]

Pruébalo, funciona para mí.

+0

¡Oh, vaya, esto es complicado! Pero funciona. Creo que Apple debería arreglar esto. La propiedad isVideoOrientationSupported se debe poder establecer en el mismo runloop cuando se crea AVCaptureOutput. Hacerlo en algún punto posterior simplemente complica innecesariamente el código. Incluso si hay una razón detrás, al menos el documento debería hablar sobre esto. ¡Debo transformar manualmente mi coordenada para leer el píxel antes de encontrar esta publicación! – Hlung

+1

En realidad, no necesita hacerlo en un runloop posterior. Puede hacer esto justo después de agregar addOutput: a AVCaptureSession. – Hlung

+0

Esta es una respuesta que salva vidas. Realmente no puedo entender por qué no se menciona nada sobre estas condiciones en la documentación. – aqs

Cuestiones relacionadas