如何使用 AVFoundation 为逐帧生成的视频设置方向? [英] How do I set the orientation for a frame-by-frame-generated video using AVFoundation?

查看:27
本文介绍了如何使用 AVFoundation 为逐帧生成的视频设置方向?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 iPhone 应用程序,它从摄像头获取视频,通过一些 OpenGL 着色器代码运行它,然后使用 AVFoundation 将输出写入视频文件.该应用程序以横向(任一)方向运行,因此录制的所有视频都应为横向.

I am writing an iPhone app which takes video from the camera, runs it through some OpenGL shader code and then writes the output to a video file using AVFoundation. The app runs in lanscape orientation (either) and therefore all video recorded should be landscape.

我在开始录制之前使用的当前代码来正确获取视频是:

The current code I use before starting recording to get the video the right way round is:

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

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

where videoWriterInput is an instance of AVAssetWriterInput and the aim is to compensate for the landscape mode and the reveresed orientation of OpenGL.

这会生成在 Quicktime 播放器上下载和播放时可以正确播放的视频.但是,如果我将录制的视频添加到 iPhone 照片库,缩略图会正确显示,但如果手机处于横向状态,视频会旋转 90 度播放.如果手机是纵向的,视频可以正常播放,但会被水平裁剪以适应纵向尺寸.

This produces video which when downloaded and played on Quicktime player plays correctly. However, if I add the recorded video to the iPhone photo library, the thumbnail displays correctly but the video plays rotated 90 degrees if the phone is held in landscape. If the phone is held in portrait the video plays correctly but is cropped horizontally to fit the portrait dimensions.

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

According to this Apple tech note the capture output for AVCaptureVideoDataOutput, which I use for processing the video frames, does not support setting the video orientation.

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

Has anyone successfully recorded landscape generated video which can be added to the iPhone library and plays correctly in landscape and if so how?

推荐答案

你的帖子让我看到了 Apples Videos 应用程序如何播放视频.我用我的应用程序在四个方向上记录了几个项目.他们都以正确的方向播放.我刚刚注意到视频应用不像相册应用中的播放器那样支持旋转.视频应用程序希望您横向握住设备(至少是我的 iPod touch).我做了一些纵向录制,将它们添加到 iTunes,包括使用 Apple 的相机应用程序创建的所有内容,在将设备旋转到纵向时都没有旋转.

Your post opened my eyes about how Apples Videos app plays back video. I recorded several items with my app with the device in the four orientations. They all played back properly oriented. I just noticed that the Videos app doesn't support rotation like the player in the Photos Album app. The Videos app expects you to hold the device (at least my iPod touch) in landscape. I did some portrait recordings, added them to iTunes, and all, including the one created with Apple's camera app, did not rotate when rotating the device to portrait orientation.

无论如何...

我的应用程序是一个延时应用程序,它不会像你那样对帧进行任何额外的处理,所以 YMMV 在下面.我设置了我的应用程序,使其在设备旋转时不会旋转窗口.这样我总是处理设备的一个方向.我使用 AVFoundation 从视频流中抓取每第 N 帧并将其写出来.

My app is a time lapse app that does not do any extra processing on the frames like you are doing, so YMMV on the following. I have my app set up so that it does not rotate the window as the device is rotated. This way I'm always dealing with one orientation of the device. I use AVFoundation to grab every Nth frame from the video stream and write that out.

在设置录制时,我会执行以下操作.

As I set up for recording, I do the following.

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的.

That detectOrientation calls the following method. I've reduced the actual code for clarity here. In my app I also rotate some buttons, so notice they do not get the same transformation. The thing to pay attention to is how I'm setting up the 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 方法中有以下内容.

As a side note, since I want the method called when ever the device is rotated, and I've turned off automatic rotation, I have the following in my viewDidLoad method.

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

这是我在 this SOF Q& 中找到的提示;A.

这篇关于如何使用 AVFoundation 为逐帧生成的视频设置方向?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆