カメラの向きに対するドライバーのサポート
重要
このトピックで後述する自動修正方法は、カメラ センサーの 非参照方向マウントに推奨される ソリューションです。 これは、カメラ フィードを使用するように既に記述されているアプリケーションの大半は、回転情報をチェックする方法も、それを修正する方法も知らないため、アプリの互換性を確保するためです。 以下の自動修正セクションの情報を注意深くご確認してください。
さまざまなフォーム ファクター コンピューティング デバイスが導入されると、いくつかの物理的制約により、カメラ センサーが従来とは異なる向きでマウントされます。 このため、OS とアプリケーションに対してセンサーのマウント方法を適切に説明し、その結果のビデオを適切にレンダリングまたは記録できるようにする必要があります。
Windows 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') を指定します。
回転 フィールドの値に基づいて、必要に応じてアプリケーションは追加の回転を実行して、キャプチャされたフレームを正しくレンダリングできます。
回転値
カメラとディスプレイが同じハウジング (またはエンクロージャ/ケース) を共有するデバイスの場合、これらの周辺機器を表面に取り付け、それぞれの平面上で固定された任意の角度で回転させることができます。 そのため、アプリケーションは、キャプチャされたフレームを正しい向きでレンダリング サーフェイスに転置できるように、2 つの周辺機器間の空間関係を記述するメカニズムが必要です。
この問題を解決する 1 つの方法は、サーフェスと回転度の概念が既に定義されている ACPI _PLD構造を使用することです。 例えば、_PLD構造体には、既に パネル フィールドがあり、周辺機器が存在するサーフェスを指定します。
ACPI _PLD パネル フィールドの定義 (Rev. 5.0a)
次の 2 つの図は、各パネルの定義を視覚的に示しています。
デスクトップ PC およびほとんどのデバイスのパネル定義
折り畳み式デバイスのパネル定義
実際、ACPI の 「パネル」 の概念は、既にWindows によって既に採用されており、以下のようになっています。
カメラ デバイス インターフェイスは、キャプチャ デバイスが固定された場所に静的にマウントされている場合に、 Panel フィールド適切に設定された_PLD構造と関連付けられます。
アプリケーションは、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 を呼び出してネイティブ表示の向きを照会できます。このプロパティは、横向きまたは縦向きのいずれかを返します。
NativeOrientation が返す値に関係なく、論理ディスプレイ スキャン パターンは、ディスプレイの左上隅から始まり、左から右に下に移動して開始します (図 5 を参照)。 既定の物理的なデフォルトの向きが明示されていないデバイスの場合、このプロパティは ACPI トップ パネルの位置を意味するだけでなく、カメラ出力バッファーとレンダリング サーフェイスの間の空間関係も提供します。
カメラとは異なり、 NativeOrientation プロパティは ACPI に基づいていないため、_PLD構造を持たないことにご注意ください。 このことは、ディスプレイがデバイスに静的にマウントされている場合でも当てはまります。
Portrait Primary デバイスにマウントする場合、カメラ ドライバーは、実際のカメラ出力バッファーの向きに関係なく、ほとんどのアプリケーションを横向きのカメラを出力バッファーの出力として処理することに注意する必要があります。 このため、縦向き Primary デバイス上で、カメラドライバーが NativeOrientation 縦向きから 90 度の向きオフセットを持つカメラ バッファーを出力することをお勧めします。 これにより、縦向きデバイスでこの追加の回転を実行しているアプリケーションは、回転を予想される向きに修正できるようになります。 これは、カメラ アプリケーションと回転 サンプル を使用して確認できます。
オフセット マウント
IHV/OEM は、アプリの互換性を維持するために、センサーを 0 度以外のオフセットでマウントすることを避けることを強くお勧めします。 多くの既存およびレガシ アプリは、ACPI の PLD テーブルを検索することを知らず、また、0 度以外のオフセットを修正しようともしません。 したがって、このようなアプリでは、結果のビデオが誤ってレンダリングされる可能性があります。
上記のように IHV/OEM が 0 度の向きにセンサーをマウントできない場合、次の軽減手順を優先順に行うことをお勧めします。
結果の出力フレームが 0 度の向きになるように、カメラ ドライバー (AV ストリーム ミニポート ドライバーのカーネル モードまたはデバイス MFT や MFT0 などのプラグインを使用するユーザー モード) 内で 0 度以外の向きを自動修正します。
カメラ パイプラインがキャプチャされたイメージを修正できるように、FSSensorOrientation タグを使用して 0 度以外の向きを宣言します。
前述のように、ACPI の PLD テーブルに 0 度以外の向きを宣言します。
圧縮/エンコードされたメディアの種類
圧縮および/またはエンコードされたメディアの種類 (M JPG、JPEG、H264、HEVC など) の場合、パイプラインの修正を使用できません。 このため、FSSensorOrientation が 0 以外の値に設定されている場合、圧縮/エンコードされたメディアの種類は除外されます。
MJPG メディア の種類 (UVC カメラのものなど) の場合、フレーム サーバー パイプラインは、自動デコードされたメディアの種類 (DShow ベースのアプリケーションではNV12 または YUY2) を提供します。 自動デコードおよび修正されたメディアの種類が表示されますが、元の MJPG 形式は表示されません。
[!注意!] 圧縮/エンコードされたメディアの種類をアプリケーションに公開する必要がある場合、IHV/ODM は FSSensorOrientation の修正を使用してはいけません。 代わりに、修正はカメラ ドライバー (AV ストリーム ドライバー経由のカーネル モードまたは DMFT/MFT0 経由のユーザー モード) によって行う必要があります。
AV ストリーム ミニポート/デバイス MFT/MFT0 経由で自動修正
センサーを 0 度オフセットでマウントできない場合に 推奨される シナリオは、AV Stream ミニポート ドライバー (または DMFT または MFT0 のいずれかの形式のユーザー モード プラグイン) に、結果としてキャプチャされたフレームを修正して、0 度オフセットでパイプラインに公開されるようにすることです。
AV ストリーム ミニポートおよび/またはデバイス MFT/MFT0 プラグインからビデオ フレームを修正する場合、結果のメディアの種類の宣言は、修正されたフレームに基づいている必要があります。 センサーが 90 度オフセットでマウントされ、その結果のビデオがセンサーからの縦横比が 9:16 であっても、修正されたビデオは 16:9 になる場合、メディアの種類は 16:9 の縦横比を宣言する必要があります。
これには、結果のストライド情報も含まれます。 これは、修正を行うコンポーネントが IHV/OEM によって制御され、カメラ パイプラインがビデオフレームの内容を見ることができるのは、修正が行われた後だけであるために必要です。
修正はユーザー モードで行われ、パイプラインとユーザー モード プラグインの間の API コントラクトに従う必要があることを強くお勧めします。 具体的には、DMFT または MFT0 を使用する場合、IMFDeviceTransform::P rocessMessage または IMFTransform::P rocessMessage が MFT_MESSAGE_Standard Edition T_D3D_MANAGER メッセージで呼び出された場合、ユーザー モード プラグインは次のガイドラインに従う必要があります。
- D3D マネージャーが指定されていない場合 (メッセージの ulParam が 0 の場合)、ユーザー モード プラグインは回転補正を処理するために GPU 操作を行ってはいけません。 そして、結果のフレームはシステム メモリに提供する必要があります。
- D3D マネージャーが指定されている場合 (メッセージの ulParam は DXGI マネージャーの IUnknownである場合)、その DXGI マネージャーを回転補正に使用する必要があり、結果のフレームは GPU メモリである必要があります。
- 実行時のユーザー モード プラグインでは、 D3D マネージャー メッセージも処理する必要があります。 MFT_MESSAGE_Standard Edition T_D3D_MANAGER メッセージが発行されると、プラグインによって生成される次のフレームは、要求されたメモリの種類 (つまり、DXGI Manager が提供された場合は GPU、それ以外の場合は CPU) に対応する必要があります。
- AV Stream ドライバー (またはユーザー モード プラグイン) が回転補正を処理する場合、ACPI の PLD 構造体の回転フィールドを 0 に設定する必要があります。
Note
オートコレクトを使用する場合、OEM および IHV は、_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 度オフセットに戻すために90度反時計回りに回転します。
MS OS 記述子 1.0
USB ベースのカメラの場合、FSSensorOrientation は MSOS 記述子を介して公開される可能性があります。
MS OS 記述子 1.0 には、2 つのコンポーネントがあります:
- 固定長のヘッダー セクション
- ヘッダー セクションの後に続く 1 つ以上の可変長のカスタム プロパティ セクション
MS OS 記述子 1.0 ヘッダー セクション
ヘッダー セクションには、単一のカスタム プロパティ (Face 認証プロファイル) が記述されています。
オフセット | フィールド | サイズ (バイト) | Value | アクリルアミド |
---|---|---|---|---|
0 | dwLength | 4 | <> | |
4 | bcdVersion | 2 | 0x0100 | バージョン 1.0 |
6 | wIndex | 2 | 0x0005 | 拡張プロパティ OS 記述子 |
8 | wCount | 2 | 0x0001 | 1 つのカスタム プロパティ |
カスタム MS OS 記述子 1.0 プロパティ セクション
オフセット | フィールド | サイズ (バイト) | Value | アクリルアミド |
---|---|---|---|---|
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 | プロパティ データの場合は 4 バイト (sizeof(DWORD))です。 |
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 度時計回り
上記の図では、次のようになります:
左側の図は、キャプチャするシーンを示しています。
中央の図は、物理的な読み出し順序が左下隅から始まり、左から右に上方向に移動する CMOS センサーによってシーンがどのように表示されるかを示しています。
右側の図は、カメラ ドライバーの出力を表します。 この例では、メディア バッファーの内容は追加の回転なしに、そのままネイティブの向きで表示できます。 その結果、ACPI _PLD 回転フィールドの値は 0 になります。
回転: 90 度時計回り
この場合、メディア バッファーのコンテンツは、元のシーンと比較して、時計回りに 90 度回転します。 その結果、ACPI _PLD 回転フィールドの値は 2 になります。
回転: 180 度時計回り
この場合、メディア バッファーのコンテンツは、元のシーンと比較して、時計回りに 180 度回転します。 その結果、ACPI _PLD 回転フィールドの値は 4 になります。
回転: 270 度時計回り
この場合、メディア バッファーのコンテンツは、元のシーンと比較して、時計回りに 270 度回転します。 その結果、ACPI _PLD 回転フィールドの値は 6 になります。