2011-10-08 75 views
3

我正在写一个iPhone应用程序,它从摄像头获取视频,通过一些OpenGL着色器代码运行它,然后使用AVFoundation将输出写入视频文件。该应用程序以lanscape方向(或者)运行,因此所有记录的视频都应该是横向的。如何使用AVFoundation设置逐帧生成视频的方向?

当前的代码我开始录音,以获得该视频的正确的方式是使用前:

[[self videoWriterInput] setTransform:CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI), -1.0, 1.0)]; 

其中videoWriterInput是AVAssetWriterInput一个实例,目的是弥补风景模式和reveresed方向的OpenGL。

这会产生在Quicktime播放器下载并播放时播放正确的视频。但是,如果我将录制的视频添加到iPhone照片库,则缩略图可以正确显示,但如果手机处于横向模式,则视频播放会旋转90度。如果手机保持纵向显示,则视频播放正确,但会水平裁剪以适应纵向尺寸。

根据this Apple tech note我用于处理视频帧的AVCaptureVideoDataOutput的捕获输出不支持设置视频方向。

是否有人成功录制了横向生成的视频,这些视频可以添加到iPhone库并在横向上正确播放,如果是这样的话?

+0

是否有任何理由,你不能这样做在OpenGL旋转读出像素的帧缓冲区之前,以获得正确的方向?这样您就不必担心放在MOV/MP4标题中的变换。默认会正常工作。 –

+0

感谢这个想法。然而问题在于屏幕上的实时视图是正确的 - 只有将录制的视频保存到iPhone库并播放它,甚至在桌面上正确播放录音,才会显示错误的视图。 – domgblackwell

回答

9

您的文章打开了我的眼睛,关于Apples Videos应用程序如何播放视频。我用这个设备在四个方向上记录了几个项目。他们都回放得很好。我只注意到视频应用不支持像Photos Album应用中的播放器那样的旋转。视频应用程序希望您将设备(至少是我的iPod touch)横向放置。我做了一些肖像录音,将它们添加到iTunes中,包括使用Apple相机应用程序创建的所有内容在将设备旋转到纵向时都不旋转。

反正...

我的应用程序是一个时间的推移应用程序,不会做框架的任何额外的处理就像你正在做的,所以因人而异放在下面。我设置了我的应用程序,以便在设备旋转时不会旋转窗口。这样我总是处理设备的一个方向。我使用AVFoundation从视频流中抓取每一个第N帧并写出来。

当我设置录音时,我做了以下操作。

inputWriterBuffer = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo outputSettings: outputSettings]; 
    // I call this explicitly before recording starts. Video plays back the right way up. 
[self detectOrientation]; 
inputWriterBuffer.transform = playbackTransform; 

detectOrientation调用以下方法。这里我已经减少了实际的代码。在我的应用程序中,我也旋转了一些按钮,所以注意他们没有得到相同的转换。需要注意的是我如何设置playbackTransform ivar。

-(void) detectOrientation { 
CGAffineTransform buttonTransform; 

switch ([[UIDevice currentDevice] orientation]) { 
    case UIDeviceOrientationUnknown: 
     NULL; 
    case UIDeviceOrientationFaceUp: 
     NULL; 
    case UIDeviceOrientationFaceDown: 
     NULL; 
     break; 
    case UIDeviceOrientationPortrait: 
     [UIButton beginAnimations: @"myButtonTwist" context: nil]; 
     [UIButton setAnimationDuration: 0.25]; 
     buttonTransform = CGAffineTransformMakeRotation((0 * M_PI)/180); 
     recordingStarStop.transform = buttonTransform; 
     [UIButton commitAnimations];    

     playbackTransform = CGAffineTransformMakeRotation((90 * M_PI)/180); 
     break; 
    case UIDeviceOrientationLandscapeLeft: 
     [UIButton beginAnimations: @"myButtonTwist" context: nil]; 
     [UIButton setAnimationDuration: 0.25]; 
     buttonTransform = CGAffineTransformMakeRotation((90 * M_PI)/180); 
     recordingStarStop.transform = buttonTransform; 
     [UIButton commitAnimations];    

     // Transform depends on which camera is supplying video 
     if (theProject.backCamera == YES) playbackTransform = CGAffineTransformMakeRotation(0/180); 
     else playbackTransform = CGAffineTransformMakeRotation((-180 * M_PI)/180); 

     break; 
    case UIDeviceOrientationLandscapeRight: 
     [UIButton beginAnimations: @"myButtonTwist" context: nil]; 
     [UIButton setAnimationDuration: 0.25]; 
     buttonTransform = CGAffineTransformMakeRotation((-90 * M_PI)/180); 
     recordingStarStop.transform = buttonTransform; 
     [UIButton commitAnimations]; 

     // Transform depends on which camera is supplying video 
     if (theProject.backCamera == YES) playbackTransform = CGAffineTransformMakeRotation((-180 * M_PI)/180); 
     else playbackTransform = CGAffineTransformMakeRotation(0/180); 

     break; 
    case UIDeviceOrientationPortraitUpsideDown: 
     [UIButton beginAnimations: @"myButtonTwist" context: nil]; 
     [UIButton setAnimationDuration: 0.25]; 
     buttonTransform = CGAffineTransformMakeRotation((180 * M_PI)/180); 
     recordingStarStop.transform = buttonTransform; 
     [UIButton commitAnimations]; 

     playbackTransform = CGAffineTransformMakeRotation((-90 * M_PI)/180); 
     break; 
    default: 
     playbackTransform = CGAffineTransformMakeRotation(0/180); // Use the default, although there are likely other issues if we get here. 
     break; 
} 
} 

作为一个方面说明,因为我要永远当设备旋转调用的方法,我已经关掉自动旋转,我在我的viewDidLoad方法如下。

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(detectOrientation) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; 

这是我在this SOF Q&A中发现的提示。

+0

这个答案确实导致了我的应用程序的正确答案。对于OpenGL转换后的视频,我仍然需要应用比例来翻转视频,但关键的洞察是我需要通过-M_PI旋转而不是M_PI。谢谢! – domgblackwell

+0

不客气。 –

0

很简单...

在您的顶点着色器中:

uniform float preferredRotation; 。 。 。 MAT4 rotationMatrix = MAT4(COS(preferredRotation)-sin(preferredRotation),0.0,0.0, SIN(preferredRotation),COS(preferredRotation),0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0, 0.0,1.0);

/* 90-degrees 
mat4 rotationMatrix = mat4(cos(preferredRotation), -sin(preferredRotation), (1.0 - cos(preferredRotation)) - sin(preferredRotation), 0.0, 
          -sin(preferredRotation), cos(preferredRotation), 0.0, 0.0, 
          0.0,      0.0, 1.0, 0.0, 
          0.0,      0.0, 0.0, 1.0); 

在调用该着色器中的视图或视图控制器:

如果([videoTrack statusOfValueForKey:@ “preferredTransform” 错误:无] == AVKeyValueStatusLoaded){ CGAffineTransform preferredTransform = [videoTrack preferredTransform]; self.playerView.preferredRotation = -1 * atan2(preferredTransform.b,preferredTransform.a);

...等等...

相关问题