2011-10-08 46 views
3

我正在寫一個iPhone應用程序,它從攝像頭獲取視頻,通過一些OpenGL着色器代碼運行它,然後使用AVFoundation將輸出寫入視頻文件。該應用程序以lanscape方向(或者)運行,因此所有記錄的視頻都應該是橫向的。如何使用AVFoundation設置逐幀生成視頻的方向?

當前的代碼我開始錄音,以獲得該視頻的正確的方式是使用前:

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

其中videoWriterInput是AVAssetWriterInput一個實例,目的是彌補風景模式和reveresed方向的OpenGL。

這會產生在Quicktime播放器下載並播放時播放正確的視頻。但是,如果我將錄製的視頻添加到iPhone照片庫,則縮略圖可以正確顯示,但如果手機處於橫向模式,則視頻播放會旋轉90度。如果手機保持縱向顯示,則視頻播放正確,但會水平裁剪以適應縱向尺寸。

根據this Apple tech note我用於處理視頻幀的AVCaptureVideoDataOutput的捕獲輸出不支持設置視頻方向。

是否有人成功錄製了橫向生成的視頻,這些視頻可以添加到iPhone庫並在橫向上正確播放,如果是這樣的話?

+0

是否有任何理由,你不能這樣做在OpenGL旋轉讀出像素的幀緩衝區之前,以獲得正確的方向?這樣您就不必擔心放在MOV/MP4標題中的變換。默認會正常工作。 –

+0

感謝這個想法。然而問題在於屏幕上的實時視圖是正確的 - 只有將錄製的視頻保存到iPhone庫並播放它,甚至在桌面上正確播放錄音,纔會顯示錯誤的視圖。 – domgblackwell

回答

9

您的文章打開了我的眼睛,關於Apples Videos應用程序如何播放視頻。我用這個設備在四個方向上記錄了幾個項目。他們都回放得很好。我只注意到視頻應用不支持像Photos Album應用中的播放器那樣的旋轉。視頻應用程序希望您將設備(至少是我的iPod touch)橫向放置。我做了一些肖像錄音,將它們添加到iTunes中,包括使用Apple相機應用程序創建的所有內容在將設備旋轉到縱向時都不旋轉。

反正...

我的應用程序是一個時間的推移應用程序,不會做框架的任何額外的處理就像你正在做的,所以因人而異放在下面。我設置了我的應用程序,以便在設備旋轉時不會旋轉窗口。這樣我總是處理設備的一個方向。我使用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 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方法如下。

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

這是我在this SOF Q&A中發現的提示。

+0

這個答案確實導致了我的應用程序的正確答案。對於OpenGL轉換後的視頻,我仍然需要應用比例來翻轉視頻,但關鍵的洞察是我需要通過-M_PI旋轉而不是M_PI。謝謝! – domgblackwell

+0

不客氣。 –

0

很簡單...

在您的頂點着色器中:

uniform float preferredRotation; 。 。 。 MAT4 rotationMatrix = MAT4(COS(preferredRotation)-sin(preferredRotation),0.0,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);

/* 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); 

在調用該着色器中的視圖或視圖控制器:

如果([videoTrack statusOfValueForKey:@ 「preferredTransform」 錯誤:無] == AVKeyValueStatusLoaded){ CGAffineTransform preferredTransform = [videoTrack preferredTransform]; self.playerView.preferredRotation = -1 * atan2(preferredTransform.b,preferredTransform.a);

...等等...