From e0a205d44a437a14bd56bd96a75a8f125ca03551 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 21 Sep 2013 12:57:03 +0000 Subject: [PATCH] [MCIAVI32] * Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60269 --- reactos/dll/win32/mciavi32/CMakeLists.txt | 3 +- reactos/dll/win32/mciavi32/mciavi.c | 300 +++++++++++--------- reactos/dll/win32/mciavi32/mmoutput.c | 10 +- reactos/dll/win32/mciavi32/private_mciavi.h | 3 +- reactos/media/doc/README.WINE | 2 +- 5 files changed, 169 insertions(+), 149 deletions(-) diff --git a/reactos/dll/win32/mciavi32/CMakeLists.txt b/reactos/dll/win32/mciavi32/CMakeLists.txt index adc7a9b14ea..78f9cabfa99 100644 --- a/reactos/dll/win32/mciavi32/CMakeLists.txt +++ b/reactos/dll/win32/mciavi32/CMakeLists.txt @@ -9,10 +9,9 @@ list(APPEND SOURCE mciavi.c mmoutput.c wnd.c - mciavi_res.rc ${CMAKE_CURRENT_BINARY_DIR}/mciavi32.def) -add_library(mciavi32 SHARED ${SOURCE}) +add_library(mciavi32 SHARED ${SOURCE} mciavi_res.rc) set_module_type(mciavi32 win32dll) target_link_libraries(mciavi32 wine) add_importlibs(mciavi32 msvfw32 winmm user32 gdi32 msvcrt kernel32 ntdll) diff --git a/reactos/dll/win32/mciavi32/mciavi.c b/reactos/dll/win32/mciavi32/mciavi.c index fd51e8196d8..07afa3175fc 100644 --- a/reactos/dll/win32/mciavi32/mciavi.c +++ b/reactos/dll/win32/mciavi32/mciavi.c @@ -87,7 +87,6 @@ static DWORD MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp) InitializeCriticalSection(&wma->cs); wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs"); - wma->ack_event = CreateEventW(NULL, FALSE, FALSE, NULL); wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); wma->wDevID = modp->wDeviceID; wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0); @@ -121,7 +120,6 @@ static DWORD MCIAVI_drvClose(DWORD dwDevID) mciSetDriverData(dwDevID, 0); mciFreeCommandResource(wma->wCommandTable); - CloseHandle(wma->ack_event); CloseHandle(wma->hStopEvent); LeaveCriticalSection(&wma->cs); @@ -336,149 +334,34 @@ DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) return dwRet; } -static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms); - -struct MCIAVI_play_data +static double currenttime_us(void) { - MCIDEVICEID wDevID; - DWORD flags; - MCI_PLAY_PARMS params; -}; - -/* - * MCIAVI_mciPlay_thread - * - * FIXME: probably should use a common worker thread created at the driver - * load time and queue all async commands to it. - */ -static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg) -{ - struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg; - DWORD ret; - - TRACE("In thread before async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); - ret = MCIAVI_mciPlay(data->wDevID, data->flags | MCI_WAIT, &data->params); - TRACE("In thread after async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); - - HeapFree(GetProcessHeap(), 0, data); - return ret; -} - -/* - * MCIAVI_mciPlay_async - */ -static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams) -{ - HANDLE handle, ack_event = wma->ack_event; - struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data)); - - if (!data) return MCIERR_OUT_OF_MEMORY; - - data->wDevID = wma->wDevID; - data->flags = dwFlags; - data->params = *lpParams; - - if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL))) - { - WARN("Couldn't create thread for async play, playing synchronously\n"); - return MCIAVI_mciPlay_thread(data); - } - SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); - CloseHandle(handle); - /* wait until the thread starts up, so the app could see a changed status */ - WaitForSingleObject(ack_event, INFINITE); - TRACE("Async play has started\n"); - return 0; + LARGE_INTEGER lc, lf; + QueryPerformanceCounter(&lc); + QueryPerformanceFrequency(&lf); + return (lc.QuadPart * 1000000) / lf.QuadPart; } /*************************************************************************** - * MCIAVI_mciPlay [internal] + * MCIAVI_player [internal] */ -static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +static DWORD MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) { - WINE_MCIAVI *wma; - DWORD frameTime; DWORD dwRet; LPWAVEHDR waveHdr = NULL; unsigned i, nHdr = 0; - DWORD dwFromFrame, dwToFrame; DWORD numEvents = 1; HANDLE events[2]; - - TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); - - if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; - - wma = MCIAVI_mciGetOpenDev(wDevID); - if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; - if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; - if (dwFlags & MCI_TEST) return 0; + double next_frame_us; EnterCriticalSection(&wma->cs); - if (!wma->hFile) - { - LeaveCriticalSection(&wma->cs); - return MCIERR_FILE_NOT_FOUND; - } - if (!wma->hWndPaint) - { - LeaveCriticalSection(&wma->cs); - return MCIERR_NO_WINDOW; - } - - LeaveCriticalSection(&wma->cs); - - if (!(dwFlags & MCI_WAIT)) - return MCIAVI_mciPlay_async(wma, dwFlags, lpParms); - - if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) - ShowWindow(wma->hWndPaint, SW_SHOWNA); - - EnterCriticalSection(&wma->cs); - - dwFromFrame = wma->dwCurrVideoFrame; - dwToFrame = wma->dwPlayableVideoFrames - 1; - - if (dwFlags & MCI_FROM) { - dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); - } - if (dwFlags & MCI_TO) { - dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); - } - if (dwToFrame >= wma->dwPlayableVideoFrames) - dwToFrame = wma->dwPlayableVideoFrames - 1; - - TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); - - wma->dwCurrVideoFrame = dwFromFrame; - wma->dwToVideoFrame = dwToFrame; - - /* if already playing exit */ - if (wma->dwStatus == MCI_MODE_PLAY) - { - LeaveCriticalSection(&wma->cs); - SetEvent(wma->ack_event); - return 0; - } - if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame) { dwRet = 0; - SetEvent(wma->ack_event); goto mci_play_done; } - wma->dwStatus = MCI_MODE_PLAY; - /* signal the state change */ - SetEvent(wma->ack_event); - - if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN)) - FIXME("Unsupported flag %08x\n", dwFlags); - - /* time is in microseconds, we should convert it to milliseconds */ - frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000; - events[0] = wma->hStopEvent; if (wma->lpWaveFormat) { if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0) @@ -496,39 +379,45 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms } } + next_frame_us = currenttime_us(); while (wma->dwStatus == MCI_MODE_PLAY) { HDC hDC; - DWORD tc, delta; + double tc, delta; DWORD ret; - tc = GetTickCount(); + tc = currenttime_us(); hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; if (hDC) { - MCIAVI_PaintFrame(wma, hDC); + while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame){ + double dur; + ++wma->dwCurrVideoFrame; + dur = MCIAVI_PaintFrame(wma, hDC); + if(!dur) + break; + next_frame_us += dur; + TRACE("next_frame: %f\n", next_frame_us); + } ReleaseDC(wma->hWndPaint, hDC); } + if(wma->dwCurrVideoFrame >= wma->dwToVideoFrame) + break; if (wma->lpWaveFormat) - MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); + MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); - delta = GetTickCount() - tc; - if (delta < frameTime) - delta = frameTime - delta; + tc = currenttime_us(); + if(tc < next_frame_us) + delta = next_frame_us - tc; else delta = 0; LeaveCriticalSection(&wma->cs); - ret = WaitForMultipleObjects(numEvents, events, FALSE, delta); + ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000); EnterCriticalSection(&wma->cs); if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break; - - if (wma->dwCurrVideoFrame < dwToFrame) - wma->dwCurrVideoFrame++; - else - break; } if (wma->lpWaveFormat) { @@ -568,12 +457,145 @@ mci_play_done: if (dwFlags & MCI_NOTIFY) { TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback); mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), - wDevID, MCI_NOTIFY_SUCCESSFUL); + wma->wDevID, MCI_NOTIFY_SUCCESSFUL); } LeaveCriticalSection(&wma->cs); return dwRet; } +struct MCIAVI_play_data +{ + WINE_MCIAVI *wma; + DWORD flags; + MCI_PLAY_PARMS params; /* FIXME: notify via wma->hCallback like the other MCI drivers */ +}; + +/* + * MCIAVI_mciPlay_thread + * + * FIXME: probably should use a common worker thread created at the driver + * load time and queue all async commands to it. + */ +static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg) +{ + struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg; + DWORD ret; + + TRACE("In thread before async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags); + ret = MCIAVI_player(data->wma, data->flags, &data->params); + TRACE("In thread after async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags); + + HeapFree(GetProcessHeap(), 0, data); + return ret; +} + +/* + * MCIAVI_mciPlay_async + */ +static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams) +{ + HANDLE handle; + struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data)); + + if (!data) return MCIERR_OUT_OF_MEMORY; + + data->wma = wma; + data->flags = dwFlags; + if (dwFlags & MCI_NOTIFY) + data->params.dwCallback = lpParams->dwCallback; + + if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL))) + { + WARN("Couldn't create thread for async play, playing synchronously\n"); + return MCIAVI_mciPlay_thread(data); + } + SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); + CloseHandle(handle); + return 0; +} + +/*************************************************************************** + * MCIAVI_mciPlay [internal] + */ +static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +{ + WINE_MCIAVI *wma; + DWORD dwRet; + DWORD dwFromFrame, dwToFrame; + + TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); + + if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIAVI_mciGetOpenDev(wDevID); + if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; + if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_TEST) return 0; + + if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN|MCI_MCIAVI_PLAY_FULLBY2)) + FIXME("Unsupported flag %08x\n", dwFlags); + + EnterCriticalSection(&wma->cs); + + if (!wma->hFile) + { + LeaveCriticalSection(&wma->cs); + return MCIERR_FILE_NOT_FOUND; + } + if (!wma->hWndPaint) + { + LeaveCriticalSection(&wma->cs); + return MCIERR_NO_WINDOW; + } + + dwFromFrame = wma->dwCurrVideoFrame; + dwToFrame = wma->dwPlayableVideoFrames - 1; + + if (dwFlags & MCI_FROM) { + dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); + } + if (dwFlags & MCI_TO) { + dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); + } + if (dwToFrame >= wma->dwPlayableVideoFrames) + dwToFrame = wma->dwPlayableVideoFrames - 1; + + TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); + + wma->dwCurrVideoFrame = dwFromFrame; + wma->dwToVideoFrame = dwToFrame; + + LeaveCriticalSection(&wma->cs); + + if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) + ShowWindow(wma->hWndPaint, SW_SHOWNA); + + EnterCriticalSection(&wma->cs); + + /* if already playing exit */ + if (wma->dwStatus == MCI_MODE_PLAY) + { + LeaveCriticalSection(&wma->cs); + return 0; + } + + wma->dwStatus = MCI_MODE_PLAY; + + LeaveCriticalSection(&wma->cs); + + if (dwFlags & MCI_WAIT) + return MCIAVI_player(wma, dwFlags, lpParms); + + dwRet = MCIAVI_mciPlay_async(wma, dwFlags, lpParms); + + if (dwRet) { + EnterCriticalSection(&wma->cs); + wma->dwStatus = MCI_MODE_STOP; + LeaveCriticalSection(&wma->cs); + } + return dwRet; +} + /*************************************************************************** * MCIAVI_mciStop [internal] */ diff --git a/reactos/dll/win32/mciavi32/mmoutput.c b/reactos/dll/win32/mciavi32/mmoutput.c index 8c86441d364..c8a63ffe495 100644 --- a/reactos/dll/win32/mciavi32/mmoutput.c +++ b/reactos/dll/win32/mciavi32/mmoutput.c @@ -600,20 +600,20 @@ void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr) } } -LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) +double MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) { void* pBitmapData; LPBITMAPINFO pBitmapInfo; if (!hDC || !wma->inbih) - return TRUE; + return 0; TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame); if (wma->dwCurrVideoFrame != wma->dwCachedFrame) { if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset) - return FALSE; + return 0; if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize) { @@ -626,7 +626,7 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) wma->outbih, wma->outdata) != ICERR_OK) { WARN("Decompression error\n"); - return FALSE; + return 0; } } @@ -648,5 +648,5 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) wma->source.right - wma->source.left, wma->source.bottom - wma->source.top, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); - return TRUE; + return (wma->ash_video.dwScale / (double)wma->ash_video.dwRate) * 1000000; } diff --git a/reactos/dll/win32/mciavi32/private_mciavi.h b/reactos/dll/win32/mciavi32/private_mciavi.h index 804702f1b51..fc04be43c04 100644 --- a/reactos/dll/win32/mciavi32/private_mciavi.h +++ b/reactos/dll/win32/mciavi32/private_mciavi.h @@ -83,7 +83,6 @@ typedef struct { /* data for the background mechanism */ CRITICAL_SECTION cs; HANDLE hStopEvent; - HANDLE ack_event; /* acknowledge that an async command has started */ } WINE_MCIAVI; extern HINSTANCE MCIAVI_hInstance DECLSPEC_HIDDEN; @@ -100,7 +99,7 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) DECLSPEC_HIDDEN; DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr) DECLSPEC_HIDDEN; BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma) DECLSPEC_HIDDEN; void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr) DECLSPEC_HIDDEN; -LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) DECLSPEC_HIDDEN; +double MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) DECLSPEC_HIDDEN; /* mciavi.c */ WINE_MCIAVI* MCIAVI_mciGetOpenDev(UINT wDevID) DECLSPEC_HIDDEN; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 9b9d5ba944f..49ccd770419 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -97,7 +97,7 @@ reactos/dll/win32/localspl # Synced to Wine-1.5.26 reactos/dll/win32/localui # Synced to Wine-1.7.1 reactos/dll/win32/lz32 # Synced to Wine-1.5.19 reactos/dll/win32/mapi32 # Synced to Wine-1.7.1 -reactos/dll/win32/mciavi32 # Synced to Wine-1.5.4 +reactos/dll/win32/mciavi32 # Synced to Wine-1.7.1 reactos/dll/win32/mcicda # Synced to Wine-1.5.19 reactos/dll/win32/mciqtz32 # Synced to Wine-1.5.4 reactos/dll/win32/mciseq # Synced to Wine-1.5.4