1. 程式人生 > >Android音視訊學習——Camera2官方demo解析(1)

Android音視訊學習——Camera2官方demo解析(1)

本篇內容主要解決螢幕旋轉和Surface旋轉之間的關係,使相機的預覽畫面與螢幕旋轉方向一致。

在官方demo的開始,定義了一個SparseIntArray,用來儲存螢幕旋轉的key和value:

private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

接著是static語句塊,用來初始化這個SparseIntArray

static {
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION
_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); }

可以說一開始就懵逼了,這還咋看下去啊!不急,有請Log和大神來幫忙。

在進行capture的時候有這樣一段程式碼:

// ①
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));

// ②
private int getOrientation(int rotation) { // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X) // We have to take that into account and rotate JPEG properly. // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS. // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360; } // ③ mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

其中getRotation()在API文件中的描述如下:

Returns the rotation of the screen from its "natural" orientation. The returned value may be Surface.ROTATION_0 (no rotation), Surface.ROTATION_90, Surface.ROTATION_180, or Surface.ROTATION_270. For example, if a device has a naturally tall screen, and the user has turned it on its side to go into a landscape orientation, the value returned here may be either Surface.ROTATION_90 or Surface.ROTATION_270 depending on the direction it was turned. The angle is the rotation of the drawn graphics on the screen, which is the opposite direction of the physical rotation of the device. For example, if the device is rotated 90 degrees counter-clockwise, to compensate rendering will be rotated by 90 degrees clockwise and thus the returned value here will be Surface.ROTATION_90.

簡單翻譯一下:

該方法返回的是當前螢幕相對於“自然方向的旋轉角度”,所謂的自然方向就是:手機豎屏,平板橫屏。返回值是上面列舉的四種。例如,如果一個裝置自然方向是豎屏,當將其橫向放置的時候,返回值要麼是Surface.ROTATION_90,或者Surface.ROTATION_270,取決於順逆時針的轉動。

此外,螢幕上繪圖的角度旋轉與物理裝置的旋轉方向正好相反,例如,如果裝置相對於自然方向逆時針旋轉90度,那麼繪圖需要順時針旋轉90度才能保證彌補渲染的改變,即返回值是Surface.ROTATION_90

以上這點大家可以開啟相簿,旋轉屏幕後對比前後兩張圖片,就能看出旋轉方向的差異。比如我將手機螢幕豎立正對著我,通過Log可以看出,當向自己的左邊旋轉手機時,rotation返回為1,也即Surface.ROTATION_90,向右邊旋轉就是3,對應Surface.ROTATION_270

在①程式碼中,獲得了rotation就可以對預覽的圖片進行旋轉,旋轉方法位於②方法中。

在②中,mSensorOrientation變數是由③程式碼獲得的,代表的是當前影象感測器(Image Sensor)的取景方向,有90度和270度兩種,如果是90度,那麼程式碼化簡以後就是ORIENTATIONS.get(rotation),如果是270度,那麼化簡以後的效果就是將JPEG旋轉180度。

下面主要分析ORIENTATIONS.get(rotation),這裡是讓螢幕旋轉方向和相機預覽方向一致的關鍵。

由於Android廠商的底層改動不同,各個機器的版本配置也不全相同,所以上述的90度和270度不能一一列舉,下面僅借MI3的機器來舉例子。以下內容借鑑自Android相機角度問題

前面提到的Sensor被安裝到手機上,就有一個預設的取景方向了,並且不會改變,座標原點位於手機橫放時的左上角,可以通過cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)獲取Sensor的安裝角度,如下圖:

這裡寫圖片描述

比如MI3手機的螢幕“自然”方向和後置相機的影象感測器方向如下圖:

這裡寫圖片描述

可以看出兩個座標系旋轉90度就能變成了對方。

當手機為橫屏時,兩座標系重合,此時相機的預覽方向和最終的拍照方向一致,圖片是“正確”的,但是若手機為豎屏,兩座標系相差90度,而拍照方向依然為Sensor的方向,也就是橫屏方向,由於手機上的照相應用做了處理,如果是未處理的狀態,照出的相片會顯示成橫屏的模樣,等價於逆時針旋轉了90度,如果要正常顯示就要順時針旋轉90度,如下圖:

這裡寫圖片描述

這裡寫圖片描述

再附上兩張實物照片,左邊是橫屏拍攝,右邊是豎屏拍攝後未通過相機處理的照片:

這裡寫圖片描述

通過查閱文件可知,CaptureRequest.JPEG_ORIENTATION的值是針對順時針旋轉而言的,所以恰好滿足順時針旋轉90度的要求。

到這裡也就知道了為什麼要在靜態語句塊中設定不同的旋轉方向了,按照上面的分析舉個簡單的例子加深印象:

比如先將手機面向自己逆時針旋轉90度,程式碼塊①中的rotation值為Surface.ROTATION_90,進入程式碼塊②,由於是後置攝像頭,Sensor的安裝方向為自然方向逆時針旋轉90度,mSensorOrientation的值為90,也就直接呼叫ORIENTATIONS.get(rotation),獲取的值為0,也就是相片不需要旋轉,其他情況類似。

相關推薦

Android視訊學習——Camera2官方demo解析1

本篇內容主要解決螢幕旋轉和Surface旋轉之間的關係,使相機的預覽畫面與螢幕旋轉方向一致。 在官方demo的開始,定義了一個SparseIntArray,用來儲存螢幕旋轉的key和value: private static final Sparse

Android視訊學習——Camera2官方demo解析2

本篇主要就幾個關鍵的類進行解釋,並且對需要注意的點註釋,此外再總結一下如何使用Camera2進行拍照和預覽的流程。附上官方demo。 上面是Camera2的流程示意圖,由於我喜歡從整體思路上分析程式碼,所以下面先就整個呆萌的思路拓展一下。 首先肯

Android FM模組學習之四原始碼解析

     由於最近一直忙專案,沒有時間來更新文件,今天抽空來寫一點,希望大家可以學習使用!      這一章當然還是來分析FM模組的原始碼。FmReceiver.java publicFmReceiver(String devicePath,FmRxEvCallbacks

Android FM模組學習之四原始碼解析

     我今天想分享的是FM模組的儲存方法,即FmSharedPreferences.java FmSharedPreferences(Context context)在構造方法中載入Load()方法, public void  Load(){       Log.d(

Android FM模組學習之四原始碼解析

  前一章我們瞭解了FM手動調頻,接下來我們要分析FM模組用到的原始碼。此原始碼是基於高通平臺的,別的平臺都大同小異,只不過是平臺自己作了些小改動而已。    首先要看的當然是主activity,

Android視訊】TS流資料解析和Jni2Java回撥

為了解析傳輸到手機的TS流有效視訊資料,進行預覽播放和錄製等功能,在網上看到的部分關於android播放TS流,如UDP預覽播放,採取的方式真是夠標新立異,如通過儲存到本地ts檔案然後播放,會有閃屏現象等,當然也有很多的播放器支援播放,如ffmepg-and

Android視訊(一) Camera2 API採集資料

這是Android音視訊的第一篇文章,終於回到了我的老本行上。之前好像從來沒有做過Camera相關的開發,這塊對我來說還是有點陌生,所以從頭開始學起。 Camera2 在Android API21中Google釋出了Camera2來取代原本的Camera,兩者的變動也是比較大的。 Ca

Android視訊學習第4章:視訊直播實現之推送視訊

H.264標準學習 1.H264編碼框架 H264碼流檔案分為兩層: (1) VCL(Video Coding Layer)視訊編碼層: 負責高效的視訊內容表示,VCL 資料即編碼處理的輸出,它表示被壓縮編碼後的視訊資料序列。 (2)

Android框架---Google官方Gson解析

Gson(又稱Google Gson)是Google公司釋出的一個開放原始碼的Java庫,主要用途為序列化Java物件為JSON字串,或反序列化JSON字串成Java物件。 而JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式,

Android自助餐】Handler訊息機制完全解析MessageQueue的佇列管理

Android自助餐Handler訊息機制完全解析(二)MessageQueue的佇列管理 Android自助餐Handler訊息機制完全解析二MessageQueue的佇列管理 新增到訊息佇列enqueueMessage 從佇

Android自助餐】Handler訊息機制完全解析鳥瞰與總結

Android自助餐Handler訊息機制完全解析(五)鳥瞰與總結 Android自助餐Handler訊息機制完全解析五鳥瞰與總結 Message MessageQueue Handler Looper

Android自助餐】Handler訊息機制完全解析Looper解析

Android自助餐Handler訊息機制完全解析(四)Looper解析 Android自助餐Handler訊息機制完全解析四Looper解析 Looper 初始化prepare 提供loope

pytorch學習_官方turtorial理解

一、處理各型別資料的一些python packages Generally, when you have to deal with image, text, audio or video data, you can use standard python pac

Android 開源框架Universal-Image-Loader完全解析--- 基本介紹及使用

                大家好!差不多兩個來月沒有寫文章了,前段時間也是在忙換工作的事,準備筆試面試什麼的事情,現在新工作找好了,新工作自己也比較滿意,唯一遺憾的就是自己要去一個新的城市,新的環境新的開始,希望自己能儘快的適應新環境,現在在準備交接的事情,自己也有一些時間了,所以就繼續給大家分享And

Android網路框架:OKHttp原始碼簡單解析

這是第一次解析原始碼並把它寫出來,在之前,我一直以為只要會用別人的輪子就好,做出實際的效果就行,對看原始碼對自己的能力提升不以為然。後來偶然聽到一句話:看別人的DEMO,你就可以會用輪子,但是要想用好輪子,還是得看原始碼。我覺得看原始碼有兩個方面的好處: 1

Deep Learning學習 之 CNN程式碼解析MATLAB

MATLAB實現CNN一般會用到deepLearnToolbox-master。但是根據Git上面的說明,現在已經停止更新了,而且有很多功能也不太能夠支援,具體的請大家自習看一看Git中的README。 deepLearnToolbox-master是一個深度

pytorch學習_官方tutorial理解

一、What is pytorch?(兩點note) 1.1 Any operation that mutates a tensor in-place is post-fixed with an . For example: x.copy(y), x.t_(),

視訊開發——音訊流解碼播放

iOS音視訊開發相關文章: 在iOS中,Core Audio提供的一套軟體介面來處理音訊,支援錄音、播放、聲音效果、格式轉換、檔案流解析等。現在常用的場景是網路傳輸過來的音訊流播放,在Core Audio中,可以使用Audio Queue或者OpenAL實現。

Android 開源框架Universal-Image-Loader完全解析--- 圖片快取策略詳解

本篇文章繼續為大家介紹Universal-Image-Loader這個開源的圖片載入框架,介紹的是圖片快取策略方面的,如果大家對這個開源框架的使用還不瞭解,大家可以看看我之前寫的一篇文章Android 開源框架Universal-Image-Loader完全解析(一)---

Android N App分屏模式完全解析

在上篇中,介紹了什麼是App分屏模式,以及如何設定我們的App來進入分屏模式。這次我們看一下,作為開發者,我們應該如何讓自己的App進入分屏模式,當App進入分屏模式時,我們注意哪些問題。 簡單地說,我認為除了保證分屏時App功能、效能正常以外,我們需要重點學習 如何在分屏模式下開啟新的Activity 以