// MemoryAviPlayback_mci.cpp : MCI を使ってメモリ上のAVIファイルを再生する。 #include "stdafx.h" #include <vfw.h> #include <mmreg.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <crtdbg.h> #include <TCHAR.h> #pragma comment (lib, "winmm.lib") #pragma comment (lib, "vfw32.lib") #include "MemoryAviPlayback_mci.h" #define MAX_LOADSTRING 100 static char * g_lpData = NULL; static long g_cfileSize; // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス // このコード モジュールに含まれる関数の宣言を転送します: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK IOProc(LPMMIOINFO lpMMIOInfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2); CRITICAL_SECTION g_csSema; BOOL g_bRepeat = FALSE; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 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 = _T("avi realtime audio stream"); wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wcex); InitializeCriticalSection(&g_csSema); HWND hWnd; hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("avi realtime audio stream"), 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 ); // ファイル読み込み 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); // 再生開始 mciSendString("open test.MEV+ type avivideo alias vp01",NULL,0,NULL); TCHAR tmp[MAX_PATH]; _stprintf_s(tmp,MAX_PATH,_T("window vp01 handle %d"),(DWORD)hWnd); mciSendString(tmp,NULL,0,NULL); mciSendString("play vp01 notify",NULL,0,hWnd); g_bRepeat = true; }else{ DestroyWindow(hWnd); } // メイン メッセージ ループ: MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } g_bRepeat = false; EnterCriticalSection(&g_csSema); if (g_lpData != NULL){ mciSendString("close vp01",NULL,0,NULL); mmioInstallIOProc(mmioFOURCC('M', 'E', 'V', ' '), NULL,MMIO_REMOVEPROC); delete g_lpData; } LeaveCriticalSection(&g_csSema); return (int)msg.wParam; } // // 関数:WndProc // 説明:ウインドウに渡されたイベントのハンドラ // LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch (message){ case WM_DESTROY: PostQuitMessage(0); break; case MM_MCINOTIFY: // とりあえずループ再生専用 if (g_bRepeat) mciSendString("play vp01 from 0 notify",NULL,0,hWnd); return DefWindowProc(hWnd, message, wParam, lParam); 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 += (LONG)lParam2; dataRead = lParam2; } LeaveCriticalSection(&g_csSema); return (dataRead); } case MMIOM_SEEK: switch (lParam2) { case SEEK_SET: lpMMIOInfo->lDiskOffset = (LONG)lParam1; break; case SEEK_CUR: lpMMIOInfo->lDiskOffset += (LONG)lParam1; break; case SEEK_END: lpMMIOInfo->lDiskOffset = g_cfileSize - lParam1; break; } return lpMMIOInfo->lDiskOffset; default: return -1; } }