ホーム >プログラム >Delphi 6 ローテクTips

DirectShowを利用して再生・その1


動画ファイルや音声ファイルを再生するにはDelphiに標準で付属するTMediaPlayerを使ったりTWindowsMediaPlayerを取り込んで使ったりと色々ありますが、DirectShowを使うという手もあります。
TMediaPlayerやTWindowsMediaPlayerのようにコンポーネントをフォームに貼り付けてプロパティをセットして動作を決めてゆくというようなお手軽さはありませんが、ビデオ映像のキャプチャが(慣れれば)簡単にできるなどそれを補って余りある魅力があります。
コンポーネントを貼り付けてのお手軽さを求めるならDSPackというものを利用する手もあります。

このページではDSPackのコンポーネントは使わずに生のDicrectShowをいじくりまわしてやっています。

今回は下準備ととりあえず再生するだけのサンプルです。


参考サイト

下準備

まずはDirectShowのヘッダーをDelphi用に翻訳したユニットを使えるようにします。
この作業はDelphi 6などの古いバージョンでDirectShowのヘッダー(DirectShow9.pasあるいはDirectShow9.dcu)が付属しないものに必要なものです。
あらかじめDirectShowのヘッダーが付属しているバージョンのDelphiには必須ではありません。

DirectShowのヘッダーをDelphi用に翻訳したものはDSPackに入っています。
DSPack以外にも探せば色々とあるようですが、DSPackはDirectShowをコンポーネント化していて、更にそのソースコードがついているのでお勧めです。

ダウンロードして解凍したら、DirectShow9.pasのあるフォルダ(src\Directx9)とDSPackのソースコードのあるフォルダ(src\DSPack)をDelphiのライブラリのパスに追加します。
DSPackのソースコードのあるフォルダはDSPackのコンポーネントを使わない場合でもBaseClass.pasとDSUtil.pasを使うことがあるのでパスに追加しておきます。

Delphiのメニューで「プロジェクト」→「オプション」で出てくるダイアログの「ディレクトリ/条件」タブの「検索パス」の欄に追加します。

これで準備OKです。

ちなみに、DSPackの圧縮ファイルを解凍してできるファイルにはDirectX用のヘッダーユニットの他にもサンプルソースコードなどが色々あります。
それらのサンプルを動かすにはDSPackをインストールして使えるようにしておく必要があります。
インストールのやり方はreadme.htmlに(英文ですが)書いてあります。
Delphi 6の場合なら、

  1. ライブラリの検索パスにsrcフォルダ中のDirectx9とDSPackの二つのフォルダを追加します。
  2. packagesフォルダ中のDirectX9_D6.dpkを読み込んでコンパイル。
    インストールはしません。
  3. packagesフォルダ中のDSPack_D6.dpkを読み込んでコンパイル。
    これもインストールはしません。
  4. 最後にpackagesフォルダ中のDSPackDesign_D6.dpkを読み込んでコンパイルしてインストール。

これでOKです。
DirectX9_D6.dpkとDSPack_D6.dpkはコンパイルするだけでインストールはしません。
DSPackDesign_D6.dpkをインストールするだけです。
メディアプレーヤーのサンプルだけでなくDVDプレーヤーのサンプルやフィルターのサンプルなどもあるのでインストールしておいて損はないと思います。

とりあえず再生

それでは早速DirectShowでの再生をやってみましょう。
とりあえず再生しっぱなしなサンプルです。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DirectShow9;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private 宣言 }
    F_GraphBuilder : IGraphBuilder;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation
uses
  ActiveX;

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
var
  li_Ret         : HResult;
  l_MediaControl : IMediaControl;
begin
  if (OpenDialog1.Execute) then begin
    F_GraphBuilder  := nil;

    //グラフ作成
    li_Ret := CoCreateInstance(
        CLSID_FilterGraph,
        nil,
        CLSCTX_INPROC_SERVER,
        IID_IGraphBuilder,
        F_GraphBuilder
    );
    if (li_Ret <> S_OK) then begin
      Exit;
    end;

    //読み込み
    if not(Succeeded(F_GraphBuilder.RenderFile(POLESTR(WideString(OpenDialog1.FileName)), nil)) then begin
      Exit;
    end;

    //再生開始
    F_GraphBuilder.QueryInterface(IMediaControl, l_MediaControl);
    l_MediaControl.Run;
    l_MediaControl := nil;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  F_GraphBuilder := nil;
end;

end.

interface部のuses節にDirectShow9ユニットを追加します。
implementation部のuses節にActiveXユニットを追加します。
Form1のprivate宣言部にIGraphBuilder型の変数F_GraphBuilderを宣言します。
Form1にButtonコントロールとOpenDialogコントロールを貼り付けます。
Buttonコントロールをダブルクリックして表示されるButton1Clickイベントに上記のコードを加えます。
Form1のFormDestroyイベントにF_GraphBuilderを初期化するコードを加えます。

これだけです。
このプログラムを実行させ、ボタンをクリックしてファイル選択ダイアログで音楽ファイルや動画ファイルを選べば再生が始まります。
選択したファイルが動画なら別ウィンドウを開いて再生します。
参考サイトのサンプルのコードと比べるとずいぶんあっさりしていますが、これは手抜きができるところを思いっきり抜いているためです。
このようにDirectShowは手を抜いた部分を賢く補完してくれるので意外と取っ付きやすいです。

参考サイトのサンプルはコマンドラインのプログラムなので再生の後待機するようなコードが必要ですが、フォームを使う場合には必要ありません。
またDirectShowを使うにあたってCOMの初期化のためにCoInitializeを最初に呼びなさい、そしてそれに合わせて終了時にCoUninitializeも呼びなさいとありますが、これもDelphiでは必要ありません。
必要ないというか、すでにComObjユニットで呼ばれているのでわざわざ自分でやる必要がありません。
そしてComObjユニットはDirectShow9ユニットのuses節に含まれています。

 結果、Delphiでは必要なし。

ということです。
更にCoUninitializeはCoInitializeの戻り値によって呼ばなければならなかったり逆に呼んではならなかったりするので、この場合余分なことはしない方が良いという判断で省略します。

気をつける点はD6のファイル選択ダイアログのFileNameプロパティはAnsiStringなのでWideStringにキャストしてからRenderFileに渡すという点です。
それをしないと、POLESTRはPWideCharと同じなのでPWideChar(OpenDialog1.FileName)とするのと同じことになり(Unicode化以前のDelphiでは)文字化けするのでファイルの読み込みに失敗します。

今回はファイルを選んで再生しっぱなしなサンプルでしたが、IMediaControlインターフェースを使えば再生、一時停止、停止などができます。
IMediaPositionインターフェースを使えば再生位置の移動なども簡単にできます。