如何使用AVFoundation为逐帧生成的视频设置方向?



我正在编写一个iPhone应用程序,该应用程序从相机拍摄视频,通过一些OpenGL着色器代码运行它,然后使用AVFoundation将输出写入视频文件。应用程序以横向方向运行(或者),因此所有录制的视频都应该是横向的。

我在开始录制之前使用的当前代码是:

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

其中videoWriterInput是AVAssetWriterInput的一个实例,目的是补偿横向模式和OpenGL的反向方向。

这产生的视频,当下载和播放Quicktime播放器播放正确。不过,如果我将录制的视频添加到iPhone的照片库中,缩略图会正确显示,但如果手机横着拿,视频会旋转90度播放。如果手机竖着拿,视频会正常播放,但会水平裁剪以适应竖着的尺寸。

根据Apple技术说明,我用于处理视频帧的AVCaptureVideoDataOutput的捕获输出不支持设置视频方向。

有没有人成功地录制了可以添加到iPhone库并在景观中正确播放的景观生成视频,如果是这样,如何?

你的帖子让我对苹果视频应用程序播放视频的方式大开眼界。我用我的app用四个方向的设备记录了几个项目。他们都有正确的方向。我只是注意到,视频应用程序不像相册应用程序中的播放器那样支持旋转。视频应用程序要求你以横向方式拿着设备(至少是我的iPod touch)。我做了一些人像录制,并将它们添加到iTunes中,所有这些,包括用苹果相机应用创建的那个,在将设备旋转到人像方向时都没有旋转。

无论如何……

我的应用程序是一个时间推移应用程序,不做任何额外的处理像你正在做的帧,所以YMMV在以下。我设置了我的应用程序,这样它就不会在设备旋转时旋转窗口。这样我总是处理设备的一个方向。我使用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变量的

-(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];

这是我在这篇sofsofq & a中找到的一个技巧。

简单多了…

在你的顶点着色器中:

uniform float preferredRotation;...mat4 rotationMatrix = mat4(cos(preferrerotation), -sin(preferrerotation), 0.0, 0.0,sin(preferredrotion), cos(preferredrotion), 0.0, 0.0,0.0 0.0 1.0 0.00.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);

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

if ([videoTrack statusOfValueForKey:@"preferredTransform"错误:nil] == AVKeyValueStatusLoaded) {CGAffineTransform preferredTransform = [videoTrack preferredTransform];self. playerview . preferrerotation = -1 * atan2(preferredTransform.)

b, preferredTransform.a);

最新更新