ここのAppleのドキュメントには、次のように記載されています。
クライアントは、AVCaptureVideoDataOutput -captureOutput:didOutputSampleBuffer:fromConnection: デリゲート コールバックで、物理的に回転された CVPixelBuffers を受け取ることができるようになりました。以前の iOS バージョンでは、前面カメラは常に AVCaptureVideoOrientationLandscapeLeft でバッファーを配信し、背面カメラは常に AVCaptureVideoOrientationLandscapeRight でバッファーを配信していました。4 つの AVCaptureVideoOrientations すべてがサポートされ、回転はハードウェア アクセラレーションされます。バッファーの回転を要求するために、クライアントは AVCaptureVideoDataOutput のビデオ AVCaptureConnection で -setVideoOrientation: を呼び出します。物理的なバッファのローテーションにはパフォーマンス コストがかかるため、必要な場合にのみローテーションをリクエストしてください。たとえば、AVAssetWriter を使用して回転したビデオを QuickTime ムービー ファイルに書き込む場合は、
したがって、AVAssetExportSession を使用する Aaron Vegh が投稿したソリューションは機能しますが、必要ありません。Apple doc の言うように、向きを正しく設定して、VLC などの Apple 以外の QuickTime プレーヤーで再生したり、Chrome を使用して Web で再生したりする場合は、AVCaptureVideoDataOutput の AVCaptureConnection でビデオの向きを設定する必要があります。AVAssetWriterInput に設定しようとすると、VLC や Chrome などのプレーヤーの方向が正しくなくなります。
キャプチャセッションのセットアップ中に設定したコードは次のとおりです。
// DECLARED AS PROPERTIES ABOVE
@property (strong,nonatomic) AVCaptureDeviceInput *audioIn;
@property (strong,nonatomic) AVCaptureAudioDataOutput *audioOut;
@property (strong,nonatomic) AVCaptureDeviceInput *videoIn;
@property (strong,nonatomic) AVCaptureVideoDataOutput *videoOut;
@property (strong,nonatomic) AVCaptureConnection *audioConnection;
@property (strong,nonatomic) AVCaptureConnection *videoConnection;
------------------------------------------------------------------
------------------------------------------------------------------
-(void)setupCaptureSession{
// Setup Session
self.session = [[AVCaptureSession alloc]init];
[self.session setSessionPreset:AVCaptureSessionPreset640x480];
// Create Audio connection ----------------------------------------
self.audioIn = [[AVCaptureDeviceInput alloc]initWithDevice:[self getAudioDevice] error:nil];
if ([self.session canAddInput:self.audioIn]) {
[self.session addInput:self.audioIn];
}
self.audioOut = [[AVCaptureAudioDataOutput alloc]init];
dispatch_queue_t audioCaptureQueue = dispatch_queue_create("Audio Capture Queue", DISPATCH_QUEUE_SERIAL);
[self.audioOut setSampleBufferDelegate:self queue:audioCaptureQueue];
if ([self.session canAddOutput:self.audioOut]) {
[self.session addOutput:self.audioOut];
}
self.audioConnection = [self.audioOut connectionWithMediaType:AVMediaTypeAudio];
// Create Video connection ----------------------------------------
self.videoIn = [[AVCaptureDeviceInput alloc]initWithDevice:[self videoDeviceWithPosition:AVCaptureDevicePositionBack] error:nil];
if ([self.session canAddInput:self.videoIn]) {
[self.session addInput:self.videoIn];
}
self.videoOut = [[AVCaptureVideoDataOutput alloc]init];
[self.videoOut setAlwaysDiscardsLateVideoFrames:NO];
[self.videoOut setVideoSettings:nil];
dispatch_queue_t videoCaptureQueue = dispatch_queue_create("Video Capture Queue", DISPATCH_QUEUE_SERIAL);
[self.videoOut setSampleBufferDelegate:self queue:videoCaptureQueue];
if ([self.session canAddOutput:self.videoOut]) {
[self.session addOutput:self.videoOut];
}
self.videoConnection = [self.videoOut connectionWithMediaType:AVMediaTypeVideo];
// SET THE ORIENTATION HERE -------------------------------------------------
[self.videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
// --------------------------------------------------------------------------
// Create Preview Layer -------------------------------------------
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
CGRect bounds = self.videoView.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.bounds = bounds;
previewLayer.position=CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
[self.videoView.layer addSublayer:previewLayer];
// Start session
[self.session startRunning];
}