ラベル DirectShow の投稿を表示しています。 すべての投稿を表示
ラベル DirectShow の投稿を表示しています。 すべての投稿を表示

2013年6月18日火曜日

フォーム内で再生:DirectShow

フォームアプリケーションで再生 の記事を変更する。


とりあえず表示してみる。諸々の処理は省略してあります。
ボタンをクリックすると表示する。

 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
     IGraphBuilder *pGraph = NULL;  
     IMediaControl *pControl = NULL;  
     IMediaEvent   *pEvent = NULL;
     IVideoWindow  *pVideoWindow = NULL;

     // COM ライブラリを初期化する。  
     HRESULT hr = CoInitialize(NULL);  
     if (FAILED(hr))  
     {  
      printf("ERROR - Could not initialize COM library");  
      return;  
     }  

     // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。  
     hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,   
      IID_IGraphBuilder, (void **)&pGraph);  
     if (FAILED(hr))  
     {  
      printf("ERROR - Could not create the Filter Graph Manager.");  
      return;  
     }  

     hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);  
     hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
     hr = pGraph->QueryInterface(IID_IVideoWindow, (LPVOID*)&pVideoWindow);

     // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。  
     hr = pGraph->RenderFile(L"G:\\sampleMovie\\avi_divx5_mp3.avi", NULL);  

     // 描画先ウィンドウの設定
     HWND hWnd = reinterpret_cast< HWND & >(this->Handle);
     hr = pVideoWindow->put_Owner((OAHWND)hWnd);
     hr = pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);
     hr = pVideoWindow->SetWindowPosition(0,0,320,240);
     hr = pVideoWindow->put_Visible(OATRUE);

     // グラフを実行する。  
     hr = pControl->Run();  

     pControl->Release();  
     pEvent->Release();  
     pGraph->Release();  
    }
 };

2013年6月15日土曜日

音量を調整する。

IBasicAudio::put_Volume

#include <dshow.h>
void main(void)
{
 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IBasicAudio *pBasicAudio = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

 // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
 hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);
 
 // 音量調整インターフェース
 hr = pGraph->QueryInterface(IID_IBasicAudio, (LPVOID *)&pBasicAudio);
 
 hr = pBasicAudio->put_Volume(-10000);//ボリュームを -10,000 ~ 0 の数値で指定する。

 // グラフを実行する。
 hr = pControl->Run();
 if (SUCCEEDED(hr))
 {
  // 完了するまで待機する。
  long evCode;
  pEvent->WaitForCompletion(INFINITE, &evCode);

  // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
  // 無期限にブロックする場合がある。
 }

 pBasicAudio->Release();
 pControl->Release();
 pEvent->Release();
 pGraph->Release();
 CoUninitialize();
}

全ストリーム長(再生時間)を受け取る。

IMediaPosition::get_Duration


#include <dshow.h>
void main(void)
{
 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IMediaPosition *pMediaPosition;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

 // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
 hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);
 
 // ストリームの時間幅を取得する
 hr = pGraph->QueryInterface(IID_IMediaPosition,(LPVOID *)&pMediaPosition);
 REFTIME plength;
 hr = pMediaPosition->get_Duration(&plength);

 printf("%lf\n", plength);

 // グラフを実行する。
 hr = pControl->Run();
 if (SUCCEEDED(hr))
 {
  // 完了するまで待機する。
  long evCode;
  pEvent->WaitForCompletion(INFINITE, &evCode);

  // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
  // 無期限にブロックする場合がある。
 }

 pMediaPosition->Release();
 pControl->Release();
 pEvent->Release();
 pGraph->Release();
 CoUninitialize();
}

ビデオのサイズを取得する

IBasicVideo インターフェイス


#include <dshow.h>
void main(void)
{
 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IBasicVideo *pBasicVideo = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

 // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
 hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);
 
 // 幅と高さを取得します
 hr = pGraph->QueryInterface(IID_IBasicVideo, (LPVOID *)&pBasicVideo);
 
 long pVideoHeight, pVideoWidth;

 hr = pBasicVideo->get_VideoHeight(&pVideoHeight);
 hr = pBasicVideo->get_VideoWidth(&pVideoWidth);

 printf("width=%d, height=%d\n", pVideoWidth, pVideoHeight);

 // グラフを実行する。
 hr = pControl->Run();
 if (SUCCEEDED(hr))
 {
  // 完了するまで待機する。
  long evCode;
  pEvent->WaitForCompletion(INFINITE, &evCode);

  // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
  // 無期限にブロックする場合がある。
 }

 pBasicVideo->Release();
 pControl->Release();
 pEvent->Release();
 pGraph->Release();
 CoUninitialize();
}

作成したウインドウ上で動画再生

ウインドウの作成:win32 の記事で作ったウインドウに
msdnのサンプルコードを実行してみる で作ったソースを追加

IVideoWindow インターフェイス

ウインドウ作成時に動画を再生するようにする。


// GT_HelloWorldWin32.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

#include <dshow.h>

// Global variables

// The main window class name.
static TCHAR szWindowClass[] = _T("win32app");

// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");

HINSTANCE hInst;

// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
 HINSTANCE hPrevInstance,
 LPSTR lpCmdLine,
 int nCmdShow)
{
 WNDCLASSEX wcex;

 wcex.cbSize = sizeof(WNDCLASSEX);
 wcex.style          = CS_HREDRAW | CS_VREDRAW;
 wcex.lpfnWndProc    = WndProc;
 wcex.cbClsExtra     = 0;
 wcex.cbWndExtra     = 0;
 wcex.hInstance      = hInstance;
 wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
 wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
 wcex.lpszMenuName   = NULL;
 wcex.lpszClassName  = szWindowClass;
 wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

 if (!RegisterClassEx(&wcex))
 {
  MessageBox(NULL,
   _T("Call to RegisterClassEx failed!"),
   _T("Win32 Guided Tour"),
   NULL);

  return 1;
 }

 hInst = hInstance; // Store instance handle in our global variable

 // The parameters to CreateWindow explained:
 // szWindowClass: the name of the application
 // szTitle: the text that appears in the title bar
 // WS_OVERLAPPEDWINDOW: the type of window to create
 // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
 // 500, 100: initial size (width, length)
 // NULL: the parent of this window
 // NULL: this application does not have a menu bar
 // hInstance: the first parameter from WinMain
 // NULL: not used in this application
 HWND hWnd = CreateWindow(
  szWindowClass,
  szTitle,
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, CW_USEDEFAULT,
  500, 400,
  NULL,
  NULL,
  hInstance,
  NULL
  );

 if (!hWnd)
 {
  MessageBox(NULL,
   _T("Call to CreateWindow failed!"),
   _T("Win32 Guided Tour"),
   NULL);

  return 1;
 }

 // The parameters to ShowWindow explained:
 // hWnd: the value returned from CreateWindow
 // nCmdShow: the fourth parameter from WinMain
 ShowWindow(hWnd,
  nCmdShow);
 UpdateWindow(hWnd);

 // Main message loop:
 MSG msg;
 while (GetMessage(&msg, NULL, 0, 0))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }

 return (int) msg.wParam;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 PAINTSTRUCT ps;
 HDC hdc;
 TCHAR greeting[] = _T("Hello, World!");

 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IVideoWindow  *pVideoWindow = NULL;

 HRESULT hr = CoInitialize(NULL);// COM ライブラリを初期化する。

 switch (message)
 {
 case WM_CREATE://ウインドウ作成時の処理

  // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
  hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
   IID_IGraphBuilder, (void **)&pGraph);
  if (FAILED(hr))
  {
   printf("ERROR - Could not create the Filter Graph Manager.");
   
  }

  hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
  hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

  hr = pGraph->QueryInterface(IID_IVideoWindow, (LPVOID*)&pVideoWindow);
  
  // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
  hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);

  // 描画先ウィンドウの設定
  hr = pVideoWindow->put_Owner((OAHWND)hWnd);
  hr = pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);
  hr = pVideoWindow->put_Visible(OATRUE);

  // グラフを実行する。
  hr = pControl->Run();

  // 描画先ウィンドウ内の描画位置の設定
  pVideoWindow->SetWindowPosition(0, 0, 320, 240);

  pVideoWindow->Release();
  pControl->Release();
  pEvent->Release();
  pGraph->Release();
  CoUninitialize();

  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);

  // Here your application is laid out.
  // For this introduction, we just print out "Hello, World!"
  // in the top left corner.
  //TextOut(hdc,5, 5,greeting, _tcslen(greeting));
  // End application-specific layout section.

  EndPaint(hWnd, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
  break;
 }

 return 0;
}

2013年6月14日金曜日

ビデオ ウィンドウのタイトル設定



#include <dshow.h>
void main(void)
{
 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IVideoWindow *pVidWin  = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

 // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
 hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);
 if (SUCCEEDED(hr))
 {
  //ウインドウのタイトル変更
  pGraph->QueryInterface(IID_IVideoWindow,(LPVOID *)&pVidWin );
  pVidWin->put_Caption(L"動画プレイヤー");


  // グラフを実行する。
  hr = pControl->Run();
  if (SUCCEEDED(hr))
  {
   // 完了するまで待機する。
   long evCode;
   pEvent->WaitForCompletion(INFINITE, &evCode);

   // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
   // 無期限にブロックする場合がある。
  }
 }

 pVidWin->Release();
 pControl->Release();
 pEvent->Release();
 pGraph->Release();
 CoUninitialize();
}

指定されたタイトルの指定された時間から再生を開始する。

IDvdControl2::PlayAtTimeInTitle

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IGraphBuilder *m_pGraph;
 IMediaControl *m_pIMC;
 IDvdInfo2 *m_pIDvdI2;
 IDvdControl2  *m_pIDvdC2;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // DVD ナビゲータ インターフェイスへのポインタを取得する。
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdControl2, reinterpret_cast<void**>(&m_pIDvdC2));

 // フィルタ グラフ マネージャへのポインタを取得する。
 hr = m_pIDvdGB->GetFiltergraph(&m_pGraph);

 // フィルタ グラフを全体として制御するため、
 // グラフ ポインタを使って IMediaControl へのポインタを取得する。
 hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pIMC);

 hr = m_pIMC->Run();

 /* 指定されたタイトルの指定された時間から再生を開始する。ここから*/
 DVD_HMSF_TIMECODE time;
 time.bHours = 0;
 time.bMinutes = 0;
 time.bSeconds = 0;
 time.bFrames = 0;

 hr = m_pIDvdC2->PlayAtTimeInTitle(5, &time, DVD_CMD_FLAG_Block, NULL);//ok
 /* ここまで */

 MessageBox(0, 0, L"OK", 0);

 m_pIDvdI2->Release();
 m_pIDvdC2->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}




2013年6月13日木曜日

現在のタイトルの総再生時間を取得する。

試しに再生したDVDはタイトル3から再生をはじめる。

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IGraphBuilder *m_pGraph;
 IMediaControl *m_pIMC;
 IDvdInfo2 *m_pIDvdI2;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // フィルタ グラフ マネージャへのポインタを取得する。
 hr = m_pIDvdGB->GetFiltergraph(&m_pGraph);

 // フィルタ グラフを全体として制御するため、
 // グラフ ポインタを使って IMediaControl へのポインタを取得する。
 hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pIMC);

 // DVD ナビゲータ インターフェイスへのポインタを取得する。
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));


 m_pIMC->Run();

 /* タイトル */
 //現在のタイトルの総再生時間を取得する。
 DVD_HMSF_TIMECODE pTotalTime;
 ULONG pulTimeCodeFlags;

 hr = m_pIDvdI2->GetTotalTitleTime(&pTotalTime,&pulTimeCodeFlags);

 if (SUCCEEDED(hr))
 {
  //時、分、秒、フレーム単位の総時間を受け取る
  printf("時::%d\n",pTotalTime.bHours);
  printf("分::%d\n",pTotalTime.bMinutes);
  printf("秒::%d\n",pTotalTime.bSeconds);
  printf("フレーム::%d\n",pTotalTime.bFrames);

  //ディスクが作成されたときの再生フレーム レート
  if(pulTimeCodeFlags == DVD_TC_FLAG_25fps)
  {
   printf("ディスクは、25 フレーム/秒で再生されるようにオーサリングされている。\n");
  }
  else if(pulTimeCodeFlags == DVD_TC_FLAG_30fps)
  {
   printf("ディスクは、30 フレーム/秒で再生されるようにオーサリングされている。\n");
  }
  else if(pulTimeCodeFlags == DVD_TC_FLAG_DropFrame)
  {
   printf("ディスクは、29.97 フレーム/秒で再生されるようにオーサリングされている。\n");
  }
  else if(pulTimeCodeFlags == DVD_TC_FLAG_Interpolated)
  {
   printf("DVD ナビゲータ フィルタによるディスクのフレーム レートの最善の見積りを表す値。\n");
  }
 }

 MessageBox(0, 0, L"OK", 0);

 m_pIDvdI2->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}




現在 DVD ナビゲータが置かれている DVD ドメインを取得する。

とりあえず使い方程度

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IGraphBuilder *m_pGraph;
 IMediaControl *m_pIMC;
 IDvdInfo2 *m_pIDvdI2;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // フィルタ グラフ マネージャへのポインタを取得する。
 hr = m_pIDvdGB->GetFiltergraph(&m_pGraph);

 // フィルタ グラフを全体として制御するため、
 // グラフ ポインタを使って IMediaControl へのポインタを取得する。
 hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pIMC);

 // DVD ナビゲータ インターフェイスへのポインタを取得する。
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));


 m_pIMC->Run();

 /* DVD ナビゲータ状態情報 */
 //現在 DVD ナビゲータが置かれているドメインを取得する。
 DVD_DOMAIN  pDomain;

 hr = m_pIDvdI2->GetCurrentDomain(&pDomain);

 if (SUCCEEDED(hr))
 {
  if(pDomain == DVD_DOMAIN_FirstPlay)
  {
   printf("DVD_DOMAIN_FirstPlay::DVD ディスクの既定の初期化を行う。");
  }
  else if(pDomain == DVD_DOMAIN_VideoManagerMenu)
  {
   printf("DVD_DOMAIN_VideoManagerMenu::ディスク全体のメニューを表示する。");
  }
  else if(pDomain == DVD_DOMAIN_VideoTitleSetMenu)
  {
   printf("DVD_DOMAIN_VideoTitleSetMenu::現在のタイトル セットのメニューを表示する。");
  }
  else if(pDomain == DVD_DOMAIN_Title)
  {
   printf("DVD_DOMAIN_Title::現在のタイトルを表示する。");
  }
  else if(pDomain == DVD_DOMAIN_Stop)
  {
   printf("DVD_DOMAIN_Stop::DVD ナビゲータは DVD 停止ドメインに入っている。");
  }
 }

 MessageBox(0, 0, L"OK", 0);

 m_pIDvdI2->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}






指定されたタイトルのチャプターの数を取得する。

IDvdInfo2::GetNumberOfChapters

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IDvdInfo2 *m_pIDvdI2;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // DVD ナビゲータ インターフェイスへのポインタを取得する。
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));

 /* ディスク情報 */
 //指定されたタイトルのチャプターの数を取得する
 ULONG ulTitle = 4;
 ULONG pulNumOfChapters;
 hr = m_pIDvdI2->GetNumberOfChapters(ulTitle, &pulNumOfChapters);

 if (SUCCEEDED(hr))
 {
  printf("タイトル%uのチャプターの数 : %u\n", ulTitle,pulNumOfChapters);
 }

 MessageBox(0, 0, L"OK", 0);

 m_pIDvdI2->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}





現在の DVD ボリューム情報を取得する。

IDvdInfo2 インターフェイス
IDvdInfo2::GetDVDVolumeInfo

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IDvdInfo2 *m_pIDvdI2;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // DVD ナビゲータ インターフェイスへのポインタを取得する。
 hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, reinterpret_cast<void**>(&m_pIDvdI2));

 /* ディスク情報 */
 //現在の DVD ボリューム情報を取得する。
 ULONG pulNumOfVolumes;
 ULONG pulVolume;
 DVD_DISC_SIDE pSide;
 ULONG pulNumOfTitles;

 hr = m_pIDvdI2->GetDVDVolumeInfo(&pulNumOfVolumes,
  &pulVolume, 
  &pSide, 
  &pulNumOfTitles);

 if (SUCCEEDED(hr))
 {
  printf("ボリューム セット内のボリュームの数  : %u\n", pulNumOfVolumes);
  printf("このルート ディレクトリのボリューム番号: %u\n", pulVolume);
  switch (pSide) {
  case DVD_SIDE_A:
   printf("現在のディスク面                    ;サイド A\n");
   break;
  case DVD_SIDE_B:
   printf("現在のディスク面                    :サイド B\n");
   break;
  }
  printf("このボリュームで使えるタイトルの数     : %u\n", pulNumOfTitles);
 }

 MessageBox(0, 0, L"OK", 0);

 m_pIDvdI2->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}



DVD の再生

とりあえず再生してみる

#include <dshow.h>

int main()
{
 IDvdGraphBuilder *m_pIDvdGB;
 IGraphBuilder *m_pGraph;
 IMediaControl *m_pIMC;

 CoInitialize(NULL);

 HRESULT hr;

 // DVD グラフ ビルダ オブジェクトのインスタンスを作成する。
 hr = CoCreateInstance(CLSID_DvdGraphBuilder,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_IDvdGraphBuilder,
  (LPVOID *)&m_pIDvdGB);

 // DVD フィルタ グラフを作成する。
 AM_DVD_RENDERSTATUS buildStatus;
 hr = m_pIDvdGB->RenderDvdVideoVolume(NULL, AM_DVD_HWDEC_PREFER, &buildStatus);

 // フィルタ グラフ マネージャへのポインタを取得する。
 hr = m_pIDvdGB->GetFiltergraph(&m_pGraph);

 // フィルタ グラフを全体として制御するため、
 // グラフ ポインタを使って IMediaControl へのポインタを取得する。
 hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pIMC);

 m_pIMC->Run();

 MessageBox(0, 0, 0, 0);

 m_pIMC->Stop();

 m_pIMC->Release();
 m_pGraph->Release();
 m_pIDvdGB->Release();

 CoUninitialize();

 return 0;
}

2013年6月10日月曜日

VMR-9 フィルタを使う

VMR-9 フィルタ グラフの作成

#include <dshow.h>

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;
 ICaptureGraphBuilder2 *pBuild;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 // MediaControlインターフェース取得
 pGraph->QueryInterface(IID_IMediaControl,(LPVOID *)&pMediaControl);

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\avi_divx5_mp3.avi", L"Source", &pSource);

 // CaptureGraphBuilder2というキャプチャ用GraphBuilderを生成する
 hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, 
  IID_ICaptureGraphBuilder2, 
  (LPVOID *)&pBuild);

 // FilterGraphをセットする
 hr = pBuild->SetFiltergraph(pGraph);

 // ビデオ ストリームを VMR にレンダリングする。
 hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

 // 再生開始
 pMediaControl->Run();

 MessageBox(0,0,0,0);

 pMediaControl->Release();
 pBuild->Release();
 pGraph->Release();

 // COM終了
 CoUninitialize();
}
フィルタを表示させてみた

こんな感じか?

フィルタを表示させたときのソース
#include <dshow.h>

HRESULT EnumFilters (IFilterGraph *pGraph);

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;
 ICaptureGraphBuilder2 *pBuild;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 // MediaControlインターフェース取得
 pGraph->QueryInterface(IID_IMediaControl,(LPVOID *)&pMediaControl);

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\avi_divx5_mp3.avi", L"Source", &pSource);

 // CaptureGraphBuilder2というキャプチャ用GraphBuilderを生成する
 hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, 
  IID_ICaptureGraphBuilder2, 
  (LPVOID *)&pBuild);

 // FilterGraphをセットする
 hr = pBuild->SetFiltergraph(pGraph);

 // ビデオ ストリームを VMR にレンダリングする。
 hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

 // 再生開始
 pMediaControl->Run();

 EnumFilters(pGraph);

 MessageBox(0,0,0,0);


 pMediaControl->Release();
 pBuild->Release();
 pGraph->Release();

 // COM終了
 CoUninitialize();
}

HRESULT EnumFilters (IFilterGraph *pGraph) 
{
 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return 0;
 }

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr)) return hr;

 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
 {
  FILTER_INFO FilterInfo;
  hr = pFilter->QueryFilterInfo(&FilterInfo);
  if (FAILED(hr))
  {
   MessageBox(NULL, TEXT("Could not get the filter info"),
    TEXT("Error"), MB_OK | MB_ICONERROR);
   continue;  // 次は正しく動く可能性がある。
  }

#ifdef UNICODE
  //MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
  //printf(FilterInfo.achName);
  wprintf(L"%s\n", FilterInfo.achName);
#else
  char szName[MAX_FILTER_NAME];
  int cch = WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
   MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);
  if (chh > 0)
   MessageBox(NULL, szName, TEXT("Filter Name"), MB_OK);
#endif

  // FILTER_INFO 構造体はフィルタ グラフ マネージャへのポインタを保持する。
  // その参照カウントは解放しなければならない。
  if (FilterInfo.pGraph != NULL)
  {
   FilterInfo.pGraph->Release();
  }
  pFilter->Release();
 }

 pEnum->Release();
 return S_OK;
}

msdnのページでは、Capture Graph Builder を使いたくない場合の方法も書いてあったので、
とりあえずやってみた。
未整理のソースコード、一応動く程度

#include <dshow.h>

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

 // MediaControlインターフェース取得
 pGraph->QueryInterface(IID_IMediaControl,(LPVOID *)&pMediaControl);

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\cap.avi", L"Source", &pSource);

 // CaptureGraphBuilder2というキャプチャ用GraphBuilderを生成する
 //hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, 
 // IID_ICaptureGraphBuilder2, 
 // (LPVOID *)&pBuild);

 // FilterGraphをセットする
 /*hr = pBuild->SetFiltergraph(pGraph);*/

 // ビデオ ストリームを VMR にレンダリングする。
 // hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 //hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

 //ピンの列挙
 IFilterGraph* pFGraph;
 hr = pGraph->QueryInterface(IID_IFilterGraph, (void**)&pFGraph);

 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr))
  return;

 //フィルタの列挙
 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) {
  IPin  *pPin = NULL;
  FILTER_INFO FilterInfo;

  hr = pFilter->QueryFilterInfo(&FilterInfo);

  wprintf(L"%s", FilterInfo.achName);
  printf(" フィルターが見つかった\n");

  //ピンを探しに行く
  IFilterGraph2 *pGraph2 = NULL;
  hr = pGraph->QueryInterface(IID_PPV_ARGS(&pGraph2));

  {
   IEnumPins  *pEnum;
   IPin       *pPin;
   IPin* pConnectedPin = NULL;

   hr = pFilter->EnumPins(&pEnum);
   if (FAILED(hr))
   {
    return ;
   }
    while(pEnum->Next(1, &pPin, 0) == S_OK)
    {
     // ピンが列挙される
     printf("pinの列挙--");
     PIN_DIRECTION PinDirThis;

     hr = pPin->QueryDirection(&PinDirThis);
     if ((hr == S_OK)&&(PinDirThis == PINDIR_INPUT))
     {
      printf("入力ピン--");// 
      hr = pPin->ConnectedTo(&pConnectedPin);//接続済みか調べる
      if (hr == S_OK)
      {
       printf("接続済み\n");// 
      }else{
       printf("未接続\n");// 
      }
     }

     if ((hr == S_OK)&&(PinDirThis == PINDIR_OUTPUT))
     {
      printf("出力ピン--");//
      hr = pPin->ConnectedTo(&pConnectedPin);//接続済みか調べる
      if (hr == S_OK)
      {
       printf("接続済み\n");// 
      }else
       printf("未接続\n");// 
      hr = pGraph2->RenderEx(pPin,AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
     }

    }
  }

  // 見つかったピンを何かに使用
  if (pPin) {
   pPin->Release();
  }

  pFilter->Release();
 }

 // 再生開始
 pMediaControl->Run();

 MessageBox(0,0,0,0);

 pMediaControl->Release();
// pBuild->Release();
 pGraph->Release();

 // /COM終了
 CoUninitialize();
}


AM_RENDEREX_RENDERTOEXISTINGRENDERERS フラグを使って、IFilterGraph2::RenderEx を呼び出すと、既にグラフにあるレンダリング フィルタ のみを使い、出力ファイルがレンダリングされるそうです。

音は出ない。どうすればいいのだろうか?
サウンドフィルタの追加
 /*サウンド部分*/
 IBaseFilter *pAudioRenderer = NULL;
 hr = CoCreateInstance(CLSID_DSoundRender, NULL,
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAudioRenderer);

 hr = pGraph->AddFilter(pAudioRenderer, L"Audio Renderer");

2013年6月9日日曜日

ピンのID(識別子)を取得する



#include <dshow.h>

IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir);

void main(void)
{
 IGraphBuilder *pGraph = NULL;
  IMediaControl *pControl = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

    // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
    hr = pGraph->RenderFile(L"G:\\sampleMovie\\cap.avi", NULL);

 //ピンの列挙
 IFilterGraph* pFGraph;
 hr = pGraph->QueryInterface(IID_IFilterGraph, (void**)&pFGraph);

 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr))
  return;

 //フィルタの列挙
 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) {
  IPin  *pPin = NULL;
  
  //ピンを探しに行く
  pPin = GetPin(pFilter, PINDIR_INPUT);

  // 見つかったピンを何かに使用
  if (pPin) {
   pPin->Release();
  }

  pFilter->Release();
 }


 hr = pControl->Run();

 MessageBox(0,0,0,0);

 pControl->Release();
 pGraph->Release();
 CoUninitialize();
}

IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir){
 printf("--------pinを探す場所--------\n");
 BOOL       bFound = FALSE;
 IEnumPins  *pEnum;
 IPin       *pPin;

 HRESULT hr = pFilter->EnumPins(&pEnum);
 if (FAILED(hr))
 {
  return NULL;
 }

 while(pEnum->Next(1, &pPin, 0) == S_OK)
 {
  // ピンが列挙される
  printf("pinの列挙--");

  LPWSTR idGet;
  hr = pPin->QueryId(&idGet);
  wprintf(L"ID: %d :: ", idGet);
  wprintf(L"%s\n", idGet);

 }

 pEnum->Release();
 pPin->Release();

 return 0;
}

フィルタグラフ内のピンの列挙

ピンの列挙

ピンを列挙してみる

#include <dshow.h>

IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir);

void main(void)
{
 IGraphBuilder *pGraph = NULL;
  IMediaControl *pControl = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

 hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

    // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
    hr = pGraph->RenderFile(L"G:\\sampleMovie\\cap.avi", NULL);

 //ピンの列挙
 IFilterGraph* pFGraph;
 hr = pGraph->QueryInterface(IID_IFilterGraph, (void**)&pFGraph);

 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr))
  return;

 //フィルタの列挙
 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) {
  IPin  *pPin = NULL;
  
  printf("フィルターが見つかった\n");
  
  //ピンを探しに行く
  pPin = GetPin(pFilter, PINDIR_INPUT);

  // 見つかったピンを何かに使用
  if (pPin) {
   pPin->Release();
  }

  pFilter->Release();
 }


 hr = pControl->Run();

 MessageBox(0,0,0,0);

 pControl->Release();
 pGraph->Release();
 CoUninitialize();
}

IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir){
 printf("pinを探す場所\n");
 BOOL       bFound = FALSE;
 IEnumPins  *pEnum;
 IPin       *pPin;

 HRESULT hr = pFilter->EnumPins(&pEnum);
 if (FAILED(hr))
 {
  return NULL;
 }

 while(pEnum->Next(1, &pPin, 0) == S_OK)
 {
  // ピンが列挙される
  printf("pinの列挙--");
  PIN_DIRECTION PinDirThis;

  hr = pPin->QueryDirection(&PinDirThis);
  if ((hr == S_OK)&&(PinDirThis == PINDIR_INPUT))
  {
   printf("入力ピン\n");
  }

  if ((hr == S_OK)&&(PinDirThis == PINDIR_OUTPUT))
  {
   printf("出力ピン\n");// 
  }

 }

 return 0;
}


フィルタグラフ内のフィルタの列挙

ファイルの再生ではDirectShowがすべて処理してくれるので、
File Source しか指定していないので表示させてみる。

【表示結果】
Video Renderer
Color Space Converter
AVI Splitter
G:\\sampleMovie\\cap.avi



#include <dshow.h>

HRESULT EnumFilters (IFilterGraph *pGraph);

void main(void)
{
 IGraphBuilder *pGraph = NULL;
 IMediaControl *pControl = NULL;
 IMediaEvent   *pEvent = NULL;
 IFilterGraph  *pFGraph = NULL;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
    hr = pGraph->RenderFile(L"G:\\sampleMovie\\cap.avi", NULL);

 hr = pGraph->QueryInterface(IID_IFilterGraph, (void**)&pFGraph);

    if (SUCCEEDED(hr))
    {
        // グラフを実行する。
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // 完了するまで待機する。
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

            // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
            // 無期限にブロックする場合がある。
        }
    }
 
 EnumFilters(pFGraph);

    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}

HRESULT EnumFilters (IFilterGraph *pGraph) 
{
 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return 0;
 }

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr)) return hr;

 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
 {
  FILTER_INFO FilterInfo;
  hr = pFilter->QueryFilterInfo(&FilterInfo);
  if (FAILED(hr))
  {
   MessageBox(NULL, TEXT("Could not get the filter info"),
    TEXT("Error"), MB_OK | MB_ICONERROR);
   continue;  // 次は正しく動く可能性がある。
  }

#ifdef UNICODE
  MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
#else
  char szName[MAX_FILTER_NAME];
  int cch = WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
   MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);
  if (chh > 0)
   MessageBox(NULL, szName, TEXT("Filter Name"), MB_OK);
#endif

  // FILTER_INFO 構造体はフィルタ グラフ マネージャへのポインタを保持する。
  // その参照カウントは解放しなければならない。
  if (FilterInfo.pGraph != NULL)
  {
   FilterInfo.pGraph->Release();
  }
  pFilter->Release();
 }

 pEnum->Release();
 return S_OK;
}

デバイスとフィルタの列挙

System Device Enumerator の使い方

win32コンソールアプリケーションを空で作る

#include <dshow.h>


void main(void)
{
 printf("コンソール表示開始\n");

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("COM ライブラリを初期化エラー");
  return;
 }

 // System Device Enumerator を作成する。
 //HRESULT hr;
 ICreateDevEnum *pSysDevEnum = NULL;
 hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  IID_ICreateDevEnum, (void **)&pSysDevEnum);
 if (FAILED(hr)) {
  printf("System Device Enumerator を作成エラー");
  MessageBox(0,0,0,0);//コンソールウインドウを閉じないように
  return;
 }

 // ビデオ コンプレッサ カテゴリのクラス列挙子を取得する。
 IEnumMoniker *pEnumCat = NULL;
 hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

 if (hr == S_OK) 
 {
  // モニカを列挙する。
  IMoniker *pMoniker = NULL;
  ULONG cFetched;
  while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
  {
   IPropertyBag *pPropBag;
   hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
   if (SUCCEEDED(hr))
   {
    // フィルタのフレンドリ名を取得するには、次の処理を行う。
    VARIANT varName;
    VariantInit(&varName);
    hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    if (SUCCEEDED(hr))
    {
     // なんらかの方法で UI に名前を表示する。
     wprintf(L"%s\n", varName.bstrVal);
    }
    VariantClear(&varName);

    // フィルタのインスタンスを作成するには、次の処理を行う。
    IBaseFilter *pFilter;
    hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
     (void**)&pFilter);
    // ここでグラフにフィルタを追加する。
    // 後で忘れずに pFilter を解放すること。
    pPropBag->Release();
   }
   pMoniker->Release();
  }
  pEnumCat->Release();
 }

 pSysDevEnum->Release();

 MessageBox(0,0,TEXT("OK"),0);//コンソールウインドウを閉じないようにする

}



CLSID_VideoCompressorCategory は10個(私の環境の場合)
フィルタ カテゴリを変更する場合
フィルタ カテゴリ 一覧



2013年5月25日土曜日

フォームアプリケーションで再生



Windows フォームアプリケーションを作成する。
ボタンをひとつ貼り付けてクリックハンドラにコードを貼り付ける

#pragma once

#include <dshow.h>

namespace aviPleayetForm {

 using namespace System;
 using namespace System::ComponentModel;
 using namespace System::Collections;
 using namespace System::Windows::Forms;
 using namespace System::Data;
 using namespace System::Drawing;

 /// <summary>
 /// Form1 の概要
 /// </summary>
 public ref class Form1 : public System::Windows::Forms::Form
 {
 public:
  Form1(void)
  {
   InitializeComponent();
   //
   //TODO: ここにコンストラクター コードを追加します
   //
  }

 protected:
  /// <summary>
  /// 使用中のリソースをすべてクリーンアップします。
  /// </summary>
  ~Form1()
  {
   if (components)
   {
    delete components;
   }
  }
 private: System::Windows::Forms::Button^  button1;
 protected: 

 private:
  /// <summary>
  /// 必要なデザイナー変数です。
  /// </summary>
  System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
  /// <summary>
  /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
  /// コード エディターで変更しないでください。
  /// </summary>
  void InitializeComponent(void)
  {
   this->button1 = (gcnew System::Windows::Forms::Button());
   this->SuspendLayout();
   // 
   // button1
   // 
   this->button1->Location = System::Drawing::Point(13, 228);
   this->button1->Name = L"button1";
   this->button1->Size = System::Drawing::Size(75, 23);
   this->button1->TabIndex = 0;
   this->button1->Text = L"button1";
   this->button1->UseVisualStyleBackColor = true;
   this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
   // 
   // Form1
   // 
   this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
   this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
   this->ClientSize = System::Drawing::Size(284, 263);
   this->Controls->Add(this->button1);
   this->Name = L"Form1";
   this->Text = L"Form1";
   this->ResumeLayout(false);

  }
#pragma endregion
 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
     IGraphBuilder *pGraph = NULL;
     IMediaControl *pControl = NULL;
     IMediaEvent   *pEvent = NULL;

     // COM ライブラリを初期化する。
     HRESULT hr = CoInitialize(NULL);
     if (FAILED(hr))
     {
      printf("ERROR - Could not initialize COM library");
      return;
     }

     // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
     hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
      IID_IGraphBuilder, (void **)&pGraph);
     if (FAILED(hr))
     {
      printf("ERROR - Could not create the Filter Graph Manager.");
      return;
     }

     hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
     hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

     // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
     hr = pGraph->RenderFile(L"E:\\sampleMovie\\avi_divx5_mp3.avi", NULL);
     if (SUCCEEDED(hr))
     {
      // グラフを実行する。
      hr = pControl->Run();
      if (SUCCEEDED(hr))
      {
       // 完了するまで待機する。
       long evCode;
       pEvent->WaitForCompletion(INFINITE, &evCode);

       // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
       // 無期限にブロックする場合がある。
      }
     }
     pControl->Release();
     pEvent->Release();
     pGraph->Release();
    }
 };
}


プロジェクトの変更

「プロジェクト(P)」→「***のプロパティ(P)」→「構成プロパティ」→「リンカ」→「入力」で 「追加の依存ファイル」を追加
「親またはプロジェクトの規定値から継承」 をチェック


「プロジェクト(P)」→「***のプロパティ(P)」→「構成プロパティ」→「全般」で 共通ランタイム サポートを変更
純粋MSIL共通言語ランタイム(/clr:pure) ⇒ 共通言語ランタイム(/clr)


GraphEdit でDVD フィルタ グラフの構成を表現してみる

とりあえず表示だけしてみる


vista で表示できました。
windows 8 pro ではコーデックが無いのかどうか分かりませんが、うまくいきませんでした。
Windows Media Center Pack を 800円で購入すればいいようです。

800円か~。
フリーのデコーダーを使います。

GPL MPEG-2 Decoder を入れると windows 8 でも再生できました。
音は http://www.ac3filter.net/ の AC3Filter を使う 

2013年5月10日金曜日

msdnのサンプルコードを実行してみる

msdn->DirectShow ->ファイルの再生法


win32コンソールアプリケーションで空のプロジェクトを作成する。

ソースファイルに新しい項目c++ファイルを追加する。

ファイルの再生法 のページの下の方のサンプルコードをコピーする。
再生するファイル名の所は動画ファイルが保存されている場所に変更する。\(エスケープ文字)に注意

このまま実行してもエラーが出る。


1>------ ビルド開始: プロジェクト: win32Console001, 構成: Debug Win32 ------
1>  main.cpp
1>main.obj : error LNK2001: 外部シンボル "_IID_IMediaEvent" は未解決です。
1>main.obj : error LNK2001: 外部シンボル "_IID_IMediaControl" は未解決です。
1>main.obj : error LNK2001: 外部シンボル "_CLSID_FilterGraph" は未解決です。
1>main.obj : error LNK2001: 外部シンボル "_IID_IGraphBuilder" は未解決です。
1>c:\users\xxxx\documents\visual studio 2010\Projects\win32Console001\Debug\win32Console001.exe : fatal error LNK1120: 外部参照 4 が未解決です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

プロジェクトのプロパティーの設定をする。


DirectShow->ファースト ステップ ガイド->ビルド環境の設定 を読んで、

Dshow.hを読み込んだ時に必要になるライブラリを設定する。




Strmiids.lib
Quartz.lib

ビルドして実行する。

参考

空のCLRプロジェクトで作成した場合エラーは出ないが、
HRESULT hr = CoInitialize(NULL);
の部分で失敗しますので、
共通言語ランタイムサポートの設定を
共通言語ランタイムサポートを使用しない に変更する。


CLRプロジェクトでは、すでにランタイムで呼び出されている。ので
別スレッドで対応する、
http://msdn.microsoft.com/ja-jp/library/ms164416.aspx
共通言語ランタイムサポートを使いたい場合は。
COM ライブラリの初期化 が失敗した時の操作をコメントアウトする
#include 

HRESULT hr = CoInitialize(NULL);

void main(void)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;

    // COM ライブラリを初期化する。
    HRESULT hr = CoInitialize(NULL);
    //if (FAILED(hr))
    //{
    //    printf("ERROR - Could not initialize COM library");
    //    return;
    //}

    // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    // グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
    hr = pGraph->RenderFile(L"G:\\sampleMovie\\sample.wmv", NULL);
    if (SUCCEEDED(hr))
    {
        // グラフを実行する。
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // 完了するまで待機する。
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

            // 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
            // 無期限にブロックする場合がある。
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}