亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

[iOS]關于視頻方向的若干問題

2019-11-14 18:46:03
字體:
來源:轉載
供稿:網友

版本:
OS X 10.10.5
Xcode 6.4(6E35b)
iOS >= 7 

一、MOV/MP4視頻文件中的Rotation元數據

iOS上內置相機應用錄制的mov/mp4視頻可能產生一個Rotation元數據,表示錄制視頻時攝像頭旋轉到了多少角度。其值一般為這四個:0、90、180或270。類似于圖片文件的Exif信息中的Orientation元數據。
Rotation元數據用于播放器確定渲染視頻的方向,但有的播放器會對其視而不見。稍后會測試幾種常見的播放器/播放控件對Rotation元數據的支持。
注:
實際上視頻文件的Rotation元數據并不是保存的角度值,不過如果只關心角度問題而不是圖像拉伸之類的,可以這樣簡單理解。關于如何獲取Rotation元數據角度值,有興趣的可以參看vlc的源碼。
 
下面用MediaInfo看看用iphone相機應用使用后置攝像頭錄制的兩個視頻,觀察其Rotation元數據。請留意文件名分別為IMG_1427.MOV和IMG_1428.MOV,后文也會用這兩個文件做對比。
1、使用后置攝像頭在Portrait(豎屏,Home鍵在下邊)模式時錄制的視頻,其Rotation值為90。
(圖一:Rotation值為90)
 
2、使用后置攝像頭在LandscapeRigth(橫屏,Home鍵在右邊)模式時錄制的視頻,則無Rotation元數據,或者說Rotation值為0。
(圖二:無Rotation值或者說Rotation值為0)
  
關于Rotation的0、90、180和270這四個角度值可以這樣理解:LandscapeRigth為0度;以Home鍵或攝像頭為圓心,順時針旋轉到Portrait為90度;旋轉到LandscapeLeft為180度;旋轉到PortraitUpsideDown為270度。
 
這里先在OS X 10.10.4和Windows 8上看看這兩個視頻文件的屬性:
1、將手機里的視頻文件導出到OS X,并在Finder中看預覽,兩個文件的顯示方向都是正確的。再查看Rotation值為90的IMG_1427.MOV視頻文件的屬性。顯示其尺寸為1080*1920,而不是1920*1080。但不要被這個假象欺騙了,視頻的實際尺寸還是1920*1080。最后看沒有Rotation值或者說Rotation值為0的IMG_1428.MOV視頻文件,顯示其尺寸為1920*1080,一切正常。使用QuickTime播放,能正確識別出兩個視頻的方向。
 
(圖三) 
2、在Windows資源管理器中看預覽,IMG_1427.MOV和IMG_1428.MOV的顯示方向都是正確的;再查看兩個文件的屬性,尺寸都顯示為1920*1080;使用Windows Media Player播放,能正確識別出兩個視頻的方向。

二、常見視頻播放器對方向的識別

iOS相冊調出的播放器和Win8上的Windows Media Player能夠正確識別出MOV/MP4的方向,即實際尺寸為1920*1080的、Rotation值為90的IMG_1427.MOV視頻能夠按1080*1920的尺寸并調整方向進行渲染;沒有Rotation值或者說Rotation值為0的IMG_1428.MOV視頻按1920*1080的尺寸并按實際方向進行渲染。Andriod也存在類似情況。
VLC for OS X(why?)和iOS的MPMoviePlayerViewControlle對Rotation沒有識別,它們總是按實際尺寸和默認方向進行渲染。對于MPMoviePlayerViewControlle下面有解決方案。
Safari瀏覽器調出的播放器應該也是MPMoviePlayerViewController,所以也無法正確識別方向。 

三、MPMoviePlayerViewController控制視頻方向

需要額外的參數來確定視頻的方向,然后旋轉播放器,達到各種視頻——mov/mp4/m3u8等——都可以正確播放的目的。
 
 1 //…... 2     NSString * url = @"http://www.yourdomain.com/Videos/1.m3u8"; 3     MPMoviePlayerViewController * vc = [[MPMoviePlayerViewController alloc] init]; 4     vc.moviePlayer.contentURL = [NSURL URLWithString:url]; 5     // 這里播放一個Rotation為90的視頻,即Home鍵在下錄制的視頻 6     [self rotateVideoView:vc degrees:90]; 7     [self PResentMoviePlayerViewControllerAnimated:vc]; 8     [vc.moviePlayer play]; 9  10 //…...11 - (void)rotateVideoView:(MPMoviePlayerViewController *)movePlayerViewController degrees:(NSInteger)degrees12 {13     if(degrees==0||degrees==360) return;14     if(degrees<0) degrees = (degrees % 360) + 360;15     if(degrees>360) degrees = degrees % 360;16     // MPVideoView在iOS8中Tag為1002,不排除蘋果以后更改的可能性。參考遞歸查看View層次結構的lldb命令: (lldb) po [movePlayerViewController.view recursiveDescription]17     UIView *videoView = [movePlayerViewController.view viewWithTag:1002];18     if ([videoView isKindOfClass:NSClassFromString(@"MPVideoView")]) {19         videoView.transform = CGAffineTransformMakeRotation(M_PI * degrees / 180.0);20         videoView.frame = movePlayerViewController.view.bounds;21     }22 }
View Code

改為Category:

 1 #import "MPMoviePlayerViewController+Rotation.h" 2  3 @implementation MPMoviePlayerViewController (Rotation) 4  5 - (void)rotateVideoViewWithDegrees:(NSInteger)degrees 6 { 7     if(degrees==0||degrees==360) return; 8     if(degrees<0) degrees = (degrees % 360) + 360; 9     if(degrees>360) degrees = degrees % 360;10    11     // MPVideoView在iOS8中Tag為1002,不排除蘋果以后更改的可能性。參考遞歸查看View層次結構的lldb命令: (lldb) po [movePlayerViewController.view recursiveDescription]12     UIView *videoView = [self.view viewWithTag:1002];13     if ([videoView isKindOfClass:NSClassFromString(@"MPVideoView")]) {14         videoView.transform = CGAffineTransformMakeRotation(M_PI * degrees / 180.0);15         videoView.frame = self.view.bounds;16     }17 }18 19 @end

四、HTML5控制視頻方向 

在video標簽中增加 style="-webkit-transform: rotate(90deg);” ,不過控件也被旋轉了。這就需要將默認播放控件隱藏了并且自繪控件,此略。

五、使用ffmpeg寫入Rotation元數據 

對于沒有Rotation元數據的mp4文件,可通過ffmpeg等工具寫入。比如視頻需要順時針旋轉90度顯示:
 ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=90 output.mp4 
注:
如果愿意,寫入非0、90、180或270的值,比如45之類的也是可以的。 

六、獲取視頻方向(角度) 

+ (NSUInteger)degressFromVideoFileWithURL:(NSURL *)url{    NSUInteger degress = 0;       AVAsset *asset = [AVAsset assetWithURL:url];    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];    if([tracks count] > 0) {        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];        CGAffineTransform t = videoTrack.preferredTransform;               if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){            // Portrait            degress = 90;        }else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){            // PortraitUpsideDown            degress = 270;        }else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){            // LandscapeRight            degress = 0;        }else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){            // LandscapeLeft            degress = 180;        }    }       return degress;}

七、按正確方向對視頻進行截圖

關鍵點是將AVAssetImageGrnerator對象的appliesPreferredTrackTransform屬性設置為YES。
 
 1 + (UIImage *)extractImageFromVideoFileWithUrl:(NSURL *)url 2 { 3     NSDictionary *opts = @{AVURLAssetPreferPreciseDurationAndTimingKey:@(NO)}; 4     AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:opts]; 5     AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 6     // 應用方向 7     gen.appliesPreferredTrackTransform = YES; 8     CMTime time = CMTimeMakeWithSeconds(1, 60); 9     NSError *error = nil;10     CMTime actualTime;11     CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];12     if(error)13     {14         DLog(@"%@ %@",__FUNCTION_FILE_LINE__,error);15         return nil;16     }17     UIImage *thumb = [[UIImage alloc] initWithCGImage:image];18     CGImageRelease(image);19    20     return thumb;21 } 

八、實時視頻的方向處理

使用AVFoundation制作自定義相機時,采集出來的視頻幀保存在CMSampleBufferRef結構中,顏色空間可以設置為sRGB或YUV。進行一些內存操作就可實現旋轉。以下代碼是針對YUV的。 
注:
這種涉及大量內存拷貝的操作,實際應用中要權衡其利弊。以下代碼未經過測試。
1、RGB24旋轉90度  
 1 // RGB24旋轉90度 2 void RGB24Rotate90(int8_t *des, const int8_t *src, int width, int height) 3 { 4     if(!des || !src) return; 5     6     int n = 0; 7     int linesize = width * 3; 8     int i, j; 9     // 逆時針旋轉10     for (j = width; j > 0; j--) {11         for (i = 0; i < height; i++) {12             memccpy(&des[n], &src[linesize * i + j * 3 - 3], 0, 3);13             n += 3;14         }15     }16     /*17     // 順時針旋轉18     for (j = 0 ; j < width; j++) {19         for (i = height; i > 0; i--) {20             memccpy(&des[n], &src[linesize * (i - 1) + j * 3 - 3], 0, 3);21             n += 3;22         }23     }24     */25 }
View Code

 
2、RGB24旋轉90度  
 1 // YUV420旋轉90度 2 void YUV420Rotate90(int8_t *des, const int8_t *src, int width, int height) 3 { 4     int i = 0, j = 0, n = 0; 5     int hw = width / 2, hh = height / 2; 6     7     const int8_t *ptmp = src; 8     for (j = width; j > 0; j--) { 9         for (i = 0; i < height; i++) {10             des[n++] = ptmp[width * i + j];11         }12     }13    14     ptmp = src + width * height;15     for (j = hw; j > 0; j--) {16         for (i = 0; i < hh; i++) {17             des[n++] = ptmp[hw * i + j];18         }19     }20    21     ptmp = src + width * height * 5 / 4;22     for (j = hw; j > 0; j--) {23         for (i = 0; i < hh; i++) {24             des[n++] = ptmp[hw * i + j];25         }26     }27 }
View Code

或:

 1 int8_t[] rotateYUV420Degree90(int8_t[] data, int imageWidth, int imageHeight) 2 { 3     int8_t [] yuv = new int8_t[imageWidth*imageHeight*3/2]; 4     // Rotate the Y luma 5     int i = 0; 6     for(int x = 0;x < imageWidth;x++) 7     { 8         for(int y = imageHeight-1;y >= 0;y--) 9         {10             yuv[i] = data[y*imageWidth+x];11             i++;12         }13     }14     // Rotate the U and V color components15     i = imageWidth*imageHeight*3/2-1;16     for(int x = imageWidth-1;x > 0;x=x-2)17     {18         for(int y = 0;y < imageHeight/2;y++)19         {20             yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x];21             i--;22             yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)];23             i--;24         }25     }26     return yuv;27 }
View Code

九、參考資料: 

 
 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲а∨天堂久久精品喷水| 久久天天躁狠狠躁夜夜躁2014| 日韩性xxxx爱| 亚洲成av人乱码色午夜| 国产91ⅴ在线精品免费观看| 久久国产精品久久久久久久久久| 一本色道久久88综合日韩精品| 色综合视频一区中文字幕| 青青在线视频一区二区三区| 久久久精品一区二区| 91av在线影院| 久久夜色精品国产欧美乱| 欧美xxxx综合视频| 中文字幕日韩专区| 欧美性感美女h网站在线观看免费| 亚洲欧美三级在线| 精品magnet| 91精品视频在线免费观看| 激情久久av一区av二区av三区| 91国产在线精品| 亚洲精品久久久久中文字幕二区| 日本精品免费一区二区三区| 欧美精品第一页在线播放| 久久精品国产久精国产一老狼| 亚洲乱码国产乱码精品精天堂| 国产欧美中文字幕| 欧美精品生活片| 丝袜情趣国产精品| 亚洲性线免费观看视频成熟| 97在线视频免费| 亚洲精品一区二区三区婷婷月| 日韩免费在线看| 国产成人精品最新| 中文字幕亚洲欧美日韩2019| 欧美激情一级二级| 欧美亚洲在线播放| 日韩国产精品一区| 欧美亚洲在线观看| 国产精品美女在线观看| 北条麻妃一区二区在线观看| 国产激情999| 91精品国产高清久久久久久久久| 一区二区欧美亚洲| 欧美黑人一区二区三区| 亚洲一区二区久久| 欧美日韩国产一中文字不卡| 欧美精品免费看| 欧洲永久精品大片ww免费漫画| 欧美在线xxx| 欧美精品久久一区二区| 亚洲aⅴ日韩av电影在线观看| 欧美在线性爱视频| 91精品国产高清自在线看超| 美女精品视频一区| 欧美电影免费观看电视剧大全| 亚洲缚视频在线观看| 久久中文精品视频| 亚洲区在线播放| 欧美丝袜一区二区| 欧美激情综合色综合啪啪五月| 精品国偷自产在线视频99| 国产精品视频公开费视频| 国产美女直播视频一区| 欧美日韩xxxxx| 亚洲精品小视频在线观看| 国产精品wwww| 国产欧美va欧美va香蕉在线| 国产精品嫩草影院一区二区| 国产精品视频26uuu| 久久99视频免费| 成人97在线观看视频| 91视频九色网站| 国产精品一区二区久久久久| 国产精品91久久| 久久久伊人欧美| 欧美丝袜一区二区三区| 日韩免费在线免费观看| 日韩av毛片网| 亚洲bt欧美bt日本bt| 日韩精品中文字幕在线观看| 在线播放日韩精品| 亚洲成人中文字幕| 欧美黑人性生活视频| 欧美成人精品影院| 91精品久久久久久久久| 欧美激情视频三区| 一区二区三区天堂av| 欧美中文字幕第一页| 欧美性xxxxx极品| 伊人久久男人天堂| 日韩中文在线中文网在线观看| 精品福利一区二区| 97在线视频免费看| 国产精品流白浆视频| 亚洲毛茸茸少妇高潮呻吟| 久久久伊人日本| 亚洲女人天堂色在线7777| 国产日韩欧美电影在线观看| 国产成人精品一区二区在线| 亚洲一区二区三区四区视频| 亚洲欧洲日产国码av系列天堂| 92版电视剧仙鹤神针在线观看| 中文字幕日韩av| 成人h视频在线观看播放| 5278欧美一区二区三区| 俺也去精品视频在线观看| 国产欧美最新羞羞视频在线观看| 日韩av在线高清| 一区二区中文字幕| 国产成人极品视频| 亚洲精品456在线播放狼人| 97视频在线观看网址| 亚洲激情久久久| 欧美激情欧美狂野欧美精品| 精品日韩美女的视频高清| 亚洲精品一区二区三区婷婷月| 亚洲人成电影网站色…| 97在线观看免费| 亚洲综合大片69999| 国产日本欧美一区二区三区| 久国内精品在线| 欧美另类极品videosbestfree| 国产网站欧美日韩免费精品在线观看| 午夜精品免费视频| 日韩欧美中文第一页| 自拍亚洲一区欧美另类| 亚洲成人中文字幕| 久久久久久久久久久成人| 亚洲黄色有码视频| 久久精品国产99国产精品澳门| 懂色av中文一区二区三区天美| 欧美亚洲视频在线看网址| 色综合色综合网色综合| 91久热免费在线视频| 国产精品亚发布| 亲爱的老师9免费观看全集电视剧| 96精品视频在线| 国产精品高清免费在线观看| 久久天堂电影网| 久久久免费精品视频| 国产精品自拍网| 最近2019中文字幕大全第二页| 亚洲人成电影网站色…| 国产成人精品视频在线观看| 日韩福利伦理影院免费| 日韩中文在线观看| 久热精品在线视频| 国产精自产拍久久久久久蜜| 欧美激情第99页| 欧日韩不卡在线视频| 丝袜亚洲欧美日韩综合| 色阁综合伊人av| 国产亚洲人成a一在线v站| 久久久精品国产一区二区| 久99久在线视频| 欧美理论电影在线观看| 国产亚洲欧洲黄色| 亚洲国产精品推荐| 91精品久久久久久久久中文字幕| 欧美高清videos高潮hd| 亚洲欧美中文字幕在线一区| 国产成人涩涩涩视频在线观看| 九色成人免费视频| 成人免费淫片aa视频免费|