Как установить ориентацию для покадрового видео с помощью AVFoundation? - PullRequest
4 голосов
/ 08 октября 2011

Я пишу приложение для iPhone, которое берет видео с камеры, запускает его через некоторый код шейдера OpenGL и затем записывает вывод в видеофайл, используя AVFoundation. Приложение работает в ориентации Lanscape (либо), и поэтому все записанное видео должно быть в альбомной ориентации.

Текущий код, который я использую перед началом записи для правильного воспроизведения видео:

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

, где videoWriterInput является экземпляром AVAssetWriterInput, и цель состоит в том, чтобы компенсировать ландшафтный режим и уважаемую ориентацию OpenGL.

Это производит видео, которое при загрузке и воспроизведении на Quicktime Player воспроизводится правильно. Однако, если я добавлю записанное видео в библиотеку фотографий iPhone, миниатюра будет отображаться правильно, но воспроизведение видео будет повернуто на 90 градусов, если телефон находится в альбомной ориентации. Если телефон находится в портретном режиме, видео воспроизводится правильно, но обрезается по горизонтали, чтобы соответствовать размерам портрета.

Согласно этой технической заметке Apple вывод захвата для AVCaptureVideoDataOutput, который я использую для обработки видеокадров, не поддерживает настройку ориентации видео.

Кто-нибудь успешно записал видео, созданное в альбомной ориентации, которое можно добавить в библиотеку iPhone и правильно воспроизводить в альбомной ориентации, и если да, то как?

Ответы [ 2 ]

11 голосов
/ 22 октября 2011

Ваше сообщение открыло мне глаза на то, как приложение «Apple Video» воспроизводит видео.Я записал несколько элементов в своем приложении с устройством в четырех направлениях.Все они воспроизводятся правильно ориентированными.Я только что заметил, что приложение «Видео» не поддерживает вращение, как проигрыватель в приложении «Фотоальбом».Приложение "Видео" ожидает, что вы будете держать устройство (по крайней мере, мой iPod touch) в альбомной ориентации.Я сделал несколько портретных записей, добавил их в iTunes, и все, включая созданную с помощью приложения Apple для камеры, не поворачивались при повороте устройства в портретную ориентацию.

В любом случае ...

Мое приложение - это приложение, работающее по промежутку времени, которое не выполняет никакой дополнительной обработки кадров, как вы, поэтому 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;

То, что deteOrientation вызывает следующий метод,Я сократил фактический код для ясности здесь.В моем приложении я также вращаю некоторые кнопки, поэтому обратите внимание, что они не получают одинаковое преобразование.На что нужно обратить внимание, так это на то, как я настраиваю ИВАР PlayTransform.

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

Это совет, который я нашел в этом SOF Q & A .

0 голосов
/ 19 января 2016

Намного проще ...

В вашем вершинном шейдере:

равномерное плавание предпочитаемое вращение; , , , mat4 вращениеMatrix = mat4 (cos (предпочитаемое вращение), -sin (предпочтительное вращение), 0,0, 0,0, sin (предпочтительное вращение), cos (предпочтительное вращение), 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);

В контроллере вида или представления, который вызывает шейдер:

if ([videoTrack statusOfValueForKey: @ ошибка "extendedTransform": nil] == AVKeyValueStatusLoaded) { CGAffineTransform предпочитаемое преобразование = [videoTrack предпочитаемый преобразование]; self.playerView.preferredRotation = -1 * atan2 (privileTransform.b, предпочитаемый Transform.a);

... и так далее ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...