DirectShow DRM-Protected ASF ファイルの読み取り
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、および Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、従来の API を使用する既存のコードを、可能であれば新しい API を使用するように書き直すよう提案しています。]
このトピックでは、DirectShow を使用して、Windows Media Digital Rights Management (DRM) で保護されているメディア ファイルを再生する方法について説明します。
DRM の概念
Windows Media DRM を使用してメディア ファイルを保護するには、次の 2 つの異なる手順が必要です。
- コンテンツ プロバイダーはファイルをパッケージ化します。つまり、ファイルを暗号化し、ASF ファイル ヘッダーにライセンス情報を添付します。 ライセンス情報には、クライアントがライセンスを取得できる URL が含まれます。
- クライアント アプリケーションは、コンテンツのライセンスを取得します。
パッケージ化は、ファイルが配布される前に行われます。 ライセンスの取得は、ユーザーがファイルを再生またはコピーしようとしたときに発生します。 ライセンスの取得は、 サイレント または サイレント以外のどちらでもかまいません。 サイレント取得では、ユーザーとの対話は必要ありません。 サイレントではない取得では、アプリケーションでブラウザー ウィンドウを開き、Web ページをユーザーに表示する必要があります。 その時点で、ユーザーはコンテンツ プロバイダーに何らかの情報を提供することが必要になる場合があります。 ただし、どちらの種類のライセンス取得でも、クライアントはライセンス サーバーに HTTP 要求を送信する必要があります。
DRM バージョン
Windows Media DRM のいくつかのバージョンが存在します。 クライアント アプリケーションの観点から、DRM バージョン 1 と DRM バージョン 7 以降の 2 つのカテゴリにグループ化できます。 (2 番目のカテゴリには、DRM バージョン 9 と 10、およびバージョン 7 が含まれます)。このように DRM バージョンを分類する理由は、バージョン 1 のライセンスがバージョン 7 以降のライセンスとは多少異なる方法で処理されるためです。 このドキュメントでは、 バージョン 7 ライセンス という用語はバージョン 7 以降を意味します。
DRM パッケージと DRM ライセンスを区別することも重要です。 ファイルが Windows Media Rights Manager バージョン 7 以降を使用してパッケージ化されている場合、DRM ヘッダーには、バージョン 7 のライセンス URL に加えて、バージョン 1 のライセンス URL を含めることができます。 バージョン 1 のライセンス URL を使用すると、バージョン 7 をサポートしていない古いプレーヤーがコンテンツのライセンスを取得できます。 ただし、逆は当てはまらないため、バージョン 1 パッケージのファイルにバージョン 7 のライセンス URL を設定することはできません。
アプリケーション セキュリティ レベル
DRM で保護されたファイルを再生するには、Microsoft によってバイナリ形式で提供される静的ライブラリにクライアント アプリケーションをリンクする必要があります。 アプリケーションを一意に識別するこのライブラリは、スタブ ライブラリと呼ばれることもあります。 スタブ ライブラリにはセキュリティ レベルが割り当てられます。この値は、スタブ ライブラリを取得したときに署名した使用許諾契約書によって決まります。
コンテンツ プロバイダーは、ライセンスを取得するために必要な最小限のセキュリティ レベルを設定します。 スタブ ライブラリのセキュリティ レベルがライセンス サーバーに必要な最小セキュリティ レベルより小さい場合、アプリケーションはライセンスを取得できません。
個別
セキュリティを強化するために、アプリケーションはクライアントのコンピューター上の DRM コンポーネントを更新する場合があります。 この更新プログラムは、個別化と呼ばれ、ユーザーのアプリケーションのコピーと、同じアプリケーションの他のすべてのコピーを区別します。 保護されたファイルの DRM ヘッダーでは、最小の個別化レベルを指定できます。 (詳細については、Windows Media Rights Manager SDK の WMRMHeader.IndividualizedVersion のドキュメントを参照してください)。
Microsoft Individualization Service は、ユーザーからの情報を処理します。 そのため、アプリケーションを個別化する前に、Microsoft のプライバシーに関する声明を表示するか、リンクを指定する必要があります ( 「Microsoft のプライバシーに関する声明」を参照してください)。
ソフトウェア証明書を指定する
アプリケーションで DRM ライセンスを使用できるようにするには、アプリケーションがソフトウェア証明書または キー を Filter Graph Manager に提供する必要があります。 このキーは、アプリケーション用に個別化された静的ライブラリに含まれています。 個別化されたライブラリの取得の詳細については、Windows Media Format SDK ドキュメント の「必要な DRM ライブラリの取得 」を参照してください。
ソフトウェア キーを指定するには、次の手順を実行します。
- スタティック ライブラリへのリンク。
- IServiceProvider インターフェイスを実装します。
- フィルター グラフ マネージャーで IObjectWithSite インターフェイスのクエリを実行します。
- IServiceProvider の実装へのポインターを使用して IObjectWithSite::SetSite を呼び出します。
- Filter Graph Manager は IServiceProvider::QueryService を呼び出し、サービス識別子 のIID_IWMReader を指定します。
- QueryService の実装で、WMCreateCertificate を呼び出してソフトウェア キーを作成します。
次のコードは 、QueryService メソッドを実装する方法を示しています。
STDMETHODIMP Player::QueryService(REFIID siid, REFIID riid, void **ppv)
{
if (ppv == NULL )
{
return E_POINTER;
}
if (siid == __uuidof(IWMReader) && riid == __uuidof(IUnknown))
{
IUnknown *punkCert;
HRESULT hr = WMCreateCertificate(&punkCert);
if (SUCCEEDED(hr))
{
*ppv = (void *) punkCert;
}
return hr;
}
return E_NOINTERFACE;
}
次のコードは、フィルター グラフ マネージャーで SetSite を呼び出す方法を示しています。
HRESULT Player::CreateFilterGraph()
{
CComPtr<IObjectWithSite> pSite;
HRESULT hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if (FAILED(hr))
{
goto done;
}
// Register the application as a site (service).
hr = pGraph->QueryInterface(&pSite);
if (FAILED(hr))
{
goto done;
}
hr = pSite->SetSite(this);
done:
return hr;
}
再生グラフの構築
DRM で保護された ASF ファイルを再生するには、次の手順に従います。
- Filter Graph Manager を作成し、IMediaEventEx インターフェイスを使用してグラフ イベントに登録します。
- CoCreateInstance を呼び出して、WM ASF リーダー フィルターの新しいインスタンスを作成します。
- フィルター グラフにフィルターを追加するには、 IFilterGraph::AddFilter を呼び出します。
- IFileSourceFilter インターフェイスのフィルターに対してクエリを実行します。
- ファイルの URL を使用して IFileSourceFilter::Load を呼び出します。
- EC_WMT_EVENTイベントを処理します。
- 最初の EC_WMT_EVENT イベントで、 WM ASF Reader フィルターに IServiceProvider インターフェイスのクエリを実行します。
- ISERVICEProvider::QueryService を呼び出して、IWMDRMReader インターフェイスへのポインターを取得します。
- IGraphBuilder::Render を呼び出して、WM ASF リーダー フィルターの出力ピンをレンダリングします。
注意
DRM で保護されたファイルを開くときに、フィルター グラフを作成するために IGraphBuilder::RenderFile を呼び出さないでください。 WM ASF リーダー フィルターは、DRM ライセンスが取得されるまで、他のフィルターに接続できません。 この手順では、アプリケーションで IWMDRMReader インターフェイスを使用する必要があります。これは、手順 7 から 8 で説明されているように、フィルターから取得する必要があります。 そのため、フィルターを作成してグラフに追加する必要があります
注意
アプリケーションでEC_WMT_EVENT イベントを処理する必要があるため、WM ASF Reader フィルターをグラフに追加する前に(手順 1) グラフ イベントに登録することが重要です (手順 3)。 イベントは、 Load が呼び出されたときに送信されます (手順 5)。
次のコードは、グラフをビルドする方法を示しています。
HRESULT Player::LoadMediaFile(PCWSTR pwszFile)
{
BOOL bIsWindowsMediaFile = IsWindowsMediaFile(pwszFile);
HRESULT hr = S_OK;
// If this is the first time opening the file, create the
// filter graph and add the WM ASF Reader filter.
if (m_DRM.State() == DRM_INITIAL)
{
hr = CreateFilterGraph();
if (FAILED(hr))
{
goto done;
}
// Use special handling for Windows Media files.
if (bIsWindowsMediaFile)
{
// Add the ASF Reader filter to the graph.
hr = m_pReader.CoCreateInstance(CLSID_WMAsfReader);
if (FAILED(hr))
{
goto done;
}
hr = pGraph->AddFilter(m_pReader, NULL);
if (FAILED(hr))
{
goto done;
}
hr = m_pReader->QueryInterface(&m_pFileSource);
if (FAILED(hr))
{
goto done;
}
}
}
if (bIsWindowsMediaFile)
{
hr = m_pFileSource->Load(pwszFile, NULL);
C++ |
---|
|
前のコードでは、関数は RenderOutputPins
WM ASF リーダー フィルターの出力ピンを列挙し、各ピンに対して IGraphBuilder::Render を 呼び出します。
HRESULT RenderOutputPins(IGraphBuilder *pGraph, IBaseFilter *pFilter)
{
CComPtr<IEnumPins> pEnumPin = NULL;
CComPtr<IPin> pConnectedPin;
CComPtr<IPin> pPin;
// Enumerate all pins on the filter
HRESULT hr = pFilter->EnumPins(&pEnumPin);
if (FAILED(hr))
{
goto done;
}
// Step through every pin, looking for the output pins.
while (S_OK == (hr = pEnumPin->Next(1, &pPin, NULL)))
{
// Skip connected pins.
hr = pPin->ConnectedTo(&pConnectedPin);
if (hr == VFW_E_NOT_CONNECTED)
{
PIN_DIRECTION PinDirection;
hr = pPin->QueryDirection(&PinDirection);
if ((S_OK == hr) && (PinDirection == PINDIR_OUTPUT))
{
hr = pGraph->Render(pPin);
}
}
pConnectedPin.Release();
pPin.Release();
// If there was an error, stop enumerating.
if (FAILED(hr))
{
break;
}
}
done:
return hr;
}
次のコードは、WM ASF リーダーから IWMDRMReader インターフェイスへのポインターを取得する方法を示しています。
HRESULT DrmManager::Initialize(IBaseFilter *pFilter)
{
CComPtr<IServiceProvider> pService;
CComPtr<IWMDRMReader> pDrmReader;
HRESULT hr = pFilter->QueryInterface(&pService);
if (SUCCEEDED(hr))
{
hr = pService->QueryService(
__uuidof(IWMDRMReader), IID_PPV_ARGS(&m_pDrmReader));
}
return hr;
}
関連トピック