AVIファイル内のビデオストリームを、Direct3D にて表示

AVIファイル内のオーディオストリームを、DirectSound にてストリーム再生

プロジェクトダウンロード(VC++2005)

【プログラム主要部分1(AVITextue.cpp)】


#include "stdafx.h"
#include <d3dx9.h>
#include "D3DQuickLib.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSQuickLib.h"
#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>    // stat 関数を使う為インクルード
#include <crtdbg.h>
#include <TCHAR.h>
#include <vfw.h>
#include <mmreg.h>
#include <msacm.h>

#include "AVIVideoTexture.h"
#include "PCMStreamForAVIStream.h"

#pragma comment (lib, "msacm32.lib")
#pragma comment (lib, "winmm.lib")
#pragma comment (lib, "vfw32.lib")

//
//    Prototypes.
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK IOProc(LPMMIOINFO lpMMIOInfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2);

CD3DEnv    *g_pD3DEnv = NULL;
CBillboard    *g_pBillboard = NULL;
CAVIVideoTexture    *g_pVideoTexture = NULL;

CDSoundEnv    *g_pDSoundEnv = NULL;
CPCMStreamForAVIStream    *g_pAudioStream = NULL;

static char * g_lpData = NULL;
static long    g_cfileSize;
CRITICAL_SECTION    g_csSema;

float            g_fTime = 0;
//------------------------------------------------------------
// Name: FrameMove
// Desc: アニメーションを行う。
//        UpdateScene 関数(d3dmain.cpp) からコールバックされる。
//------------------------------------------------------------
void FrameMove(float timeElapsed)
{
    g_fTime = timeElapsed;
}

//------------------------------------------------------------
// Name: RenderScene
// Desc: レンダリングを行う。
//        UpdateScene 関数(d3dmain.cpp) からコールバックされる。
//------------------------------------------------------------
void RenderScene(LPDIRECT3DDEVICE9 lpd3ddev)
{
    Yield();
    g_pVideoTexture->Lock();
    LPDIRECT3DTEXTURE9    pTex = g_pVideoTexture->GetRenderableTexture();
    if (pTex != NULL){
        int    w, h;
        g_pVideoTexture->GetRenderableTextureSize(&w,&h);
        g_pBillboard->Render(lpd3ddev,0,0,640,480,0,0,w,h,pTex);
        lpd3ddev->SetTexture(0,NULL);
    }
    g_pVideoTexture->Unlock();
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = "AVITextureAndAVIStreamSound";
    wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wcex);

    HWND hWnd;
    hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,"AVITexture with Sound -- Play AVI Movie",
                WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
                CW_USEDEFAULT,0,640,480,NULL,NULL,hInstance,NULL);
    if( !hWnd )
        return FALSE;

    RECT    bounds,client;
    GetWindowRect(hWnd,&bounds);
    GetClientRect(hWnd,&client);
    MoveWindow(hWnd,bounds.left,bounds.top,
        640 * 2 - client.right,
        480 * 2 - client.bottom,
        false );

    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );

    InitializeCriticalSection(&g_csSema);
    g_pD3DEnv = new CD3DEnv();
    if (SUCCEEDED(g_pD3DEnv->InitD3D(hWnd))){
        PAVIFILE   lpAviFile = NULL;
        PAVISTREAM lpVideoStream = NULL;
        PAVISTREAM lpAudioStream = NULL;
        struct    _stat    status;
        if (0 == _tstat(_T("test.avi"),&status)){
            g_cfileSize = status.st_size;
            g_lpData = new char[g_cfileSize];
            FILE    *fp = fopen(_T("test.avi"),_T("rb"));
            if (fp != NULL){
                fread(g_lpData,g_cfileSize,1,fp);
                fclose(fp);

                //    mci:カスタムIOProc のインストール
                mmioInstallIOProc(mmioFOURCC('M', 'E', 'V', ' '), (LPMMIOPROC)IOProc,
                                    MMIO_INSTALLPROC | MMIO_GLOBALPROC);

                AVIFileInit();
                
                if (AVIFileOpen(&lpAviFile, TEXT("test.MEV+"), OF_READ, NULL) != 0)
                    return  -1;
                if (AVIFileGetStream(lpAviFile, &lpVideoStream, streamtypeVIDEO, 0) != 0)
                    lpVideoStream = NULL;
                if (AVIFileGetStream(lpAviFile, &lpAudioStream, streamtypeAUDIO, 0) != 0)
                    lpAudioStream = NULL;
            }
        }
        if (lpAudioStream != NULL){
            g_pDSoundEnv = new CDSoundEnv(2,44100,16);
            if (g_pDSoundEnv){
                if (SUCCEEDED(g_pDSoundEnv->Initialize(hWnd,DSSCL_PRIORITY))){
                    g_pAudioStream = new CPCMStreamForAVIStream(g_pDSoundEnv,lpAudioStream);
                    if (g_pAudioStream){
                        g_pAudioStream->Prepare();
                    }
                }
            }
        }
        if (lpVideoStream != NULL){
            g_pVideoTexture = new CAVIVideoTexture(g_pD3DEnv,lpVideoStream);
        }
        g_pBillboard = new CBillboard(g_pD3DEnv,0);
        g_pD3DEnv->ReloadGraphics();
    }
    MSG        msg;
    while(true){
        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
            if(msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }else{
            g_pD3DEnv->UpdateScene(FrameMove,RenderScene);
            if (!g_pVideoTexture->IsPlaying() && !g_pAudioStream->IsPlaying()){
                Sleep(100);
                g_pVideoTexture->Rewind();
                g_pAudioStream->Rewind();
                g_pVideoTexture->Run();
                g_pAudioStream->Play();
            }
        }
    }
    SAFE_DELETE(g_pBillboard);
    SAFE_DELETE(g_pVideoTexture);
    SAFE_DELETE(g_pD3DEnv);
    EnterCriticalSection(&g_csSema);
    if (g_lpData != NULL){
        mmioInstallIOProc(mmioFOURCC('M', 'E', 'V', ' '), NULL,MMIO_REMOVEPROC);
        delete    g_lpData;
        g_lpData = NULL;
    }
    LeaveCriticalSection(&g_csSema);
    DeleteCriticalSection(&g_csSema);
    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch (message){
        case    WM_SIZE:
            if (SIZE_MAXIMIZED == wParam){
                g_pD3DEnv->ForceFullscreen();
            }
            break;
        case    WM_SETCURSOR:
            if (g_pD3DEnv->IsWindowed())
                ::SetCursor(::LoadCursor(NULL,IDC_ARROW));
            else
                ::SetCursor(NULL);
            break;
        case    WM_SYSCHAR:
            if (lParam&0x20000000){
                if (wParam == '\x0d'){
                    g_pD3DEnv->ToggleFullscreen();
                    break;
                }
            }
            return DefWindowProc( hWnd, message, wParam, lParam );
        case    WM_SYSCOMMAND:
            if (!g_pD3DEnv->IsWindowed()){    //    フルスクリーン時
                if (wParam != SC_CLOSE)
                    break;

                //    Windowが閉じられる前にWindowモードに戻しておく。
                g_pD3DEnv->ToggleFullscreen();
                Sleep(100);
            }
            return DefWindowProc( hWnd, message, wParam, lParam );

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

//
//    mmio: IOProc
//
LRESULT CALLBACK IOProc(LPMMIOINFO lpMMIOInfo, UINT uMessage, LPARAM
lParam1, LPARAM lParam2)
{
  static BOOL alreadyOpened = FALSE;

  switch (uMessage) {
  case MMIOM_OPEN:
      if (alreadyOpened)
          return 0;
      alreadyOpened = TRUE;

      lpMMIOInfo->lDiskOffset = 0;
      return 0;

   case MMIOM_CLOSE:
       return 0;

   case MMIOM_READ:{
            LPARAM    dataRead = 0;
               EnterCriticalSection(&g_csSema);
            if (g_lpData != NULL){
                dataRead = lParam2;
                memcpy((void *)lParam1, g_lpData+lpMMIOInfo->lDiskOffset, lParam2);
                lpMMIOInfo->lDiskOffset += lParam2;
                dataRead = lParam2;
            }
            LeaveCriticalSection(&g_csSema);
            return (dataRead);
        }
   case MMIOM_SEEK:
       switch (lParam2) {
       case SEEK_SET:
           lpMMIOInfo->lDiskOffset = lParam1;
           break;

       case SEEK_CUR:
           lpMMIOInfo->lDiskOffset += lParam1;
           break;

       case SEEK_END:
           lpMMIOInfo->lDiskOffset = g_cfileSize - lParam1;
           break;
       }
       return lpMMIOInfo->lDiskOffset;

   default:
       return -1;
   }
}

 

音声の再生には、Step3 で用いた CPCMStreamForAVIStreamクラスを使用し、 映像の表示には、Step4 で用いた CAVIVideoTexture クラスを使用します。

 

戻る