4 Stimmen

Wie setze ich die Ausrichtung für ein frame-by-frame-generiertes Video mit AVFoundation?

Ich schreibe eine iPhone-App, die Videoaufnahmen von der Kamera macht, sie durch einige OpenGL-Shadercode laufen lässt und dann das Ergebnis in einer Videodatei unter Verwendung von AVFoundation speichert. Die App läuft im Querformat (entweder) und daher sollte das aufgenommene Video immer im Querformat sein.

Der aktuelle Code, den ich verwende, um das Video vor dem Start der Aufnahme richtig herum zu erhalten, lautet:

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

wo videoWriterInput eine Instanz von AVAssetWriterInput ist und das Ziel ist, die Landschaftsmodus und die umgekehrte Ausrichtung von OpenGL auszugleichen.

Dies erzeugt Video, das beim Herunterladen und Abspielen im Quicktime-Player korrekt wiedergegeben wird. Wenn ich das aufgenommene Video jedoch zur iPhone-Fotobibliothek hinzufüge, wird das Thumbnail korrekt angezeigt, aber das Video wird um 90 Grad gedreht abgespielt, wenn das Telefon im Querformat gehalten wird. Wenn das Telefon im Hochformat gehalten wird, wird das Video korrekt wiedergegeben, aber horizontal beschnitten, um in die Hochformatabmessungen zu passen.

Laut dieser Apple-Technote unterstützt die Erfassungsausgabe für AVCaptureVideoDataOutput, die ich für die Verarbeitung der Videoframes verwende, keine Einstellung der Videoausrichtung.

Hat jemand erfolgreich im Querformat generierte Videos aufgenommen, die zur iPhone-Bibliothek hinzugefügt wurden und im Querformat korrekt abgespielt werden, und wenn ja, wie?

0 Stimmen

Gibt es einen Grund, warum Sie in OpenGL keine Rotation durchführen können, um die richtige Orientierung zu erhalten, bevor Sie die Pixel aus dem Rahmenpuffer auslesen? Auf diese Weise müssen Sie sich nicht um die Transformation kümmern, die im Header der MOV/MP4 platziert ist. Die Standardeinstellung wird einfach funktionieren.

0 Stimmen

Vielen Dank für diese Idee. Das Problem dabei ist jedoch, dass die Live-Ansicht auf dem Bildschirm korrekt ist - die falsche Ansicht erscheint nur, wenn ich das aufgenommene Video in der iPhone-Bibliothek speichere und abspiele, selbst die Aufnahme auf dem Desktop wird korrekt wiedergegeben.

11voto

Darren Reely Punkte 485

Dein Beitrag hat mir die Augen darüber geöffnet, wie die Videos-App von Apple Videos wiedergibt. Ich habe mehrere Elemente mit meiner App in den vier Ausrichtungen aufgenommen. Sie wurden alle ordnungsgemäß wiedergegeben. Ich habe gerade festgestellt, dass die Videos-App keine Rotation unterstützt wie der Player in der Fotoalbum-App. Die Videos-App erwartet, dass du das Gerät (zumindest mein iPod touch) im Querformat hältst. Ich habe einige Porträtaufnahmen gemacht, sie zu iTunes hinzugefügt und alle, einschließlich derjenigen, die mit der Kamera-App von Apple erstellt wurden, haben sich nicht gedreht, als ich das Gerät in die Hochformatposition gedreht habe.

Wie dem auch sei...

Meine App ist eine Zeitraffer-App, die keine zusätzliche Verarbeitung der Frames wie du machst durchführt, also kann es bei folgendem Ergebnisse geben. Ich habe meine App so eingerichtet, dass sie das Fenster nicht dreht, während das Gerät gedreht wird. Auf diese Weise arbeite ich immer mit einer Ausrichtung des Geräts. Ich verwende AVFoundation, um jeden N-ten Frame aus dem Video-Stream zu erfassen und auszugeben.

Wenn ich mich für die Aufnahme bereitmache, tue ich Folgendes.

inputWriterBuffer = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo outputSettings: outputSettings];
    // Ich rufe das explizit auf, bevor die Aufnahme beginnt. Video wird richtig herum wiedergegeben.
[self detectOrientation];
inputWriterBuffer.transform = playbackTransform;

Diese detectOrientation ruft die folgende Methode auf. Ich habe den tatsächlichen Code hier zur Klarheit reduziert. In meiner App drehe ich auch einige Schaltflächen, also achte darauf, dass sie nicht die gleiche Transformation erhalten. Worauf du achten solltest, ist, wie ich das PlaybackTransform ivar einrichte.

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

        // Transformation hängt davon ab, welche Kamera das Video liefert
        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];

        // Transformation hängt davon ab, welche Kamera das Video liefert
        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 ); // Verwende die Standardrotation, obwohl wahrscheinlich andere Probleme auftreten, wenn wir hierhin kommen.
        break;
}
}

Als Randnotiz, da ich möchte, dass die Methode aufgerufen wird, wann immer das Gerät gedreht wird, und ich die automatische Rotation ausgeschaltet habe, habe ich folgendes in meiner viewDidLoad-Methode.

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

Das ist ein Tipp, den ich in dieser SOF-Frage und -Antwort gefunden habe.

0 Stimmen

Diese Antwort führte tatsächlich zu der richtigen Antwort für meine App. Für OpenGL-transformiertes Video musste ich immer noch einen Maßstab anwenden, um das Video umzukehren, aber der Schlüsselerkenntnis war, dass ich um -M_PI drehen musste, nicht um M_PI. Danke!

0voto

James Bush Punkte 1457

Vielseitiger...

In deinem Vertex-Shader:

uniform float bevorzugteRotation; . . . mat4 rotationsmatrix = mat4( cos(bevorzugteRotation), -sin(bevorzugteRotation), 0.0, 0.0, sin(bevorzugteRotation), cos(bevorzugteRotation), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);

/* 90-Grade
mat4 rotationsmatrix = mat4( cos(bevorzugteRotation), -sin(bevorzugteRotation), (1.0 - cos(bevorzugteRotation)) - sin(bevorzugteRotation), 0.0,
                           -sin(bevorzugteRotation),  cos(bevorzugteRotation), 0.0, 0.0,
                           0.0,                     0.0, 1.0, 0.0,
                           0.0,                     0.0, 0.0, 1.0);

In der Ansicht oder im Ansichtscontroller, der den Shader aufruft:

if ([videoTrack statusOfValueForKey:@"preferredTransform" error:nil] == AVKeyValueStatusLoaded) { CGAffineTransform bevorzugterTransform = [videoTrack preferredTransform]; self.playerView.preferredRotation = -1 * atan2(bevorzugterTransform.b, bevorzugterTransform.a);

...und so weiter...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X