相機方向的驅動程序支援
重要
本主題稍後討論的自動更正方法是相機感測器非參考方向掛接 的建議 解決方案。 這是為了確保應用程式相容性,因為大部分已寫入以使用相機摘要的應用程式不知道要檢查,也不會更正旋轉資訊。 請仔細檢閱下方自動更正一節中的資訊。
引進不同的尺寸規格運算裝置時,某些實體條件約束會導致相機感測器以非傳統方向掛接。 因此,您必須適當地描述 OS 和應用程式,如何掛接感測器,以便正確轉譯/錄製產生的視訊。
從 Window 10 版本 1607 開始,不論相機是否根據 最低硬體需求掛接,所有相機驅動程式都必須明確指定相機方向。 具體而言,相機驅動程式必須在與擷取裝置介面相關聯的 ACPI _PLD 結構中設定新引進的字段 [旋轉]:
typedef struct _ACPI_PLD_V2_BUFFER {
UINT32 Revision:7;
UINT32 IgnoreColor:1;
UINT32 Color:24;
// …
UINT32 Panel:3; // Already supported by camera.
// …
UINT32 CardCageNumber:8;
UINT32 Reference:1;
UINT32 Rotation:4; // 0 – Rotate by 0° clockwise
// 1 – Rotate by 45° clockwise (N/A to camera)
// 2 – Rotate by 90° clockwise
// 3 – Rotate by 135° clockwise (N/A to camera)
// 4 – Rotate by 180° clockwise
// 5 – Rotate by 225° clockwise (N/A to camera)
// 6 – Rotate by 270° clockwise
UINT32 Order:5;
UINT32 Reserved:4;
//
// _PLD v2 definition fields.
//
USHORT VerticalOffset;
USHORT HorizontalOffset;
} ACPI_PLD_V2_BUFFER, *PACPI_PLD_V2_BUFFER;
對於相機,ACPI _PLD 結構的 旋轉 欄位會指定 0° ('0' 的度數、90°的 '2'、180°的 '4',而 270° 的 '6') 擷取的畫面會相對於螢幕旋轉,而顯示器則為原生方向。
根據 [旋轉 ] 欄位中的值,應用程式可以視需要執行額外的旋轉,以便正確轉譯擷取的畫面格。
旋轉值
對於相機和顯示器共用相同房屋 (或 機箱/大小 寫) 的裝置,可以讓這些周邊掛接在不同的介面上,每個周邊都會由固定但任意度在其各自的平面上旋轉。 因此,應用程式需要一個機制來描述兩個周邊之間的空間關聯性,讓擷取的框架可以轉置到正確方向的轉譯介面上。
解決此問題的其中一種方法是使用 ACPI _PLD 結構,其已經定義 表面 和 旋轉程度 的概念。 例如,_PLD 結構已經有 面板 欄位,可指定周邊所在的介面:
ACPI _PLD Panel 字段的定義 (Rev. 5.0a)
接下來的兩個圖表會以可視化方式說明每個面板的定義:
桌面電腦和大部分裝置的面板定義
可折疊裝置的面板定義
事實上,WINDOWS 已採用 ACPI「面板」的概念,其中:
如果擷取裝置以靜態方式掛接在固定位置,相機裝置介面會與_PLD結構相關聯,並據以設定 Panel 字段。
應用程式可以藉由呼叫 Windows.Devices.Enumeration.DeviceInformation.EnclosureLocation.Panel 屬性來擷取擷取裝置所在的面板。
ACPI _PLD 結構也有定義如下的 [旋轉] 欄位:
ACPI _PLD 旋轉欄位的定義 (Rev 5.0a)
我們會進一步精簡上述定義,以避免模棱兩可:
- 若為相機,ACPI _PLD 結構的旋轉欄位會指定 0° ('0' 的度數、90°的 '2'、180°的 '4',而 270° 的 '6') 撷取的畫面會相對於螢幕旋轉,而顯示器則為原生方向。
橫向主要與直向主要
在 Windows 中,您可以藉由呼叫 屬性 Windows.Graphics.Display.DisplayInformation.NativeOrientation 來查詢原生顯示方向,這會傳回 Landscape 或 Portrait:
無論您傳回哪個 值 NativeOrientation ,邏輯顯示器掃描模式都會從從左至右向下行動的顯示器左上角開始, (請參閱圖 5) 。 對於默認實體方向為不重複的裝置,此屬性不僅表示ACPI Top 面板的位置,也提供相機輸出緩衝區與轉譯介面之間的空間關聯性。
請注意,與相機不同, NativeOrientation 屬性不是以 ACPI 為基礎,因此沒有_PLD結構。 即使顯示器以靜態方式掛接至裝置,也是如此。
在直向主要裝置上掛接時,相機驅動程式必須注意,大部分的應用程式都會將裝置視為輸出橫向相機輸出緩衝區,而不論實際的相機輸出緩衝區方向為何。 因此,我們建議相機驅動程式在直向主要裝置上時,輸出與 NativeOrientation Portrait 有 90 度方向位移的相機緩衝區。 然後,這可讓在直向裝置上執行此額外旋轉的應用程式,以將旋轉更正為預期的方向。 這可以使用 相機應用程式搭配旋轉範例進行驗證。
位移掛接
強烈建議 IHV/OEM 避免在非 0 度位移中掛接感測器,以維持應用程式相容性。 許多現有和舊版應用程式不知道要尋找 ACPI 的 PLD 數據表,也不會嘗試更正非 0 度位移。 因此,針對這類應用程式,產生的視訊會轉譯不正確。
如果 IHV/OEM 無法以 0 度方向掛接感測器,如上所述,建議依照喜好設定順序執行下列風險降低步驟:
使用AV串流迷你埠驅動程式或在使用者模式中使用裝置MFT或 MFT) 0 等外掛程式,自動更正數位相機 (驅動程式內非 0 度方向,讓產生的輸出畫面處於 0 度方向。
透過 FSSensorOrientation 標籤宣告非 0 度方向,讓相機管線可以更正擷取的影像。
如上所述,在 ACPI 的 PLD 數據表中宣告非 0 度方向。
壓縮/編碼媒體類型
對於壓縮和/或編碼媒體類型 (,例如 MJPG、JPEG、H264、HEVC) ,無法使用管線更正。 因此,如果 FSSensorOrientation 設定為非零值,則會篩選掉壓縮/編碼的媒體類型。
在 MJPG 媒體類型 (例如來自 UVC 相機) 的媒體類型的情況下,Frame Server 管線會針對 DShow 型應用程式提供自動譯碼媒體類型 (NV12 或 YUY2) 。 系統會顯示自動譯碼和更正的媒體類型,但原始的 MJPG 格式將不會顯示。
[!注意!] 如果壓縮/編碼媒體類型必須公開給應用程式,IHV/ODM 不得利用 FSSensorOrientation 修正。 相反地,相機驅動程式必須透過AV Stream驅動程式或透過 DMFT/MFT0) 在核心模式中 (更正。
透過AV Stream Miniport/Device MFT/MFT0 自動更正
如果感測器無法以 0 度位移掛接,建議的案例是讓 AV Stream 迷你埠驅動程式 (或使用者模式外掛程式以 DMFT 或 MFT0 的形式插入,) 更正產生的擷取框架,使其在 0 度位移中公開至管線。
從 AV Stream Miniport 和/或 Device MFT/MFT0 外掛程式更正視訊畫面時,產生的媒體類型宣告必須以更正的畫面為基礎。 如果感測器以90度位移掛接,因此產生的視訊是感測器的9:16外觀比例,但更正的視訊會是16:9,媒體類型必須宣告16:9的外觀比例。
這包括產生的步進資訊。 這是必要的,因為負責進行更正的元件是由 IHV/OEM 所控制,而且相機管線無法看見視訊畫面,但修正之後除外。
強烈建議您在使用者模式中完成更正,而且必須遵循管線與使用者模式外掛程式之間的 API 合約。 具體而言,使用 DMFT 或 MFT0 時,當 IMFDeviceTransform::P rocessMessage 或 IMFTransform::P rocessMessage 使用MFT_MESSAGE_SET_D3D_MANAGER訊息叫用時,使用者模式外掛程式必須遵循下列指導方針:
- 如果未提供 D3D 管理員 (訊息的 ulParam 為 0) ,則使用者模式外掛程式不得叫用任何 GPU 作業來處理旋轉更正。 而且產生的框架必須在系統記憶體中提供。
- 如果提供 D3D 管理員 (訊息的 ulParam 是 DXGI 管理員的 IUnknown) ,則 DXGI 管理員必須用於旋轉修正,且產生的畫面必須是 GPU 記憶體。
- 使用者模式外掛程式也必須在運行時間期間處理 D3D 管理員訊息。 發出MFT_MESSAGE_SET_D3D_MANAGER訊息時,外掛程式所產生的下一個畫面格必須對應至要求的記憶體類型 (,亦即如果提供 DXGI 管理員,則 GPU,否則為 CPU) 。
- 當AV Stream驅動程式 (或使用者模式外掛程式) 處理旋轉修正時,ACPI的 PLD 結構的 [旋轉] 字段必須設定為 0。
注意
使用 [自動更正] 時,OEM 和 IHD 不得透過 [_PLD 旋轉 ] 欄位公告感測器的實際方向。 在此情況下, [旋轉 ] 字段必須指出校正之後的方向:0 度。
透過 FSSensorOrientation 宣告
; Defines the sensor mounting orientation offset angle in
; degrees clockwise.
FSSensorOrientation: REG_DWORD: 90, 180, 270
藉由透過 FSSensorOrientation 登錄標籤宣告感測器的非 0 度方向,相機管線可以修正所擷取的畫面,再向應用程式呈現它。
管線會根據使用案例和應用程式要求/案例,利用 GPU 或 CPU 資源來優化旋轉邏輯。
ACPI PLD 旋轉
ACPI PLD 結構的 [旋轉] 字段必須是 0。 這是為了避免使用 PLD 資訊來更正框架的混淆應用程式。
媒體類型資訊
驅動程式呈現的媒體類型必須是未更正的媒體類型。 使用 FSSensorOrientation 專案通知相機管線非 0 度位移時,感測器呈現的媒體類型信息必須是未更正的媒體類型。 例如,如果感測器掛接 90 度順時針位移,因此,而不是 16:9 外觀比例,產生的視訊為 9:16,9:16 外觀比例媒體類型必須呈現給相機管線。
這是確保管線可以正確設定計數器輪替程式的必要條件:管線需要輸入媒體類型和應用程式所需的輸出媒體類型。
這包括步進資訊。 對於相機管線的未更正媒體類型,必須顯示跨步資訊。
登錄子機碼
FSSensorOrientation 登錄項目必須在 [裝置介面] 節點上發佈。 建議的方法是在數位相機驅動程式 INF 的 AddInterface 指示詞宣告期間,將此宣告為 AddReg 指示詞。
FSSensorOrientation 中顯示的數據必須是REG_DWORD,且唯一接受的有效值為 90、180 和 270。 任何其他值都會被視為 0 度位移 (,也就是忽略) 。
每個值都以順時針方向表示感測器方向。 相機管線會藉由逆時針旋轉視訊的計數器來更正產生的視訊畫面:亦即,90 度順時針宣告會導致 90 度逆時針旋轉,讓產生的視訊畫面回到 0 度位移。
MS OS 描述元 1.0
針對USB型相機,FSSensorOrientation也可以透過 MSOS 描述元發佈。
MS OS 描述項 1.0 有兩個元件:
- 固定長度標頭區段
- 一或多個可變長度的自定義屬性區段,其遵循標頭區段
MS OS DESCRIPTOR 1.0 標頭區段
標頭區段描述臉部驗證配置檔) (單一自定義屬性。
Offset | 欄位 | 大小 (位元組) | 值 | 描述 |
---|---|---|---|---|
0 | dwLength | 4 | <> | |
4 | bcdVersion | 2 | 0x0100 | 版本 1.0 |
6 | wIndex | 2 | 0x0005 | 擴充屬性OS描述項 |
8 | wCount | 2 | 0x0001 | 一個自定義屬性 |
自定義 MS OS DESCRIPTOR 1.0 屬性區段
Offset | 欄位 | 大小 (位元組) | 值 | 描述 |
---|---|---|---|---|
0 | dwSize | 4 | 0x00000036 (54) | 此屬性的大小總計 (以位元組為單位) 。 |
4 | dwPropertyDataType | 4 | 0x00000004 | REG_DWORD_LITTLE_ENDIAN |
8 | wPropertyNameLength | 2 | 0x00000024 (36) | 屬性名稱) 以位元組為單位的大小 (。 |
10 | bPropertyName | 50 | UVC-FSSensorOrientation | Unicode 中的 “UVC-FSSensorOrientation” 字串。 |
60 | dwPropertyDataLength | 4 | 0x00000004 | 屬性數據 (sizeof (DWORD) ) 的 4 個字節。 |
64 | bPropertyData | 4 | 順時針以度為單位的位移角度。 | 有效值為 90、180 和 270。 |
MS OS 描述元 2.0
MSOS 擴充描述元 2.0 可用來定義登錄值,以新增 FSSensorOrientation 支援。 這是使用 Microsoft OS 2.0 登錄屬性描述元來完成。
針對 UVC-FSSensorOrientation 登錄專案,下列範例顯示 MSOS 2.0 描述項集:
UCHAR Example2_MSOS20DescriptorSet_UVCFSSensorOrientationForFutureWindows[0x3C] =
{
//
// Microsoft OS 2.0 Descriptor Set Header
//
0x0A, 0x00, // wLength - 10 bytes
0x00, 0x00, // MSOS20_SET_HEADER_DESCRIPTOR
0x00, 0x00, 0x0?, 0x06, // dwWindowsVersion – 0x060?0000 for future Windows version
0x4A, 0x00, // wTotalLength – 74 bytes
//
// Microsoft OS 2.0 Registry Value Feature Descriptor
//
0x40, 0x00, // wLength - 64 bytes
0x04, 0x00, // wDescriptorType – 4 for Registry Property
0x04, 0x00, // wPropertyDataType - 4 for REG_DWORD_LITTLE_ENDIAN
0x32, 0x00, // wPropertyNameLength – 50 bytes
0x55, 0x00, 0x56, 0x00, // Property Name - "UVC-FSSensorOrientation"
0x43, 0x00, 0x2D, 0x00,
0x46, 0x00, 0x53, 0x00,
0x53, 0x00, 0x65, 0x00,
0x6E, 0x00, 0x73, 0x00,
0x6F, 0x00, 0x72, 0x00,
0x4F, 0x00, 0x72, 0x00,
0x69, 0x00, 0x65, 0x00,
0x6E, 0x00, 0x74, 0x00,
0x61, 0x00, 0x74, 0x00,
0x69, 0x00, 0x6F, 0x00,
0x6E, 0x00, 0x00, 0x00,
0x00, 0x00,
0x04, 0x00, // wPropertyDataLength – 4 bytes
0x5A, 0x00, 0x00, 0x00 // PropertyData – 0x0000005A (90 degrees offset)
}
透過 ACPI PLD 資訊宣告
作為最後一個選擇,可以如上所述利用 PLD 資訊,向應用程式指出必須先更正視訊畫面,才能轉譯/編碼。 不過,如前所述,許多現有的應用程式不會使用 PLD 資訊,也不會處理畫面旋轉,因此在某些情況下,應用程式可能無法正確轉譯產生的視訊。
下圖說明每個硬體組態_PLD輪替欄位的值:
旋轉:順時針方向0度
在上圖中:
左側圖片說明要擷取的場景。
中間的圖片描述由實體讀出順序從左下角向右往上移動的 URL 感測器如何檢視場景。
右邊的圖片代表相機驅動程序的輸出。 在此範例中,可以直接轉譯媒體緩衝區的內容,而顯示器是其原生方向,而不需要額外的旋轉。 因此,ACPI _PLD Rotation 欄位的值為 0。
旋轉:順時針旋轉 90 度
在此情況下,相較於原始場景,媒體緩衝區的內容會順時針旋轉 90 度。 因此,ACPI _PLD Rotation 欄位的值為 2。
旋轉:順時針 180 度
在此情況下,相較於原始場景,媒體緩衝區的內容會順時針旋轉 180 度。 因此,ACPI _PLD [旋轉] 欄位的值為 4。
旋轉:順時針方向 270 度
在此情況下,相較於原始場景,媒體緩衝區的內容會順時針旋轉 270 度。 因此,ACPI _PLD [旋轉] 欄位的值為 6。