📄 mmoutput.c
字号:
wma->dwPlayableVideoFrames * sizeof(struct MMIOPos)); if (!wma->lpVideoIndex) { WARN("Can't alloc video index array\n"); return FALSE; } wma->dwPlayableAudioBlocks = 0; wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wma->dwPlayableVideoFrames * sizeof(struct MMIOPos)); if (!wma->lpAudioIndex) { WARN("Can't alloc audio index array\n"); return FALSE; } alb.numAudioBlocks = alb.numVideoFrames = 0; alb.inVideoSize = alb.inAudioSize = 0; alb.numAudioAllocated = 0; while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) { if (mmckInfo.fccType == listtypeAVIRECORD) { MMCKINFO tmp; while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) { MCIAVI_AddFrame(wma, &tmp, &alb); mmioAscend(wma->hFile, &tmp, 0); } } else { MCIAVI_AddFrame(wma, &mmckInfo, &alb); } mmioAscend(wma->hFile, &mmckInfo, 0); } if (alb.numVideoFrames != wma->dwPlayableVideoFrames) { WARN("Found %ld video frames (/%ld), reducing playable frames\n", alb.numVideoFrames, wma->dwPlayableVideoFrames); wma->dwPlayableVideoFrames = alb.numVideoFrames; } wma->dwPlayableAudioBlocks = alb.numAudioBlocks; if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) { WARN("inVideoSize=%ld suggestedSize=%ld\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize); wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize; } if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) { WARN("inAudioSize=%ld suggestedSize=%ld\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize); wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize; } wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize); if (!wma->indata) { WARN("Can't alloc input buffer\n"); return FALSE; } return TRUE;}BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma){ DWORD outSize; FOURCC fcc = wma->ash_video.fccHandler; /* check uncompressed AVI */ if ((fcc == mmioFOURCC('D','I','B',' ')) || (fcc == mmioFOURCC('R','L','E',' '))) { wma->hic = 0; MCIAVI_DrawFrame(wma); return TRUE; } /* get the right handle */ if (fcc == 0) fcc = wma->inbih->biCompression; if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C'); /* try to get a decompressor for that type */ wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS); if (!wma->hic) { WARN("Can't locate codec for the file\n"); return FALSE; } outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize); if (!wma->outbih) { WARN("Can't alloc output BIH\n"); return FALSE; } if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) { WARN("Can't open decompressor\n"); return FALSE; } TRACE("bih.biSize=%ld\n", wma->outbih->biSize); TRACE("bih.biWidth=%ld\n", wma->outbih->biWidth); TRACE("bih.biHeight=%ld\n", wma->outbih->biHeight); TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes); TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount); TRACE("bih.biCompression=%lx\n", wma->outbih->biCompression); TRACE("bih.biSizeImage=%ld\n", wma->outbih->biSizeImage); TRACE("bih.biXPelsPerMeter=%ld\n", wma->outbih->biXPelsPerMeter); TRACE("bih.biYPelsPerMeter=%ld\n", wma->outbih->biYPelsPerMeter); TRACE("bih.biClrUsed=%ld\n", wma->outbih->biClrUsed); TRACE("bih.biClrImportant=%ld\n", wma->outbih->biClrImportant); wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage); if (!wma->outdata) { WARN("Can't alloc output buffer\n"); return FALSE; } if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN, (DWORD)wma->inbih, (DWORD)wma->outbih) != ICERR_OK) { WARN("Can't begin decompression\n"); return FALSE; } MCIAVI_DrawFrame(wma); return TRUE;}static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2){ WINE_MCIAVI* wma = (WINE_MCIAVI*)dwInstance; switch (uMsg) { case WOM_OPEN: case WOM_CLOSE: break; case WOM_DONE: InterlockedIncrement(&wma->dwEventCount); TRACE("Returning waveHdr=%lx\n", dwParam1); SetEvent(wma->hEvent); break; default: ERR("Unknown uMsg=%d\n", uMsg); }}DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr){ DWORD dwRet; LPWAVEHDR waveHdr; unsigned i; dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat, (DWORD)MCIAVI_waveCallback, (DWORD)wma, CALLBACK_FUNCTION); if (dwRet != 0) { TRACE("Can't open low level audio device %ld\n", dwRet); dwRet = MCIERR_DEVICE_OPEN; wma->hWave = 0; goto cleanUp; } /* FIXME: should set up a heuristic to compute the number of wave headers * to be used... */ *nHdr = 7; waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize)); if (!waveHdr) { TRACE("Can't alloc wave headers\n"); dwRet = MCIERR_DEVICE_OPEN; goto cleanUp; } for (i = 0; i < *nHdr; i++) { /* other fields are zero:ed on allocation */ waveHdr[i].lpData = (char*)waveHdr + *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize; waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize; if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) { dwRet = MCIERR_INTERNAL; goto cleanUp; } } if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) { FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n"); } wma->dwCurrAudioBlock = 0; wma->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); wma->dwEventCount = *nHdr - 1; *pWaveHdr = waveHdr; cleanUp: return dwRet;}void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr){ TRACE("%ld (ec=%lu)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount); /* push as many blocks as possible => audio gets priority */ while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY && wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) { unsigned whidx = wma->dwCurrAudioBlock % nHdr; ResetEvent(wma->hEvent); if (InterlockedDecrement(&wma->dwEventCount) < 0 || !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset) break; mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET); mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize); waveHdr[whidx].dwFlags &= ~WHDR_DONE; waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize; waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR)); wma->dwCurrAudioBlock++; } InterlockedIncrement(&wma->dwEventCount);}LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC){ void* pBitmapData = NULL; LPBITMAPINFO pBitmapInfo = NULL; HDC hdcMem; HBITMAP hbmOld; int nWidth; int nHeight; if (!hDC || !wma->inbih) return TRUE; TRACE("Painting frame %lu\n", wma->dwCurrVideoFrame); if (wma->hic) { pBitmapData = wma->outdata; pBitmapInfo = (LPBITMAPINFO)wma->outbih; nWidth = wma->outbih->biWidth; nHeight = wma->outbih->biHeight; } else { pBitmapData = wma->indata; pBitmapInfo = (LPBITMAPINFO)wma->inbih; nWidth = wma->inbih->biWidth; nHeight = wma->inbih->biHeight; } if (!wma->hbmFrame) wma->hbmFrame = CreateCompatibleBitmap(hDC, nWidth, nHeight); SetDIBits(hDC, wma->hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); hdcMem = CreateCompatibleDC(hDC); hbmOld = SelectObject(hdcMem, wma->hbmFrame); BitBlt(hDC, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); return TRUE;}LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma){ HDC hDC; TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame); if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset) return FALSE; EnterCriticalSection(&wma->cs); mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET); mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize); /* FIXME ? */ wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize; if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata, wma->outbih, wma->outdata) != ICERR_OK) { LeaveCriticalSection(&wma->cs); WARN("Decompression error\n"); return FALSE; } if (IsWindowVisible(wma->hWnd) && (hDC = GetDC(wma->hWnd)) != 0) { MCIAVI_PaintFrame(wma, hDC); ReleaseDC(wma->hWnd, hDC); } LeaveCriticalSection(&wma->cs); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -