bool Wave::Open(const LPTSTR strFileName, const WAVEFORMATEX* wavFmt, const DWORD dwFlags) { HMMIO hWav; // WAVE's handle MMCKINFO child, parent; LPDIRECTSOUNDBUFFER wavFileBuffer; // temporary buffer LPDIRECTSOUNDBUFFER *p_wavFileBuffer; p_wavFileBuffer = &wavFileBuffer; hWav = mmioOpen(strFileName, NULL, MMIO_READ | MMIO_ALLOCBUF); if (hWav==NULL) { //ErrorBox("Could not find / load file at mmioOpen()"); return false; } parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); // descend to riff if (mmioDescend(hWav, &parent, NULL, MMIO_FINDRIFF)) { //ErrorBox("Could not descend to RIFF, file is corrupt or not a WAVE file."); mmioClose(hWav, 0); return false; } // descend to WAVEfmt child.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hWav, &child, &parent, 0)) { //ErrorBox("Could not descend to WAVEfmt, file is corrupt or not a WAVE file."); mmioClose(hWav, 0); return false; } // open <strong class="highlight">WAV</strong> file for reading, check to make sure format is correct if (mmioRead(hWav, (char*)&wfmex, sizeof(WAVEFORMATEX)) != sizeof(WAVEFORMATEX)) { //ErrorBox("Error reading <strong class="highlight">WAV</strong> format, file is corrupt or not a WAVE file."); mmioClose(hWav, 0); return false; } if (wfmex.wFormatTag != WAVE_FORMAT_PCM) { //ErrorBox("WAVE file is not of PCM format."); mmioClose(hWav, 0); return false; } if (mmioAscend(hWav, &child, 0)) { //ErrorBox("Error ascending to WAVE data."); mmioClose(hWav, 0); return false; } // descend to data child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hWav, &child, &parent, MMIO_FINDCHUNK)) { //ErrorBox("Error descending to the WAVE data level."); mmioClose(hWav, 0); return false; } // verification complete, now <strong class="highlight">read</strong> information // allocate memory and load pointer if (!(pData = new UCHAR [child.cksize])) { //ErrorBox("Insufficient memory to load WAVE file."); mmioClose(hWav, 0); return false; } // <strong class="highlight">read</strong> WAVE data long lBytesRead; lBytesRead = mmioRead(hWav, (char*)pData, child.cksize); if (lBytesRead<0) { //ErrorBox("Unable to <strong class="highlight">read</strong> WAVE file data."); mmioClose(hWav, 0); return false; } mmioClose(hWav, 0); // place our information on our buffer, prepare our description for direct sound dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwBufferBytes = child.cksize; // size of buffer is equal to the wave's size dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE | // Force loading in software so we can't loose it. DSBCAPS_GLOBALFOCUS | // Don't mute on 'lostfocus' DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; dsbd.lpwfxFormat = &wfmex; dsbd.dwReserved = NULL; dsbd.guid3DAlgorithm = DS3DALG_DEFAULT; return true; }
static HRESULT WINAPI IDirectMusicChordMapImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) { DMUS_PRIVATE_CHUNK Chunk; DWORD StreamSize, StreamCount, ListSize[1], ListCount[1]; LARGE_INTEGER liMove; /* used when skipping chunks */ TRACE("(%p, %p)\n", pStream, pDesc); /* FIXME: should this be determined from stream? */ pDesc->dwValidData |= DMUS_OBJ_CLASS; memcpy (&pDesc->guidClass, &CLSID_DirectMusicChordMap, sizeof(CLSID)); IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case FOURCC_RIFF: { IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); StreamSize = Chunk.dwSize - sizeof(FOURCC); StreamCount = 0; if (Chunk.fccID == DMUS_FOURCC_CHORDMAP_FORM) { TRACE_(dmfile)(": chord map form\n"); do { IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { case DMUS_FOURCC_GUID_CHUNK: { TRACE_(dmfile)(": GUID chunk\n"); pDesc->dwValidData |= DMUS_OBJ_OBJECT; IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL); break; } case DMUS_FOURCC_VERSION_CHUNK: { TRACE_(dmfile)(": version chunk\n"); pDesc->dwValidData |= DMUS_OBJ_VERSION; IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL); break; } case DMUS_FOURCC_CATEGORY_CHUNK: { TRACE_(dmfile)(": category chunk\n"); pDesc->dwValidData |= DMUS_OBJ_CATEGORY; IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL); break; } case FOURCC_LIST: { IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { /* evil M$ UNFO list, which can (!?) contain INFO elements */ case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); switch (Chunk.fccID) { /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes (though strings seem to be valid unicode) */ case mmioFOURCC('I','N','A','M'): case DMUS_FOURCC_UNAM_CHUNK: { TRACE_(dmfile)(": name chunk\n"); pDesc->dwValidData |= DMUS_OBJ_NAME; IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL); break; } case mmioFOURCC('I','A','R','T'): case DMUS_FOURCC_UART_CHUNK: { TRACE_(dmfile)(": artist chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','O','P'): case DMUS_FOURCC_UCOP_CHUNK: { TRACE_(dmfile)(": copyright chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','S','B','J'): case DMUS_FOURCC_USBJ_CHUNK: { TRACE_(dmfile)(": subject chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','M','T'): case DMUS_FOURCC_UCMT_CHUNK: { TRACE_(dmfile)(": comment chunk (ignored)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC); IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize); } while (StreamCount < StreamSize); } else { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = StreamSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return E_FAIL; } TRACE_(dmfile)(": reading finished\n"); break; } default: { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return DMUS_E_INVALIDFILE; } } TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc)); return S_OK; }
// 10 hours should be enough padding to take care of all eventualities #define RTPADDING 360000000000i64 //////////////////////////////////////////////////////////////////////////////// // Constructor //////////////////////////////////////////////////////////////////////////////// ILAVDecoder *CreateDecoderQuickSync() { return new CDecQuickSync(); } //////////////////////////////////////////////////////////////////////////////// // Codec FourCC map //////////////////////////////////////////////////////////////////////////////// static const FOURCC FourCC_MPG1 = mmioFOURCC('M','P','G','1'); static const FOURCC FourCC_MPG2 = mmioFOURCC('M','P','G','2'); static const FOURCC FourCC_VC1 = mmioFOURCC('W','V','C','1'); static const FOURCC FourCC_WMV3 = mmioFOURCC('W','M','V','3'); static const FOURCC FourCC_H264 = mmioFOURCC('H','2','6','4'); static const FOURCC FourCC_AVC1 = mmioFOURCC('A','V','C','1'); static struct { AVCodecID ffcodec; FOURCC fourCC; } quicksync_codecs[] = { { AV_CODEC_ID_MPEG2VIDEO, FourCC_MPG2 }, { AV_CODEC_ID_VC1, FourCC_VC1 }, { AV_CODEC_ID_WMV3, FourCC_WMV3 }, { AV_CODEC_ID_H264, FourCC_H264 }, };
static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr) { MMCKINFO ckMainRIFF; MMCKINFO mmckHead; MMCKINFO mmckList; MMCKINFO mmckInfo; DWORD numFrame; DWORD insize; if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) { WARN("Can't find 'RIFF' chunk\n"); return FALSE; } if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) { WARN("Can't find 'AVI ' chunk\n"); return FALSE; } mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) { WARN("Can't find 'hdrl' list\n"); return FALSE; } mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'avih' chunk\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah)); TRACE("mah.dwMicroSecPerFrame=%d\n", infoPtr->mah.dwMicroSecPerFrame); TRACE("mah.dwMaxBytesPerSec=%d\n", infoPtr->mah.dwMaxBytesPerSec); TRACE("mah.dwPaddingGranularity=%d\n", infoPtr->mah.dwPaddingGranularity); TRACE("mah.dwFlags=%d\n", infoPtr->mah.dwFlags); TRACE("mah.dwTotalFrames=%d\n", infoPtr->mah.dwTotalFrames); TRACE("mah.dwInitialFrames=%d\n", infoPtr->mah.dwInitialFrames); TRACE("mah.dwStreams=%d\n", infoPtr->mah.dwStreams); TRACE("mah.dwSuggestedBufferSize=%d\n", infoPtr->mah.dwSuggestedBufferSize); TRACE("mah.dwWidth=%d\n", infoPtr->mah.dwWidth); TRACE("mah.dwHeight=%d\n", infoPtr->mah.dwHeight); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) { WARN("Can't find 'strl' list\n"); return FALSE; } mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'strh' chunk\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash)); TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)), HIBYTE(LOWORD(infoPtr->ash.fccType)), LOBYTE(HIWORD(infoPtr->ash.fccType)), HIBYTE(HIWORD(infoPtr->ash.fccType))); TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)), HIBYTE(LOWORD(infoPtr->ash.fccHandler)), LOBYTE(HIWORD(infoPtr->ash.fccHandler)), HIBYTE(HIWORD(infoPtr->ash.fccHandler))); TRACE("ash.dwFlags=%d\n", infoPtr->ash.dwFlags); TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority); TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage); TRACE("ash.dwInitialFrames=%d\n", infoPtr->ash.dwInitialFrames); TRACE("ash.dwScale=%d\n", infoPtr->ash.dwScale); TRACE("ash.dwRate=%d\n", infoPtr->ash.dwRate); TRACE("ash.dwStart=%d\n", infoPtr->ash.dwStart); TRACE("ash.dwLength=%d\n", infoPtr->ash.dwLength); TRACE("ash.dwSuggestedBufferSize=%d\n", infoPtr->ash.dwSuggestedBufferSize); TRACE("ash.dwQuality=%d\n", infoPtr->ash.dwQuality); TRACE("ash.dwSampleSize=%d\n", infoPtr->ash.dwSampleSize); TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left, infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'strh' chunk\n"); return FALSE; } infoPtr->inbih = Alloc(mmckInfo.cksize); if (!infoPtr->inbih) { WARN("Can't alloc input BIH\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize); TRACE("bih.biSize=%d\n", infoPtr->inbih->biSize); TRACE("bih.biWidth=%d\n", infoPtr->inbih->biWidth); TRACE("bih.biHeight=%d\n", infoPtr->inbih->biHeight); TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes); TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount); TRACE("bih.biCompression=%d\n", infoPtr->inbih->biCompression); TRACE("bih.biSizeImage=%d\n", infoPtr->inbih->biSizeImage); TRACE("bih.biXPelsPerMeter=%d\n", infoPtr->inbih->biXPelsPerMeter); TRACE("bih.biYPelsPerMeter=%d\n", infoPtr->inbih->biYPelsPerMeter); TRACE("bih.biClrUsed=%d\n", infoPtr->inbih->biClrUsed); TRACE("bih.biClrImportant=%d\n", infoPtr->inbih->biClrImportant); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmioAscend(infoPtr->hMMio, &mmckList, 0); #if 0 /* an AVI has 0 or 1 video stream, and to be animated should not contain * an audio stream, so only one strl is allowed */ mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) { WARN("There should be a single 'strl' list\n"); return FALSE; } #endif mmioAscend(infoPtr->hMMio, &mmckHead, 0); /* no need to read optional JUNK chunk */ mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i'); if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) { WARN("Can't find 'movi' list\n"); return FALSE; } /* FIXME: should handle the 'rec ' LIST when present */ infoPtr->lpIndex = Alloc(infoPtr->mah.dwTotalFrames * sizeof(DWORD)); if (!infoPtr->lpIndex) return FALSE; numFrame = insize = 0; while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 && numFrame < infoPtr->mah.dwTotalFrames) { infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset; if (insize < mmckInfo.cksize) insize = mmckInfo.cksize; numFrame++; mmioAscend(infoPtr->hMMio, &mmckInfo, 0); } if (numFrame != infoPtr->mah.dwTotalFrames) { WARN("Found %d frames (/%d)\n", numFrame, infoPtr->mah.dwTotalFrames); return FALSE; } if (insize > infoPtr->ash.dwSuggestedBufferSize) { WARN("insize=%d suggestedSize=%d\n", insize, infoPtr->ash.dwSuggestedBufferSize); infoPtr->ash.dwSuggestedBufferSize = insize; } infoPtr->indata = Alloc(infoPtr->ash.dwSuggestedBufferSize); if (!infoPtr->indata) return FALSE; return TRUE; }
static demux_packet_t* getBuffer(demuxer_t* demuxer, demux_stream_t* ds, Boolean mustGetNewData, float& ptsBehind) { // Begin by finding the buffer queue that we want to read from: // (Get this from the RTP state, which we stored in // the demuxer's 'priv' field) RTPState* rtpState = (RTPState*)(demuxer->priv); ReadBufferQueue* bufferQueue = NULL; int headersize = 0; TaskToken task; if (demuxer->stream->eof) return NULL; if (ds == demuxer->video) { bufferQueue = rtpState->videoBufferQueue; if (((sh_video_t*)ds->sh)->format == mmioFOURCC('H','2','6','4')) headersize = 3; } else if (ds == demuxer->audio) { bufferQueue = rtpState->audioBufferQueue; if (bufferQueue->readSource()->isAMRAudioSource()) headersize = 1; } else { fprintf(stderr, "(demux_rtp)getBuffer: internal error: unknown stream\n"); return NULL; } if (bufferQueue == NULL || bufferQueue->readSource() == NULL) { fprintf(stderr, "(demux_rtp)getBuffer failed: no appropriate RTP subsession has been set up\n"); return NULL; } demux_packet_t* dp = NULL; if (!mustGetNewData) { // Check whether we have a previously-saved buffer that we can use: dp = bufferQueue->getPendingBuffer(); if (dp != NULL) { ptsBehind = 0.0; // so that we always accept this data return dp; } } // Allocate a new packet buffer, and arrange to read into it: if (!bufferQueue->nextpacket) { dp = new_demux_packet(MAX_RTP_FRAME_SIZE); bufferQueue->dp = dp; if (dp == NULL) return NULL; } #ifdef CONFIG_LIBAVCODEC extern AVCodecParserContext * h264parserctx; int consumed, poutbuf_size = 1; const uint8_t *poutbuf = NULL; float lastpts = 0.0; do { if (!bufferQueue->nextpacket) { #endif // Schedule the read operation: bufferQueue->blockingFlag = 0; bufferQueue->readSource()->getNextFrame(&dp->buffer[headersize], MAX_RTP_FRAME_SIZE - headersize, afterReading, bufferQueue, onSourceClosure, bufferQueue); // Block ourselves until data becomes available: TaskScheduler& scheduler = bufferQueue->readSource()->envir().taskScheduler(); int delay = 10000000; if (bufferQueue->prevPacketPTS * 1.05 > rtpState->mediaSession->playEndTime()) delay /= 10; task = scheduler.scheduleDelayedTask(delay, onSourceClosure, bufferQueue); scheduler.doEventLoop(&bufferQueue->blockingFlag); scheduler.unscheduleDelayedTask(task); if (demuxer->stream->eof) { free_demux_packet(dp); return NULL; } if (headersize == 1) // amr dp->buffer[0] = ((AMRAudioSource*)bufferQueue->readSource())->lastFrameHeader(); #ifdef CONFIG_LIBAVCODEC } else { bufferQueue->dp = dp = bufferQueue->nextpacket; bufferQueue->nextpacket = NULL; } if (headersize == 3 && h264parserctx) { // h264 consumed = h264parserctx->parser->parser_parse(h264parserctx, avcctx, &poutbuf, &poutbuf_size, dp->buffer, dp->len); if (!consumed && !poutbuf_size) return NULL; if (!poutbuf_size) { lastpts=dp->pts; free_demux_packet(dp); bufferQueue->dp = dp = new_demux_packet(MAX_RTP_FRAME_SIZE); } else { bufferQueue->nextpacket = dp; bufferQueue->dp = dp = new_demux_packet(poutbuf_size); memcpy(dp->buffer, poutbuf, poutbuf_size); dp->pts=lastpts; } } } while (!poutbuf_size); #endif // Set the "ptsBehind" result parameter: if (bufferQueue->prevPacketPTS != 0.0 && bufferQueue->prevPacketWasSynchronized && *(bufferQueue->otherQueue) != NULL && (*(bufferQueue->otherQueue))->prevPacketPTS != 0.0 && (*(bufferQueue->otherQueue))->prevPacketWasSynchronized) { ptsBehind = (*(bufferQueue->otherQueue))->prevPacketPTS - bufferQueue->prevPacketPTS; } else { ptsBehind = 0.0; } if (mustGetNewData) { // Save this buffer for future reads: bufferQueue->savePendingBuffer(dp); } return dp; }
int WaveCopyUselessChunks( HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRiff, HMMIO *phmmioOut, MMCKINFO *pckOut, MMCKINFO *pckOutRiff) { int nError; nError = 0; // First seek to the stinking start of the file, not including the riff header... if ((nError = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1) { nError = ER_CANNOTREAD; goto ERROR_IN_PROC; } nError = 0; while (mmioDescend(*phmmioIn, pckIn, pckInRiff, 0) == 0) { // quickly check for corrupt RIFF file--don't ascend past end! if ((pckIn->dwDataOffset + pckIn->cksize) > (pckInRiff->dwDataOffset + pckInRiff->cksize)) goto ERROR_IN_PROC; switch (pckIn->ckid) { // explicitly skip these... case mmioFOURCC('f', 'm', 't', ' '): break; case mmioFOURCC('d', 'a', 't', 'a'): break; case mmioFOURCC('f', 'a', 'c', 't'): break; case mmioFOURCC('J', 'U', 'N', 'K'): break; case mmioFOURCC('P', 'A', 'D', ' '): break; case mmioFOURCC('c', 'u', 'e', ' '): break; // copy chunks that are OK to copy case mmioFOURCC('p', 'l', 's', 't'): // although without the 'cue' chunk, it doesn't make much sense riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; case mmioFOURCC('D', 'I', 'S', 'P'): riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; // don't copy unknown chunks default: break; } // step up to prepare for next chunk.. mmioAscend(*phmmioIn, pckIn, 0); } ERROR_IN_PROC: { int nErrorT; // Seek back to riff header nErrorT = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET); } return(nError); }
static BOOL DSParseWaveResource(const void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData,DWORD *pcbWaveSize) { DWORD *pdw; DWORD *pdwEnd; DWORD dwRiff; DWORD dwType; DWORD dwLength; if (ppWaveHeader) *ppWaveHeader = NULL; if (ppbWaveData) *ppbWaveData = NULL; if (pcbWaveSize) *pcbWaveSize = 0; pdw = (DWORD *)pvRes; dwRiff = *pdw++; dwLength = *pdw++; dwType = *pdw++; if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F')) goto exit; // not even RIFF if (dwType != mmioFOURCC('W', 'A', 'V', 'E')) goto exit; // not a WAV pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4); while (pdw < pdwEnd) { dwType = *pdw++; dwLength = *pdw++; switch (dwType) { case mmioFOURCC('f', 'm', 't', ' '): if (ppWaveHeader && !*ppWaveHeader) { if (dwLength < sizeof(WAVEFORMAT)) goto exit; // not a WAV *ppWaveHeader = (WAVEFORMATEX *)pdw; if ((!ppbWaveData || *ppbWaveData) && (!pcbWaveSize || *pcbWaveSize)) { return TRUE; } } break; case mmioFOURCC('d', 'a', 't', 'a'): if ((ppbWaveData && !*ppbWaveData) || (pcbWaveSize && !*pcbWaveSize)) { if (ppbWaveData) *ppbWaveData = (LPBYTE)pdw; if (pcbWaveSize) *pcbWaveSize = dwLength; if (!ppWaveHeader || *ppWaveHeader) return TRUE; } break; } pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1)); } exit: return FALSE; }
//----------------------------------------------------------------------------- // Name: ReadMMIO() // Desc: Support function for reading from a multimedia I/O stream //----------------------------------------------------------------------------- HRESULT ReadMMIO( HMMIO hmmioIn, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo ) { MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. *ppwfxInfo = NULL; if( ( 0 != mmioDescend( hmmioIn, pckInRIFF, NULL, 0 ) ) ) return E_FAIL; if( (pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) return E_FAIL; // Search the input file for for the 'fmt ' chunk. ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if( 0 != mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK) ) return E_FAIL; // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; // if there are extra parameters at the end, we'll ignore them if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) return E_FAIL; // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( hmmioIn, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) return E_FAIL; // Allocate the waveformatex, but if its not pcm format, read the next // word, and thats how many extra bytes to allocate. if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { if( NULL == ( *ppwfxInfo = new WAVEFORMATEX ) ) return E_FAIL; // Copy the bytes from the pcm structure to the waveformatex structure memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) ); (*ppwfxInfo)->cbSize = 0; } else { // Read in length of extra bytes. WORD cbExtraBytes = 0L; if( mmioRead( hmmioIn, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) return E_FAIL; *ppwfxInfo = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; if( NULL == *ppwfxInfo ) return E_FAIL; // Copy the bytes from the pcm structure to the waveformatex structure memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) ); (*ppwfxInfo)->cbSize = cbExtraBytes; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if( mmioRead( hmmioIn, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { delete *ppwfxInfo; *ppwfxInfo = NULL; return E_FAIL; } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( hmmioIn, &ckIn, 0 ) ) { delete *ppwfxInfo; *ppwfxInfo = NULL; return E_FAIL; } return S_OK; }
int Sound::LoadWAV(char *filename, int control_flags) { // this function loads a .wav file, sets up the directsound // buffer and loads the data into memory, the function returns // the id number of the sound HMMIO hwav; // handle to wave file MMCKINFO parent, // parent chunk child; // child chunk WAVEFORMATEX wfmtx; // wave format structure int sound_id = -1, // id of sound to be loaded index; // looping variable unsigned char *snd_buffer, // temporary sound buffer to hold voc data *audio_ptr_1=NULL, // data ptr to first write buffer *audio_ptr_2=NULL; // data ptr to second write buffer DWORD audio_length_1=0, // length of first write buffer audio_length_2=0; // length of second write buffer // step one: are there any open id's ? for (index=0; index < MAX_SOUNDS; index++) { // make sure this sound is unused if (sound_fx[index].state==SOUND_NULL) { sound_id = index; break; } } // did we get a free id? if (sound_id==-1) return(-1); // set up chunk info structure parent.ckid = (FOURCC)0; parent.cksize = 0; parent.fccType = (FOURCC)0; parent.dwDataOffset = 0; parent.dwFlags = 0; // copy data child = parent; // open the WAV file if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL) return(-1); // descend into the RIFF parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF)) { // close the file mmioClose(hwav, 0); // return error, no wave section return(-1); } // descend to the WAVEfmt child.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hwav, &child, &parent, 0)) { // close the file mmioClose(hwav, 0); // return error, no format section return(-1); } // now read the wave format information from file if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx)) { // close file mmioClose(hwav, 0); // return error, no wave format data return(-1); } // make sure that the data format is PCM if (wfmtx.wFormatTag != WAVE_FORMAT_PCM) { // close the file mmioClose(hwav, 0); // return error, not the right data format return(-1); } // now ascend up one level, so we can access data chunk if (mmioAscend(hwav, &child, 0)) { // close file mmioClose(hwav, 0); // return error, couldn't ascend return(-1); } // descend to the data chunk child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK)) { // close file mmioClose(hwav, 0); // return error, no data return(-1); } // finally!!!! now all we have to do is read the data in and // set up the directsound buffer // allocate the memory to load sound data snd_buffer = (unsigned char *)malloc(child.cksize); // read the wave data mmioRead(hwav, (char *)snd_buffer, child.cksize); // close the file mmioClose(hwav, 0); // set rate and size in data structure sound_fx[sound_id].rate = wfmtx.nSamplesPerSec; sound_fx[sound_id].size = child.cksize; sound_fx[sound_id].state = SOUND_LOADED; // set up the format data structure memset(&pcmwf, 0, sizeof(WAVEFORMATEX)); pcmwf.wFormatTag = WAVE_FORMAT_PCM; // pulse code modulation pcmwf.nChannels = 1; // mono pcmwf.nSamplesPerSec = 11025; // always this rate pcmwf.nBlockAlign = 1; pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; pcmwf.wBitsPerSample = 8; pcmwf.cbSize = 0; // prepare to create sounds buffer dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE; dsbd.dwBufferBytes = child.cksize; dsbd.lpwfxFormat = &pcmwf; // create the sound buffer if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL))) { // release memory free(snd_buffer); // return error return(-1); } // copy data into sound buffer if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0, child.cksize, (void **) &audio_ptr_1, &audio_length_1, (void **)&audio_ptr_2, &audio_length_2, DSBLOCK_FROMWRITECURSOR))) return(0); // copy first section of circular buffer memcpy(audio_ptr_1, snd_buffer, audio_length_1); // copy last section of circular buffer memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2); // unlock the buffer if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1, audio_length_1, audio_ptr_2, audio_length_2))) return(0); // release the temp buffer free(snd_buffer); return(sound_id); }
static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame *iface, LPBITMAPINFOHEADER lpbiWanted, LPVOID lpBits, INT x, INT y, INT dx, INT dy) { IGetFrameImpl *This = impl_from_IGetFrame(iface); AVISTREAMINFOW sInfo; LPBITMAPINFOHEADER lpbi = lpbiWanted; BOOL bBestDisplay = FALSE; TRACE("(%p,%p,%p,%d,%d,%d,%d)\n", iface, lpbiWanted, lpBits, x, y, dx, dy); if (This->pStream == NULL) return AVIERR_ERROR; if (lpbiWanted == (LPBITMAPINFOHEADER)AVIGETFRAMEF_BESTDISPLAYFMT) { lpbi = NULL; bBestDisplay = TRUE; } IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo)); if (sInfo.fccType != streamtypeVIDEO) return AVIERR_UNSUPPORTED; This->bFormatChanges = (sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) != 0; This->dwFormatChangeCount = sInfo.dwFormatChangeCount; This->dwEditCount = sInfo.dwEditCount; This->lCurrentFrame = -1; /* get input format from stream */ if (This->lpInFormat == NULL) { HRESULT hr; This->cbInBuffer = (LONG)sInfo.dwSuggestedBufferSize; if (This->cbInBuffer == 0) This->cbInBuffer = 1024; IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, NULL, &This->cbInFormat); This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat + This->cbInBuffer); if (This->lpInFormat == NULL) { AVIFILE_CloseCompressor(This); return AVIERR_MEMORY; } hr = IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, This->lpInFormat, &This->cbInFormat); if (FAILED(hr)) { AVIFILE_CloseCompressor(This); return hr; } This->lpInBuffer = ((LPBYTE)This->lpInFormat) + This->cbInFormat; } /* check input format */ if (This->lpInFormat->biClrUsed == 0 && This->lpInFormat->biBitCount <= 8) This->lpInFormat->biClrUsed = 1u << This->lpInFormat->biBitCount; if (This->lpInFormat->biSizeImage == 0 && This->lpInFormat->biCompression == BI_RGB) { This->lpInFormat->biSizeImage = DIBWIDTHBYTES(*This->lpInFormat) * This->lpInFormat->biHeight; } /* only to pass through? */ if (This->lpInFormat->biCompression == BI_RGB && lpBits == NULL) { if (lpbi == NULL || (lpbi->biCompression == BI_RGB && lpbi->biWidth == This->lpInFormat->biWidth && lpbi->biHeight == This->lpInFormat->biHeight && lpbi->biBitCount == This->lpInFormat->biBitCount)) { This->lpOutFormat = This->lpInFormat; This->lpOutBuffer = DIBPTR(This->lpInFormat); return AVIERR_OK; } } /* need memory for output format? */ if (This->lpOutFormat == NULL) { This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); if (This->lpOutFormat == NULL) { AVIFILE_CloseCompressor(This); return AVIERR_MEMORY; } } /* need handle to video compressor */ if (This->hic == NULL) { FOURCC fccHandler; if (This->lpInFormat->biCompression == BI_RGB) fccHandler = comptypeDIB; else if (This->lpInFormat->biCompression == BI_RLE8) fccHandler = mmioFOURCC('R','L','E',' '); else fccHandler = sInfo.fccHandler; if (lpbi != NULL) { if (lpbi->biWidth == 0) lpbi->biWidth = This->lpInFormat->biWidth; if (lpbi->biHeight == 0) lpbi->biHeight = This->lpInFormat->biHeight; } This->hic = ICLocate(ICTYPE_VIDEO, fccHandler, This->lpInFormat, lpbi, ICMODE_DECOMPRESS); if (This->hic == NULL) { AVIFILE_CloseCompressor(This); return AVIERR_NOCOMPRESSOR; } } /* output format given? */ if (lpbi != NULL) { /* check the given output format ... */ if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8) lpbi->biClrUsed = 1u << lpbi->biBitCount; /* ... and remember it */ memcpy(This->lpOutFormat, lpbi, lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD)); if (lpbi->biBitCount <= 8) ICDecompressGetPalette(This->hic, This->lpInFormat, This->lpOutFormat); return AVIERR_OK; } else { if (bBestDisplay) { ICGetDisplayFormat(This->hic, This->lpInFormat, This->lpOutFormat, 0, dx, dy); } else if (ICDecompressGetFormat(This->hic, This->lpInFormat, This->lpOutFormat) < 0) { AVIFILE_CloseCompressor(This); return AVIERR_NOCOMPRESSOR; } /* check output format */ if (This->lpOutFormat->biClrUsed == 0 && This->lpOutFormat->biBitCount <= 8) This->lpOutFormat->biClrUsed = 1u << This->lpOutFormat->biBitCount; if (This->lpOutFormat->biSizeImage == 0 && This->lpOutFormat->biCompression == BI_RGB) { This->lpOutFormat->biSizeImage = DIBWIDTHBYTES(*This->lpOutFormat) * This->lpOutFormat->biHeight; } if (lpBits == NULL) { DWORD size = This->lpOutFormat->biClrUsed * sizeof(RGBQUAD); size += This->lpOutFormat->biSize + This->lpOutFormat->biSizeImage; This->lpOutFormat = HeapReAlloc(GetProcessHeap(), 0, This->lpOutFormat, size); if (This->lpOutFormat == NULL) { AVIFILE_CloseCompressor(This); return AVIERR_MEMORY; } This->lpOutBuffer = DIBPTR(This->lpOutFormat); } else This->lpOutBuffer = lpBits; /* for user size was irrelevant */ if (dx == -1) dx = This->lpOutFormat->biWidth; if (dy == -1) dy = This->lpOutFormat->biHeight; /* need to resize? */ if (x != 0 || y != 0) { if (dy == This->lpOutFormat->biHeight && dx == This->lpOutFormat->biWidth) This->bResize = FALSE; else This->bResize = TRUE; } if (This->bResize) { This->x = x; This->y = y; This->dx = dx; This->dy = dy; if (ICDecompressExBegin(This->hic,0,This->lpInFormat,This->lpInBuffer,0, 0,This->lpInFormat->biWidth, This->lpInFormat->biHeight,This->lpOutFormat, This->lpOutBuffer, x, y, dx, dy) == ICERR_OK) return AVIERR_OK; } else if (ICDecompressBegin(This->hic, This->lpInFormat, This->lpOutFormat) == ICERR_OK) return AVIERR_OK; AVIFILE_CloseCompressor(This); return AVIERR_COMPRESSOR; } }
static demuxer_t* demux_open_vqf(demuxer_t* demuxer) { sh_audio_t* sh_audio; WAVEFORMATEX* w; stream_t *s; headerInfo *hi; s = demuxer->stream; sh_audio = new_sh_audio(demuxer,0); sh_audio->wf = w = calloc(1, sizeof(*sh_audio->wf)+sizeof(headerInfo)); hi = (headerInfo *)&w[1]; w->wFormatTag = 0x1; sh_audio->format = mmioFOURCC('T','W','I','N'); /* TWinVQ */ w->nChannels = sh_audio->channels = 2; w->nSamplesPerSec = sh_audio->samplerate = 44100; w->nAvgBytesPerSec = w->nSamplesPerSec*sh_audio->channels*2; w->nBlockAlign = 0; sh_audio->samplesize = 2; w->wBitsPerSample = 8*sh_audio->samplesize; w->cbSize = 0; strcpy(hi->ID,"TWIN"); stream_read(s,hi->ID+KEYWORD_BYTES,VERSION_BYTES); /* fourcc+version_id */ while(1) { char chunk_id[4]; unsigned chunk_size; hi->size=chunk_size=stream_read_dword(s); /* include itself */ stream_read(s,chunk_id,4); if (chunk_size < 8) return NULL; chunk_size -= 8; if(AV_RL32(chunk_id)==mmioFOURCC('C','O','M','M')) { char buf[BUFSIZ]; unsigned i,subchunk_size; if (chunk_size > sizeof(buf) || chunk_size < 20) return NULL; if(stream_read(s,buf,chunk_size)!=chunk_size) return NULL; i=0; subchunk_size = AV_RB32(buf); hi->channelMode = AV_RB32(buf + 4); w->nChannels=sh_audio->channels=hi->channelMode+1; /*0-mono;1-stereo*/ hi->bitRate = AV_RB32(buf + 8); sh_audio->i_bps=hi->bitRate*1000/8; /* bitrate kbit/s */ w->nAvgBytesPerSec = sh_audio->i_bps; hi->samplingRate = AV_RB32(buf + 12); switch(hi->samplingRate){ case 44: w->nSamplesPerSec=44100; break; case 22: w->nSamplesPerSec=22050; break; case 11: w->nSamplesPerSec=11025; break; default: w->nSamplesPerSec=hi->samplingRate*1000; break; } sh_audio->samplerate=w->nSamplesPerSec; hi->securityLevel = AV_RB32(buf + 16); w->nBlockAlign = 0; sh_audio->samplesize = 4; w->wBitsPerSample = 8*sh_audio->samplesize; w->cbSize = 0; if (subchunk_size > chunk_size - 4) continue; i+=subchunk_size+4; while(i + 8 < chunk_size) { unsigned slen,sid; char sdata[BUFSIZ]; sid = AV_RL32(buf + i); i+=4; slen = AV_RB32(buf + i); i+=4; if (slen > sizeof(sdata) - 1 || slen > chunk_size - i) break; if(sid==mmioFOURCC('D','S','I','Z')) { hi->Dsiz=AV_RB32(buf + i); continue; /* describes the same info as size of DATA chunk */ } memcpy(sdata,&buf[i],slen); sdata[slen]=0; i+=slen; if(sid==mmioFOURCC('N','A','M','E')) { memcpy(hi->Name,sdata,FFMIN(BUFSIZ,slen)); demux_info_add(demuxer,"Title",sdata); } else if(sid==mmioFOURCC('A','U','T','H')) { memcpy(hi->Auth,sdata,FFMIN(BUFSIZ,slen)); demux_info_add(demuxer,"Author",sdata); } else if(sid==mmioFOURCC('C','O','M','T')) { memcpy(hi->Comt,sdata,FFMIN(BUFSIZ,slen)); demux_info_add(demuxer,"Comment",sdata); } else if(sid==mmioFOURCC('(','c',')',' ')) { memcpy(hi->Cpyr,sdata,FFMIN(BUFSIZ,slen)); demux_info_add(demuxer,"Copyright",sdata); } else if(sid==mmioFOURCC('F','I','L','E')) { memcpy(hi->File,sdata,FFMIN(BUFSIZ,slen)); } else if(sid==mmioFOURCC('A','L','B','M')) demux_info_add(demuxer,"Album",sdata); else if(sid==mmioFOURCC('Y','E','A','R')) demux_info_add(demuxer,"Date",sdata); else if(sid==mmioFOURCC('T','R','A','C')) demux_info_add(demuxer,"Track",sdata); else if(sid==mmioFOURCC('E','N','C','D')) demux_info_add(demuxer,"Encoder",sdata); else mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled subchunk '%c%c%c%c'='%s'\n",((char *)&sid)[0],((char *)&sid)[1],((char *)&sid)[2],((char *)&sid)[3],sdata); /* rest not recognized due to untranslatable Japanese expressions */ } } else if(AV_RL32(chunk_id)==mmioFOURCC('D','A','T','A')) { demuxer->movi_start=stream_tell(s); demuxer->movi_end=demuxer->movi_start+chunk_size; mp_msg(MSGT_DEMUX, MSGL_V, "Found data at %"PRIX64" size %"PRIu64"\n",demuxer->movi_start,demuxer->movi_end); /* Done! play it */ break; } else { mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled chunk '%c%c%c%c' %u bytes\n",chunk_id[0],chunk_id[1],chunk_id[2],chunk_id[3],chunk_size); stream_skip(s,chunk_size); /*unknown chunk type */ } } demuxer->audio->id = 0; demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; stream_seek(s,demuxer->movi_start); demuxer->seekable=0; return demuxer; }
BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma) { HDC hDC; DWORD outSize; FOURCC fcc = wma->ash_video.fccHandler; TRACE("fcc %4.4s\n", (LPSTR)&fcc); wma->dwCachedFrame = -1; /* get the right handle */ 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) { /* check for builtin DIB compressions */ fcc = wma->inbih->biCompression; if ((fcc == mmioFOURCC('D','I','B',' ')) || (fcc == mmioFOURCC('R','L','E',' ')) || (fcc == BI_RGB) || (fcc == BI_RLE8) || (fcc == BI_RLE4) || (fcc == BI_BITFIELDS)) goto paint_frame; 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=%d\n", wma->outbih->biSize); TRACE("bih.biWidth=%d\n", wma->outbih->biWidth); TRACE("bih.biHeight=%d\n", wma->outbih->biHeight); TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes); TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount); TRACE("bih.biCompression=%x\n", wma->outbih->biCompression); TRACE("bih.biSizeImage=%d\n", wma->outbih->biSizeImage); TRACE("bih.biXPelsPerMeter=%d\n", wma->outbih->biXPelsPerMeter); TRACE("bih.biYPelsPerMeter=%d\n", wma->outbih->biYPelsPerMeter); TRACE("bih.biClrUsed=%d\n", wma->outbih->biClrUsed); TRACE("bih.biClrImportant=%d\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_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) { WARN("Can't begin decompression\n"); return FALSE; } paint_frame: hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; if (hDC) { MCIAVI_PaintFrame(wma, hDC); ReleaseDC(wma->hWndPaint, hDC); } return TRUE; }
bool CWAVFileReader::open() { m_handle = ::mmioOpen(LPWSTR(m_fileName.c_str()), 0, MMIO_READ | MMIO_ALLOCBUF); if (m_handle == NULL) { wxLogError(wxT("WAVFileReader: could not open the WAV file %s\n"), m_fileName.c_str()); return false; } MMCKINFO parent; parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); MMRESULT res = ::mmioDescend(m_handle, &parent, 0, MMIO_FINDRIFF); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("WAVFileReader: %s has no \"WAVE\" header\n"), m_fileName.c_str()); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } MMCKINFO child; child.ckid = mmioFOURCC('f', 'm', 't', ' '); res = ::mmioDescend(m_handle, &child, &parent, MMIO_FINDCHUNK); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("WAVFileReader: %s has no \"fmt \" chunk\n"), m_fileName.c_str()); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } WAVEFORMATEX format; LONG len = ::mmioRead(m_handle, (char *)&format, child.cksize); if (len != LONG(child.cksize)) { wxLogError(wxT("WAVFileReader: %s is corrupt, cannot read the WAVEFORMATEX structure\n"), m_fileName.c_str()); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } if (format.wFormatTag != WAVE_FORMAT_PCM && format.wFormatTag != WAVE_FORMAT_IEEE_FLOAT) { wxLogError(wxT("WAVFileReader: %s is not PCM or IEEE Float format, is %u\n"), m_fileName.c_str(), format.wFormatTag); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } m_sampleRate = format.nSamplesPerSec; m_channels = format.nChannels; if (m_channels > 2U) { wxLogError(wxT("WAVFileReader: %s has %u channels, more than 2\n"), m_fileName.c_str(), m_channels); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } if (format.wBitsPerSample == 8U && format.wFormatTag == WAVE_FORMAT_PCM) { m_format = FORMAT_8BIT; } else if (format.wBitsPerSample == 16U && format.wFormatTag == WAVE_FORMAT_PCM) { m_format = FORMAT_16BIT; } else if (format.wBitsPerSample == 32U && format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { m_format = FORMAT_32BIT; } else { wxLogError(wxT("WAVFileReader: %s has sample width %u and format %u\n"), m_fileName.c_str(), format.wBitsPerSample, format.wFormatTag); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } res = ::mmioAscend(m_handle, &child, 0); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("WAVFileReader: %s is corrupt, cannot ascend\n"), m_fileName.c_str()); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); res = ::mmioDescend(m_handle, &child, &parent, MMIO_FINDCHUNK); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("WAVFileReader: %s has no \"data\" chunk\n"), m_fileName.c_str()); ::mmioClose(m_handle, 0U); m_handle = NULL; return false; } // Get the current location so we can rewind if needed m_offset = ::mmioSeek(m_handle, 0L, SEEK_CUR); return true; }
WIOERR WIOAPI wioFileOpen ( LPWAVEIOCB pwio, LPCTSTR pszFilePath, DWORD fdwOpen ) { UINT u; TCHAR ach[255]; WIOERR werr; HMMIO hmmio; MMCKINFO ckRIFF; MMCKINFO ck; DWORD dw; // // validate a couple of things... // if (NULL == pwio) return (WIOERR_BADPARAM); // // default our error return (assume the worst) // _fmemset(pwio, 0, sizeof(*pwio)); werr = WIOERR_FILEERROR; pwio->dwFlags = fdwOpen; // // first try to open the file, etc.. open the given file for reading // using buffered I/O // hmmio = mmioOpen((LPTSTR)pszFilePath, NULL, MMIO_READ | MMIO_ALLOCBUF); if (NULL == hmmio) goto wio_Open_Error; pwio->hmmio = hmmio; // // locate a 'WAVE' form type... // ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF)) goto wio_Open_Error; // // we found a WAVE chunk--now go through and get all subchunks that // we know how to deal with... // pwio->dwDataSamples = (DWORD)-1L; #if 0 if (lrt=riffInitINFO(&wio.pInfo)) { lr=lrt; goto wio_Open_Error; } #endif // // // while (MMSYSERR_NOERROR == mmioDescend(hmmio, &ck, &ckRIFF, 0)) { // // quickly check for corrupt RIFF file--don't ascend past end! // if ((ck.dwDataOffset + ck.cksize) > (ckRIFF.dwDataOffset + ckRIFF.cksize)) { DPF(1, "wioFileOpen() FILE MIGHT BE CORRUPT!"); DPF(1, " ckRIFF.dwDataOffset: %lu", ckRIFF.dwDataOffset); DPF(1, " ckRIFF.cksize: %lu", ckRIFF.cksize); DPF(1, " ck.dwDataOffset: %lu", ck.dwDataOffset); DPF(1, " ck.cksize: %lu", ck.cksize); wsprintf(ach, TEXT("This wave file might be corrupt. The RIFF chunk.ckid '%.08lX' (data offset at %lu) specifies a cksize of %lu that extends beyond what the RIFF header cksize of %lu allows. Attempt to load?"), ck.ckid, ck.dwDataOffset, ck.cksize, ckRIFF.cksize); u = MessageBox(NULL, ach, TEXT("wioFileOpen"), MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL); if (IDNO == u) { werr = WIOERR_BADFILE; goto wio_Open_Error; } } switch (ck.ckid) { case mmioFOURCC('L', 'I', 'S', 'T'): if (ck.fccType == mmioFOURCC('I', 'N', 'F', 'O')) { #if 0 if(lrt=riffReadINFO(hmmio, &ck, wio.pInfo)) { lr=lrt; goto wio_Open_Error; } #endif } break; case mmioFOURCC('D', 'I', 'S', 'P'): #if 0 riffReadDISP(hmmio, &ck, &(wio.pDisp)); #endif break; case mmioFOURCC('f', 'm', 't', ' '): // // !?! another format chunk !?! // if (NULL != pwio->pwfx) break; // // get size of the format chunk, allocate and lock memory // for it. we always alloc a complete extended format header // (even for PCM headers that do not have the cbSize field // defined--we just set it to zero). // dw = ck.cksize; if (dw < sizeof(WAVEFORMATEX)) dw = sizeof(WAVEFORMATEX); pwio->pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, dw); if (NULL == pwio->pwfx) { werr = WIOERR_NOMEM; goto wio_Open_Error; } // // read the format chunk // werr = WIOERR_FILEERROR; dw = ck.cksize; if (mmioRead(hmmio, (HPSTR)pwio->pwfx, dw) != (LONG)dw) goto wio_Open_Error; break; case mmioFOURCC('d', 'a', 't', 'a'): // // !?! multiple data chunks !?! // if (0L != pwio->dwDataBytes) break; // // just hang on to the total length in bytes of this data // chunk.. and the offset to the start of the data // pwio->dwDataBytes = ck.cksize; pwio->dwDataOffset = ck.dwDataOffset; break; case mmioFOURCC('f', 'a', 'c', 't'): // // !?! multiple fact chunks !?! // if (-1L != pwio->dwDataSamples) break; // // read the first dword in the fact chunk--it's the only // info we need (and is currently the only info defined for // the fact chunk...) // // if this fails, dwDataSamples will remain -1 so we will // deal with it later... // mmioRead(hmmio, (HPSTR)&pwio->dwDataSamples, sizeof(DWORD)); break; } // // step up to prepare for next chunk.. // mmioAscend(hmmio, &ck, 0); } // // if no fmt chunk was found, then die! // if (NULL == pwio->pwfx) { werr = WIOERR_ERROR; goto wio_Open_Error; } // // all wave files other than PCM are _REQUIRED_ to have a fact chunk // telling the number of samples that are contained in the file. it // is optional for PCM (and if not present, we compute it here). // // if the file is not PCM and the fact chunk is not found, then fail! // if (-1L == pwio->dwDataSamples) { if (WAVE_FORMAT_PCM == pwio->pwfx->wFormatTag) { pwio->dwDataSamples = pwio->dwDataBytes / pwio->pwfx->nBlockAlign; } else { // // !!! HACK HACK HACK !!! // // although this should be considered an invalid wave file, we // will bring up a message box describing the error--hopefully // people will start realizing that something is missing??? // //CamStudio v2.24 //By pass this message since some of the converted .wav files are like this /* u = MessageBox(NULL, TEXT("This wave file does not have a 'fact' chunk and requires one! This is completely invalid and MUST be fixed! Attempt to load it anyway?"), TEXT("wioFileOpen"), MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL); if (IDNO == u) { werr = WIOERR_BADFILE; goto wio_Open_Error; } */ // // !!! need to hack stuff in here !!! // pwio->dwDataSamples = 0L; } } // // cool! no problems.. // return (WIOERR_NOERROR); // // return error (after minor cleanup) // wio_Open_Error: wioFileClose(pwio, 0L); return (werr); } // wioFileOpen()
static OSErr (*GetMaxCompressionSize)(PixMapHandle src, const Rect *srcRect, short colorDepth, CodecQ quality, CodecType cType, CompressorComponent codec, long *size ); static OSErr (*CDSequenceEnd)( ImageSequence seqID ); static Component (*FindNextComponent)(Component prev,ComponentDescription* desc); static long (*CountComponents)(ComponentDescription* desc); static OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3); //static int format=mmioFOURCC('S','V','Q','1'); static int format=mmioFOURCC('S','V','Q','3'); //static void *frame_in; //input frame static void *frame_prev; //previous frame static void *frame_comp; //compressed frame static GWorldPtr frame_GWorld_in = NULL;//a GWorld is some kind of description for a drawing environment static GWorldPtr frame_GWorld_prev = NULL; static Rect FrameRect; static CompressorComponent compressor; static ImageDescriptionHandle desc; static ImageSequence seq;
bool CSoundFileReader::open(float sampleRate, unsigned int blockSize) { m_blockSize = blockSize; m_handle = ::mmioOpen(LPWSTR(m_fileName.c_str()), 0, MMIO_READ | MMIO_ALLOCBUF); if (m_handle == NULL) { wxLogError(wxT("SoundFileReader: could not open the WAV file %s."), m_fileName.c_str()); return false; } MMCKINFO parent; parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); MMRESULT res = ::mmioDescend(m_handle, &parent, 0, MMIO_FINDRIFF); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("SoundFileReader: %s has no \"WAVE\" header."), m_fileName.c_str()); return false; } MMCKINFO child; child.ckid = mmioFOURCC('f', 'm', 't', ' '); res = ::mmioDescend(m_handle, &child, &parent, MMIO_FINDCHUNK); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("SoundFileReader: %s has no \"fmt \" chunk."), m_fileName.c_str()); return false; } WAVEFORMATEX format; LONG len = ::mmioRead(m_handle, (char *)&format, child.cksize); if (len != LONG(child.cksize)) { wxLogError(wxT("SoundFileReader: %s is corrupt, cannot read the WAVEFORMATEX structure."), m_fileName.c_str()); return false; } if (format.wFormatTag != WAVE_FORMAT_PCM && format.wFormatTag != WAVE_FORMAT_IEEE_FLOAT) { wxLogError(wxT("SoundFileReader: %s is not PCM or IEEE Float format, is %u."), m_fileName.c_str(), format.wFormatTag); return false; } if (format.nSamplesPerSec != DWORD(sampleRate)) { wxLogError(wxT("SoundFileReader: %s has sample rate %lu, not %.0f"), m_fileName.c_str(), format.nSamplesPerSec, sampleRate); return false; } m_channels = format.nChannels; if (m_channels > 2U) { wxLogError(wxT("SoundFileReader: %s has %u channels, more than 2."), m_fileName.c_str(), m_channels); return false; } if (format.wBitsPerSample == 8U && format.wFormatTag == WAVE_FORMAT_PCM) { m_format = FORMAT_8BIT; } else if (format.wBitsPerSample == 16U && format.wFormatTag == WAVE_FORMAT_PCM) { m_format = FORMAT_16BIT; } else if (format.wBitsPerSample == 32U && format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { m_format = FORMAT_32BIT; } else { wxLogError(wxT("SoundFileReader: %s has sample width %u and format %u."), m_fileName.c_str(), format.wBitsPerSample, format.wFormatTag); return false; } res = ::mmioAscend(m_handle, &child, 0); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("SoundFileReader: %s is corrupt, cannot ascend."), m_fileName.c_str()); return false; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); res = ::mmioDescend(m_handle, &child, &parent, MMIO_FINDCHUNK); if (res != MMSYSERR_NOERROR) { wxLogError(wxT("SoundFileReader: %s has no \"data\" chunk."), m_fileName.c_str()); return false; } // Get the current location so we can rewind if needed m_offset = ::mmioSeek(m_handle, 0L, SEEK_CUR); switch (m_format) { case FORMAT_8BIT: m_buffer8 = new wxUint8[m_blockSize * m_channels]; break; case FORMAT_16BIT: m_buffer16 = new wxInt16[m_blockSize * m_channels]; break; case FORMAT_32BIT: m_buffer32 = new wxFloat32[m_blockSize * m_channels]; break; } m_buffer = new float[m_blockSize * 2U]; return CThreadReader::open(sampleRate, blockSize); }
int WaveCloseWriteFile( HMMIO *phmmioOut, // (IN) MMCKINFO *pckOut, // (IN) MMCKINFO *pckOutRIFF, // (IN) MMIOINFO *pmmioinfoOut, // (IN) DWORD cSamples // (IN) ) { int nError; nError = 0; if (*phmmioOut == NULL) return(0); pmmioinfoOut->dwFlags |= MMIO_DIRTY; if ((nError = mmioSetInfo(*phmmioOut, pmmioinfoOut, 0)) != 0) { // cannot flush, probably... goto ERROR_CANNOT_WRITE; } /* Ascend the output file out of the 'data' chunk -- this will cause * the chunk size of the 'data' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably // Do this here instead... if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably nError = mmioSeek(*phmmioOut, 0, SEEK_SET); if ((nError = (int)mmioDescend(*phmmioOut, pckOutRIFF, NULL, 0)) != 0) goto ERROR_CANNOT_WRITE; nError = 0; pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't'); if ((nError = mmioDescend(*phmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK)) == 0) { // If it didn't fail, write the fact chunk out, if it failed, not critical, just // assert (below). nError = mmioWrite(*phmmioOut, (HPSTR)&cSamples, sizeof(DWORD)); nError = mmioAscend(*phmmioOut, pckOut, 0); nError = 0; } else { nError = 0; // ASSERT(FALSE); } /* Ascend the output file out of the 'RIFF' chunk -- this will cause * the chunk size of the 'RIFF' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably ERROR_CANNOT_WRITE: if (*phmmioOut != NULL) { mmioClose(*phmmioOut, 0); *phmmioOut = NULL; } return(nError); }
ALERROR CSoundMgr::LoadWaveFile (HMMIO hFile, int *retiChannel) // LoadWaveFile // // Creates a sound buffer from an open MMIO file { ASSERT(m_pDS); MMCKINFO parent, child; ::ZeroMemory(&parent, sizeof(parent)); ::ZeroMemory(&child, sizeof(child)); // Descend into the RIFF parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hFile, &parent, NULL, MMIO_FINDRIFF)) { mmioClose(hFile, 0); return ERR_FAIL; } // Descend to the wave format child.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hFile, &child, &parent, 0)) { mmioClose(hFile, 0); return ERR_FAIL; } // Allocate a block large enough to hold the format size DWORD dwFmtSize = child.cksize; DWORD dwAllocSize = max(dwFmtSize, sizeof(WAVEFORMATEX)); WAVEFORMATEX *pFormat = (WAVEFORMATEX *)new char [dwAllocSize]; ::ZeroMemory(pFormat, dwAllocSize); if (mmioRead(hFile, (char *)pFormat, dwFmtSize) != (LONG)dwFmtSize) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } // Now descend to the data if (mmioAscend(hFile, &child, 0)) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hFile, &child, &parent, MMIO_FINDCHUNK)) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } DWORD dwDataSize = child.cksize; // Create the DirectSound buffer DSBUFFERDESC dsbdesc; LPDIRECTSOUNDBUFFER pBuffer; ::ZeroMemory(&dsbdesc, sizeof(dsbdesc)); dsbdesc.dwSize = sizeof(dsbdesc); dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; dsbdesc.dwBufferBytes = dwDataSize; dsbdesc.lpwfxFormat = pFormat; if (FAILED(m_pDS->CreateSoundBuffer(&dsbdesc, &pBuffer, NULL))) { // If we can't create the sound buffer, try creating the same buffer // but with no volume or pan controls. dsbdesc.dwFlags = 0; if (FAILED(m_pDS->CreateSoundBuffer(&dsbdesc, &pBuffer, NULL))) { delete [] (char *)pFormat; return ERR_FAIL; } } delete [] (char *)pFormat; // Now read into the buffer LPVOID pDest; DWORD dwDestSize; if (FAILED(pBuffer->Lock(0, 0, &pDest, &dwDestSize, NULL, NULL, DSBLOCK_ENTIREBUFFER))) { pBuffer->Release(); mmioClose(hFile, 0); return ERR_FAIL; } if (mmioRead(hFile, (char *)pDest, dwDestSize) != (LONG)dwDataSize) { pBuffer->Release(); mmioClose(hFile, 0); return ERR_FAIL; } // Done with the wave file mmioClose(hFile, 0); // Add to the channel int iChannel = AllocChannel(); SChannel *pChannel = GetChannel(iChannel); pChannel->pBuffer = pBuffer; pChannel->pNext = NULL; // Done if (retiChannel) *retiChannel = iChannel; return NOERROR; }
int GYMCreateFile( TCHAR *pszFileName, // (IN) HMMIO *phmmioOut, // (OUT) WAVEFORMATEX *pwfxDest, // (IN) MMCKINFO *pckOut, // (OUT) MMCKINFO *pckOutRIFF // (OUT) ) { int nError; // Return value. DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. MMCKINFO ckOut1; char Name[128] = ""; char ext[12] = "_000.wav"; int num = -1, i, j; do { if (num++ > 99999) return(20); ext[0] = '_'; i = 1; j = num / 10000; if (j) ext[i++] = '0' + j; j = (num / 1000) % 10; if (j) ext[i++] = '0' + j; j = (num / 100) % 10; ext[i++] = '0' + j; j = (num / 10) % 10; ext[i++] = '0' + j; j = num % 10; ext[i++] = '0' + j; ext[i++] = '.'; ext[i++] = 'w'; ext[i++] = 'a'; ext[i++] = 'v'; ext[i] = 0; if ((strlen(pszFileName) + strlen(ext)) > 127) return(21); strcpy(Name, pszFileName); strcat(Name, ext); } while (mmioOpen(Name, NULL, MMIO_EXIST) == (HMMIO)TRUE); dwFactChunk = (DWORD)-1; nError = 0; *phmmioOut = mmioOpen(Name, NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE); if (*phmmioOut == NULL) { nError = ER_CANNOTWRITE; goto ERROR_CANNOT_WRITE; // cannot save WAVE file } /* Create the output file RIFF chunk of form type 'WAVE'. */ pckOutRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E'); pckOutRIFF->cksize = 0; if ((nError = mmioCreateChunk(*phmmioOut, pckOutRIFF, MMIO_CREATERIFF)) != 0) { goto ERROR_CANNOT_WRITE; // cannot write file, probably } /* We are now descended into the 'RIFF' chunk we just created. * Now create the 'fmt ' chunk. Since we know the size of this chunk, * specify it in the MMCKINFO structure so MMIO doesn't have to seek * back and set the chunk size after ascending from the chunk. */ pckOut->ckid = mmioFOURCC('f', 'm', 't', ' '); pckOut->cksize = sizeof(PCMWAVEFORMAT); // we know the size of this ck. if ((nError = mmioCreateChunk(*phmmioOut, pckOut, 0)) != 0) { goto ERROR_CANNOT_WRITE; // cannot write file, probably } /* Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. */ if (pwfxDest->wFormatTag == WAVE_FORMAT_PCM) { if (mmioWrite(*phmmioOut, (HPSTR)pwfxDest, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) { nError = ER_CANNOTWRITE; goto ERROR_CANNOT_WRITE; // cannot write file, probably } } else { // Write the variable length size. if ((UINT)mmioWrite(*phmmioOut, (HPSTR)pwfxDest, sizeof(*pwfxDest) + pwfxDest->cbSize) != (sizeof(*pwfxDest) + pwfxDest->cbSize)) { nError = ER_CANNOTWRITE; goto ERROR_CANNOT_WRITE; // cannot write file, probably } } /* Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. */ if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0) { goto ERROR_CANNOT_WRITE; // cannot write file, probably } // Now create the fact chunk, not required for PCM but nice to have. This is filled // in when the close routine is called. ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); ckOut1.cksize = 0; if ((nError = mmioCreateChunk(*phmmioOut, &ckOut1, 0)) != 0) { goto ERROR_CANNOT_WRITE; // cannot write file, probably } if (mmioWrite(*phmmioOut, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != sizeof(dwFactChunk)) { nError = ER_CANNOTWRITE; goto ERROR_CANNOT_WRITE; } // Now ascend out of the fact chunk... if ((nError = mmioAscend(*phmmioOut, &ckOut1, 0)) != 0) { nError = ER_CANNOTWRITE; // cannot write file, probably goto ERROR_CANNOT_WRITE; } goto DONE_CREATE; ERROR_CANNOT_WRITE: // Maybe delete the half-written file? Ah forget it for now, its good to leave the // file there for debugging... DONE_CREATE: return(nError); }
void CSoundMgr::Play (int iChannel, int iVolume, int iPan) // Play // // Plays a channel. // // iVolume = 0 for maximum volume. // iVolume = -10,000 for minimum volume. { if (m_pDS == NULL || m_iSoundVolume == 0) return; SChannel *pChannel = GetChannel(iChannel); if (pChannel->pBuffer == NULL) return; // If the buffer is lost, then we need to restore it DWORD dwStatus; pChannel->pBuffer->GetStatus(&dwStatus); if (dwStatus & DSBSTATUS_BUFFERLOST) { if (FAILED(pChannel->pBuffer->Restore())) return; if (pChannel->sFilename.IsBlank()) return; // Open the file MMCKINFO parent, child; ::ZeroMemory(&parent, sizeof(parent)); ::ZeroMemory(&child, sizeof(child)); HMMIO hFile = mmioOpen(pChannel->sFilename.GetASCIIZPointer(), NULL, MMIO_READ | MMIO_ALLOCBUF); if (hFile == NULL) return; // Descend into the RIFF parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hFile, &parent, NULL, MMIO_FINDRIFF)) { mmioClose(hFile, 0); return; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hFile, &child, &parent, MMIO_FINDCHUNK)) { mmioClose(hFile, 0); return; } DWORD dwDataSize = child.cksize; // Now read into the buffer LPVOID pDest; DWORD dwDestSize; if (FAILED(pChannel->pBuffer->Lock(0, 0, &pDest, &dwDestSize, NULL, NULL, DSBLOCK_ENTIREBUFFER))) { mmioClose(hFile, 0); return; } if (mmioRead(hFile, (char *)pDest, dwDestSize) != (LONG)dwDataSize) { mmioClose(hFile, 0); return; } // Done with the wave file mmioClose(hFile, 0); } // Check to see if the channel is busy. If it is, then we may need to create // a second buffer. else if (dwStatus & DSBSTATUS_PLAYING) { SChannel *pLastChannel = pChannel; pChannel = pChannel->pNext; while (pChannel) { pChannel->pBuffer->GetStatus(&dwStatus); if (!(dwStatus & DSBSTATUS_BUFFERLOST) && !(dwStatus & DSBSTATUS_PLAYING)) break; pLastChannel = pChannel; pChannel = pChannel->pNext; } // If we couldn't find another channel, then duplicate the original if (pChannel == NULL) { pChannel = GetChannel(iChannel); LPDIRECTSOUNDBUFFER pNewBuffer = NULL; if (FAILED(m_pDS->DuplicateSoundBuffer(pChannel->pBuffer, &pNewBuffer))) return; SChannel *pNewChannel = new SChannel; pLastChannel->pNext = pNewChannel; pNewChannel->pBuffer = pNewBuffer; pNewChannel->pNext = NULL; pChannel = pNewChannel; } } // Adjust volume int iVolumeAdj = MAX_VOLUME_LEVEL - m_iSoundVolume; int iMaxVolume = -(iVolumeAdj * VOLUME_STEP); int iVolumeRange = iMaxVolume - MIN_VOLUME; iVolume = iMaxVolume - ((iVolumeRange * iVolume) / MIN_VOLUME); // pChannel now points to a valid buffer. Play it! pChannel->pBuffer->SetVolume(iVolume); pChannel->pBuffer->SetPan(iPan); pChannel->pBuffer->Play(0, 0, 0); // Clean-up any channels after us that are done playing SChannel *pLastChannel = pChannel; pChannel = pChannel->pNext; while (pChannel) { pChannel->pBuffer->GetStatus(&dwStatus); if (!(dwStatus & DSBSTATUS_PLAYING)) { pChannel->pBuffer->Release(); pLastChannel->pNext = pChannel->pNext; delete pChannel; pChannel = pLastChannel->pNext; } else { pLastChannel = pChannel; pChannel = pChannel->pNext; } } }
HRESULT AddAviFrame (HAVI avi, HBITMAP hbm) { DIBSECTION dibs; TAviUtil *au; int sbm; HRESULT hr; if (!avi) return AVIERR_BADHANDLE; if (!hbm) return AVIERR_BADPARAM; sbm = GetObject(hbm, sizeof(dibs), &dibs); if (sbm != sizeof(DIBSECTION)) return AVIERR_BADPARAM; au = (TAviUtil*)avi; if (au->iserr) return AVIERR_ERROR; if (!au->vidStream) // create the stream, if it wasn't there before { AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr)); strhdr.fccType = streamtypeVIDEO; strhdr.fccHandler = 0; strhdr.dwScale = au->period; strhdr.dwRate = 1000000000; strhdr.dwSuggestedBufferSize = dibs.dsBmih.biSizeImage; SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight); hr = AVIFileCreateStream(au->pfile, &au->vidStream, &strhdr); if (hr) { au->iserr = TRUE; return hr; } } if (!au->vidStreamComp) // create an empty compression, if the user hasn't set any { AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts)); opts.fccHandler = mmioFOURCC('D','I','B',' '); hr = AVIMakeCompressedStream(&au->vidStreamComp, au->vidStream, &opts, NULL); if (hr) { au->iserr = TRUE; return hr; } hr = AVIStreamSetFormat(au->vidStreamComp, 0, &dibs.dsBmih, dibs.dsBmih.biSize + dibs.dsBmih.biClrUsed * sizeof(RGBQUAD)); if (hr) { au->iserr = TRUE; return hr; } } // Now we can add the frame hr = AVIStreamWrite(au->vidStreamComp, au->nframe, 1, dibs.dsBm.bmBits, dibs.dsBmih.biSizeImage, AVIIF_KEYFRAME, NULL, NULL); if (hr) { au->iserr = TRUE; return hr; } au->nframe++; return S_OK; }
#include <stdio.h> #include <stdint.h> #include <string.h> #include "common.h" #include "hw_limit.h" uint32_t audio_not_support[] = { mmioFOURCC('Q', 'c', 'l', 'p'), AUDIO_EAC3, 0xffff, // I14_HD_1080p12_unsupported_audio_01.divx 0 }; int check_audio_type(uint32_t type, uint32_t channel, unsigned char a_flag) { int ii = 0; int nRet = 1; while(audio_not_support[ii] != 0) { if (type == audio_not_support[ii]) { nRet = 0; break; } ii++; } // check hw support switch (a_flag)
static void afterReading(void* clientData, unsigned frameSize, unsigned /*numTruncatedBytes*/, struct timeval presentationTime, unsigned /*durationInMicroseconds*/) { int headersize = 0; if (frameSize >= MAX_RTP_FRAME_SIZE) { fprintf(stderr, "Saw an input frame too large (>=%d). Increase MAX_RTP_FRAME_SIZE in \"demux_rtp.cpp\".\n", MAX_RTP_FRAME_SIZE); } ReadBufferQueue* bufferQueue = (ReadBufferQueue*)clientData; demuxer_t* demuxer = bufferQueue->ourDemuxer(); RTPState* rtpState = (RTPState*)(demuxer->priv); if (frameSize > 0) demuxer->stream->eof = 0; demux_packet_t* dp = bufferQueue->dp; if (bufferQueue->readSource()->isAMRAudioSource()) headersize = 1; else if (bufferQueue == rtpState->videoBufferQueue && ((sh_video_t*)demuxer->video->sh)->format == mmioFOURCC('H','2','6','4')) { dp->buffer[0]=0x00; dp->buffer[1]=0x00; dp->buffer[2]=0x01; headersize = 3; } resize_demux_packet(dp, frameSize + headersize); // Set the packet's presentation time stamp, depending on whether or // not our RTP source's timestamps have been synchronized yet: Boolean hasBeenSynchronized = bufferQueue->rtpSource()->hasBeenSynchronizedUsingRTCP(); if (hasBeenSynchronized) { if (verbose > 0 && !bufferQueue->prevPacketWasSynchronized) { fprintf(stderr, "%s stream has been synchronized using RTCP \n", bufferQueue->tag()); } struct timeval* fst = &(rtpState->firstSyncTime); // abbrev if (fst->tv_sec == 0 && fst->tv_usec == 0) { *fst = presentationTime; } // For the "pts" field, use the time differential from the first // synchronized time, rather than absolute time, in order to avoid // round-off errors when converting to a float: dp->pts = presentationTime.tv_sec - fst->tv_sec + (presentationTime.tv_usec - fst->tv_usec)/1000000.0; bufferQueue->prevPacketPTS = dp->pts; } else { if (verbose > 0 && bufferQueue->prevPacketWasSynchronized) { fprintf(stderr, "%s stream is no longer RTCP-synchronized \n", bufferQueue->tag()); } // use the previous packet's "pts" once again: dp->pts = bufferQueue->prevPacketPTS; } bufferQueue->prevPacketWasSynchronized = hasBeenSynchronized; dp->pos = demuxer->filepos; demuxer->filepos += frameSize + headersize; // Signal any pending 'doEventLoop()' call on this queue: bufferQueue->blockingFlag = ~0; }
/* This function will open a wave input file and prepare it for reading, * so the data can be easily * read with WaveReadFile. Returns 0 if successful, the error code if not. * pszFileName - Input filename to load. * phmmioIn - Pointer to handle which will be used * for further mmio routines. * ppwfxInfo - Ptr to ptr to WaveFormatEx structure * with all info about the file. * */ int WaveOpenFile( TCHAR*pszFileName, // (IN) HMMIO *phmmioIn, // (OUT) WAVEFORMATEX **ppwfxInfo, // (OUT) MMCKINFO *pckInRIFF // (OUT) ) { HMMIO hmmioIn; MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. WORD cbExtraAlloc; // Extra bytes for waveformatex int nError; // Return value. // Initialization... *ppwfxInfo = NULL; nError = 0; hmmioIn = NULL; if ((hmmioIn = mmioOpen(pszFileName, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL) { nError = ER_CANNOTOPEN; goto ERROR_READING_WAVE; } if ((nError = (int)mmioDescend(hmmioIn, pckInRIFF, NULL, 0)) != 0) { goto ERROR_READING_WAVE; } if ((pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E'))) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } /* Search the input file for for the 'fmt ' chunk. */ ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if ((nError = (int)mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0) { goto ERROR_READING_WAVE; } /* Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; * if there are extra parameters at the end, we'll ignore them */ if (ckIn.cksize < (long) sizeof(PCMWAVEFORMAT)) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } /* Read the 'fmt ' chunk into <pcmWaveFormat>.*/ if (mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat, (long) sizeof(pcmWaveFormat)) != (long) sizeof(pcmWaveFormat)) { nError = ER_CANNOTREAD; goto ERROR_READING_WAVE; } // Ok, allocate the waveformatex, but if its not pcm // format, read the next word, and thats how many extra // bytes to allocate. if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM) cbExtraAlloc = 0; else { // Read in length of extra bytes. if (mmioRead(hmmioIn, (LPTSTR) &cbExtraAlloc, (long) sizeof(cbExtraAlloc)) != (long) sizeof(cbExtraAlloc)) { nError = ER_CANNOTREAD; goto ERROR_READING_WAVE; } } // Ok, now allocate that waveformatex structure. if ((*ppwfxInfo = GlobalAlloc(GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtraAlloc)) == NULL) { nError = ER_MEM; goto ERROR_READING_WAVE; } // Copy the bytes from the pcm structure to the waveformatex structure memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat)); (*ppwfxInfo)->cbSize = cbExtraAlloc; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if (cbExtraAlloc != 0) { if (mmioRead(hmmioIn, (LPTSTR) (((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(cbExtraAlloc)), (long) (cbExtraAlloc)) != (long) (cbExtraAlloc)) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } } /* Ascend the input file out of the 'fmt ' chunk. */ if ((nError = mmioAscend(hmmioIn, &ckIn, 0)) != 0) { goto ERROR_READING_WAVE; } goto TEMPCLEANUP; ERROR_READING_WAVE: if (*ppwfxInfo != NULL) { GlobalFree(*ppwfxInfo); *ppwfxInfo = NULL; } if (hmmioIn != NULL) { mmioClose(hmmioIn, 0); hmmioIn = NULL; } TEMPCLEANUP: *phmmioIn = hmmioIn; return(nError); }
bool CSoundFile::OpenWaveFile() { // code taken from Visual C++ Multimedia -- Aitken and Jarol p 122 // check if file is already open if(m_hFile) return FALSE; m_hFile = mmioOpen(m_szFileName,NULL,MMIO_READ); if(m_hFile == NULL) { m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoParent.fccType = mmioFOURCC('W','A','V','E'); MMRESULT mmResult = ::mmioDescend(m_hFile, &m_MMCKInfoParent,NULL,MMIO_FINDRIFF); if(mmResult) { //CString tstr; //tstr.LoadString(IDS_STRING_ERRDESCENT); //AfxMessageBox(tstr); AfxMessageBox("Error descending into file"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoChild.ckid = mmioFOURCC('f','m','t',' '); mmResult = mmioDescend(m_hFile,&m_MMCKInfoChild,&m_MMCKInfoParent,MMIO_FINDCHUNK); if(mmResult) { AfxMessageBox("Error descending in wave file"); mmioClose(m_hFile,0); m_Mode = FILE_ERROR; m_hFile = NULL; return FALSE; } DWORD bytesRead = mmioRead(m_hFile,(LPSTR)&m_Format,m_MMCKInfoChild.cksize); if(bytesRead < 0) { AfxMessageBox("Error reading PCM wave format record"); mmioClose(m_hFile,0); m_Mode = FILE_ERROR; return FALSE; } // open output sound file mmResult = mmioAscend(m_hFile,&m_MMCKInfoChild,0); if(mmResult) { AfxMessageBox("Error ascending in File"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoChild.ckid = mmioFOURCC('d','a','t','a'); mmResult = mmioDescend(m_hFile,&m_MMCKInfoChild, &m_MMCKInfoParent,MMIO_FINDCHUNK); if(mmResult) { AfxMessageBox("error reading data chunk"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } return TRUE; }
void rtpCodecInitialize_video(demuxer_t* demuxer, MediaSubsession* subsession, unsigned& flags) { flags = 0; // Create a dummy video stream header // to make the main MPlayer code happy: sh_video_t* sh_video = new_sh_video(demuxer,0); BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER)); bih->biSize = sizeof(BITMAPINFOHEADER); sh_video->bih = bih; demux_stream_t* d_video = demuxer->video; d_video->sh = sh_video; sh_video->ds = d_video; // Map known video MIME types to the BITMAPINFOHEADER parameters // that this program uses. (Note that not all types need all // of the parameters to be set.) if (strcmp(subsession->codecName(), "MPV") == 0) { flags |= RTPSTATE_IS_MPEG12_VIDEO; } else if (strcmp(subsession->codecName(), "MP1S") == 0 || strcmp(subsession->codecName(), "MP2T") == 0) { flags |= RTPSTATE_IS_MPEG12_VIDEO|RTPSTATE_IS_MULTIPLEXED; } else if (strcmp(subsession->codecName(), "H263") == 0 || strcmp(subsession->codecName(), "H263-2000") == 0 || strcmp(subsession->codecName(), "H263-1998") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','3'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "H264") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','4'); unsigned int configLen = 0; unsigned char* configData = parseH264ConfigStr(subsession->fmtp_spropparametersets(), configLen); sh_video->bih = bih = insertVideoExtradata(bih, configData, configLen); delete[] configData; #ifdef CONFIG_LIBAVCODEC avcodec_register_all(); h264parserctx = av_parser_init(CODEC_ID_H264); avcctx = avcodec_alloc_context(); #endif needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "H261") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','1'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "JPEG") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('M','J','P','G'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "MP4V-ES") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('m','p','4','v'); // For the codec to work correctly, it may need a 'VOL Header' to be // inserted at the front of the data stream. Construct this from the // "config" MIME parameter, which was present (hopefully) in the // session's SDP description: unsigned configLen; unsigned char* configData = parseGeneralConfigStr(subsession->fmtp_config(), configLen); sh_video->bih = bih = insertVideoExtradata(bih, configData, configLen); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "X-QT") == 0 || strcmp(subsession->codecName(), "X-QUICKTIME") == 0) { // QuickTime generic RTP format, as described in // http://developer.apple.com/quicktime/icefloe/dispatch026.html // We can't initialize this stream until we've received the first packet // that has QuickTime "sdAtom" information in the header. So, keep // reading packets until we get one: unsigned char* packetData; unsigned packetDataLen; float pts; QuickTimeGenericRTPSource* qtRTPSource = (QuickTimeGenericRTPSource*)(subsession->rtpSource()); unsigned fourcc; do { if (!awaitRTPPacket(demuxer, demuxer->video, packetData, packetDataLen, pts)) { return; } } while (!parseQTState_video(qtRTPSource->qtState, fourcc)); bih->biCompression = sh_video->format = fourcc; bih->biWidth = qtRTPSource->qtState.width; bih->biHeight = qtRTPSource->qtState.height; if (qtRTPSource->qtState.sdAtomSize > 83) bih->biBitCount = qtRTPSource->qtState.sdAtom[83]; uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 86; uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom + qtRTPSource->qtState.sdAtomSize; while (pos+8 < endpos) { unsigned atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3]; if (atomLength == 0 || atomLength > endpos-pos) break; if (((!memcmp(pos+4, "avcC", 4) && fourcc==mmioFOURCC('a','v','c','1')) || !memcmp(pos+4, "esds", 4) || (!memcmp(pos+4, "SMI ", 4) && fourcc==mmioFOURCC('S','V','Q','3'))) && atomLength > 8) { sh_video->bih = bih = insertVideoExtradata(bih, pos+8, atomLength-8); break; } pos += atomLength; } needVideoFrameRate(demuxer, subsession); } else { fprintf(stderr, "Unknown MPlayer format code for MIME type \"video/%s\"\n", subsession->codecName()); } }
static HRESULT WINAPI IDirectMusicChordMapImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) { ICOM_THIS_MULTI(IDirectMusicChordMapImpl, PersistStreamVtbl, iface); FOURCC chunkID; DWORD chunkSize, StreamSize, StreamCount, ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ FIXME("(%p, %p): Loading not implemented yet\n", This, pStm); IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL); IStream_Read (pStm, &chunkSize, sizeof(DWORD), NULL); TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize); switch (chunkID) { case FOURCC_RIFF: { IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunkID)); StreamSize = chunkSize - sizeof(FOURCC); StreamCount = 0; switch (chunkID) { case DMUS_FOURCC_CHORDMAP_FORM: { TRACE_(dmfile)(": chordmap form\n"); do { IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL); IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL); StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunkSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize); switch (chunkID) { case DMUS_FOURCC_GUID_CHUNK: { TRACE_(dmfile)(": GUID chunk\n"); This->pDesc->dwValidData |= DMUS_OBJ_OBJECT; IStream_Read (pStm, &This->pDesc->guidObject, chunkSize, NULL); break; } case DMUS_FOURCC_VERSION_CHUNK: { TRACE_(dmfile)(": version chunk\n"); This->pDesc->dwValidData |= DMUS_OBJ_VERSION; IStream_Read (pStm, &This->pDesc->vVersion, chunkSize, NULL); break; } case DMUS_FOURCC_CATEGORY_CHUNK: { TRACE_(dmfile)(": category chunk\n"); This->pDesc->dwValidData |= DMUS_OBJ_CATEGORY; IStream_Read (pStm, This->pDesc->wszCategory, chunkSize, NULL); break; } case FOURCC_LIST: { IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID)); ListSize[0] = chunkSize - sizeof(FOURCC); ListCount[0] = 0; switch (chunkID) { case DMUS_FOURCC_UNFO_LIST: { TRACE_(dmfile)(": UNFO list\n"); do { IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL); IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL); ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize); switch (chunkID) { /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes (though strings seem to be valid unicode) */ case mmioFOURCC('I','N','A','M'): case DMUS_FOURCC_UNAM_CHUNK: { TRACE_(dmfile)(": name chunk\n"); This->pDesc->dwValidData |= DMUS_OBJ_NAME; IStream_Read (pStm, This->pDesc->wszName, chunkSize, NULL); break; } case mmioFOURCC('I','A','R','T'): case DMUS_FOURCC_UART_CHUNK: { TRACE_(dmfile)(": artist chunk (ignored)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','O','P'): case DMUS_FOURCC_UCOP_CHUNK: { TRACE_(dmfile)(": copyright chunk (ignored)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','S','B','J'): case DMUS_FOURCC_USBJ_CHUNK: { TRACE_(dmfile)(": subject chunk (ignored)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } case mmioFOURCC('I','C','M','T'): case DMUS_FOURCC_UCMT_CHUNK: { TRACE_(dmfile)(": comment chunk (ignored)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]); } while (ListCount[0] < ListSize[0]); break; } default: { TRACE_(dmfile)(": unknown (skipping)\n"); liMove.QuadPart = chunkSize - sizeof(FOURCC); IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } break; } default: { TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; } } TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize); } while (StreamCount < StreamSize); break; } default: { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = StreamSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return E_FAIL; } } TRACE_(dmfile)(": reading finished\n"); break; } default: { TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); liMove.QuadPart = chunkSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ return E_FAIL; } } return S_OK; }
void rtpCodecInitialize_audio(demuxer_t* demuxer, MediaSubsession* subsession, unsigned& flags) { flags = 0; // Create a dummy audio stream header // to make the main MPlayer code happy: sh_audio_t* sh_audio = new_sh_audio(demuxer,0); WAVEFORMATEX* wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX)); sh_audio->wf = wf; demux_stream_t* d_audio = demuxer->audio; d_audio->sh = sh_audio; sh_audio->ds = d_audio; d_audio->id = sh_audio->aid; wf->nChannels = subsession->numChannels(); // Map known audio MIME types to the WAVEFORMATEX parameters // that this program uses. (Note that not all types need all // of the parameters to be set.) wf->nSamplesPerSec = subsession->rtpSource()->timestampFrequency(); // by default if (strcmp(subsession->codecName(), "MPA") == 0 || strcmp(subsession->codecName(), "MPA-ROBUST") == 0 || strcmp(subsession->codecName(), "X-MP3-DRAFT-00") == 0) { wf->wFormatTag = sh_audio->format = 0x55; // Note: 0x55 is for layer III, but should work for I,II also wf->nSamplesPerSec = 0; // sample rate is deduced from the data } else if (strcmp(subsession->codecName(), "AC3") == 0) { wf->wFormatTag = sh_audio->format = 0x2000; wf->nSamplesPerSec = 0; // sample rate is deduced from the data } else if (strcmp(subsession->codecName(), "L16") == 0) { wf->wFormatTag = sh_audio->format = 0x736f7774; // "twos" wf->nBlockAlign = 1; wf->wBitsPerSample = 16; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "L8") == 0) { wf->wFormatTag = sh_audio->format = 0x20776172; // "raw " wf->nBlockAlign = 1; wf->wBitsPerSample = 8; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "PCMU") == 0) { wf->wFormatTag = sh_audio->format = 0x7; wf->nAvgBytesPerSec = 8000; wf->nBlockAlign = 1; wf->wBitsPerSample = 8; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "PCMA") == 0) { wf->wFormatTag = sh_audio->format = 0x6; wf->nAvgBytesPerSec = 8000; wf->nBlockAlign = 1; wf->wBitsPerSample = 8; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "AMR") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('s','a','m','r'); } else if (strcmp(subsession->codecName(), "AMR-WB") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('s','a','w','b'); } else if (strcmp(subsession->codecName(), "GSM") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('a','g','s','m'); wf->nAvgBytesPerSec = 1650; wf->nBlockAlign = 33; wf->wBitsPerSample = 16; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "QCELP") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('Q','c','l','p'); wf->nAvgBytesPerSec = 1750; wf->nBlockAlign = 35; wf->wBitsPerSample = 16; wf->cbSize = 0; } else if (strcmp(subsession->codecName(), "MP4A-LATM") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('m','p','4','a'); // For the codec to work correctly, it needs "AudioSpecificConfig" // data, which is parsed from the "StreamMuxConfig" string that // was present (hopefully) in the SDP description: unsigned codecdata_len; sh_audio->codecdata = parseStreamMuxConfigStr(subsession->fmtp_config(), codecdata_len); sh_audio->codecdata_len = codecdata_len; //faad doesn't understand LATM's data length field, so omit it ((MPEG4LATMAudioRTPSource*)subsession->rtpSource())->omitLATMDataLengthField(); } else if (strcmp(subsession->codecName(), "MPEG4-GENERIC") == 0) { wf->wFormatTag = sh_audio->format = mmioFOURCC('m','p','4','a'); // For the codec to work correctly, it needs "AudioSpecificConfig" // data, which was present (hopefully) in the SDP description: unsigned codecdata_len; sh_audio->codecdata = parseGeneralConfigStr(subsession->fmtp_config(), codecdata_len); sh_audio->codecdata_len = codecdata_len; } else if (strcmp(subsession->codecName(), "X-QT") == 0 || strcmp(subsession->codecName(), "X-QUICKTIME") == 0) { // QuickTime generic RTP format, as described in // http://developer.apple.com/quicktime/icefloe/dispatch026.html // We can't initialize this stream until we've received the first packet // that has QuickTime "sdAtom" information in the header. So, keep // reading packets until we get one: unsigned char* packetData; unsigned packetDataLen; float pts; QuickTimeGenericRTPSource* qtRTPSource = (QuickTimeGenericRTPSource*)(subsession->rtpSource()); unsigned fourcc, numChannels; do { if (!awaitRTPPacket(demuxer, demuxer->audio, packetData, packetDataLen, pts)) { return; } } while (!parseQTState_audio(qtRTPSource->qtState, fourcc, numChannels)); wf->wFormatTag = sh_audio->format = fourcc; wf->nChannels = numChannels; if (qtRTPSource->qtState.sdAtomSize > 33) { wf->wBitsPerSample = qtRTPSource->qtState.sdAtom[27]; wf->nSamplesPerSec = qtRTPSource->qtState.sdAtom[32]<<8|qtRTPSource->qtState.sdAtom[33]; } uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 52; uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom + qtRTPSource->qtState.sdAtomSize; while (pos+8 < endpos) { unsigned atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3]; if (atomLength == 0 || atomLength > endpos-pos) break; if (!memcmp(pos+4, "wave", 4) && fourcc==mmioFOURCC('Q','D','M','2') && atomLength > 8 && atomLength <= INT_MAX) { sh_audio->codecdata = (unsigned char*) malloc(atomLength-8); if (sh_audio->codecdata) { memcpy(sh_audio->codecdata, pos+8, atomLength-8); sh_audio->codecdata_len = atomLength-8; } break; } pos += atomLength; } } else { fprintf(stderr, "Unknown MPlayer format code for MIME type \"audio/%s\"\n", subsession->codecName()); } }
static demuxer_t* demux_open_avs(demuxer_t* demuxer) { int found = 0; AVS_T *AVS = demuxer->priv; int audio_samplesize = 0; AVS->frameno = 0; AVS->sampleno = 0; mp_msg(MSGT_DEMUX, MSGL_V, "AVS: demux_open_avs()\n"); demuxer->seekable = 1; AVS->clip = AVS->avs_take_clip(AVS->handler, AVS->avs_env); if(!AVS->clip) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_take_clip() failed\n"); return NULL; } AVS->video_info = AVS->avs_get_video_info(AVS->clip); if (!AVS->video_info) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_video_info() call failed\n"); return NULL; } if (!avs_is_yv12(AVS->video_info)) { AVS->handler = AVS->avs_invoke(AVS->avs_env, "ConvertToYV12", avs_new_value_array(&AVS->handler, 1), 0); if (avs_is_error(AVS->handler)) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Cannot convert input video to YV12: %s\n", avs_as_string(AVS->handler)); return NULL; } AVS->clip = AVS->avs_take_clip(AVS->handler, AVS->avs_env); if(!AVS->clip) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_take_clip() failed\n"); return NULL; } AVS->video_info = AVS->avs_get_video_info(AVS->clip); if (!AVS->video_info) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_video_info() call failed\n"); return NULL; } } // TODO check field-based ?? /* Video */ if (avs_has_video(AVS->video_info)) { sh_video_t *sh_video = new_sh_video(demuxer, 0); found = 1; if (demuxer->video->id == -1) demuxer->video->id = 0; if (demuxer->video->id == 0) demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; sh_video->disp_w = AVS->video_info->width; sh_video->disp_h = AVS->video_info->height; //sh_video->format = get_mmioFOURCC(AVS->video_info); sh_video->format = mmioFOURCC('Y', 'V', '1', '2'); sh_video->fps = (double) AVS->video_info->fps_numerator / (double) AVS->video_info->fps_denominator; sh_video->frametime = 1.0 / sh_video->fps; sh_video->bih = malloc(sizeof(BITMAPINFOHEADER) + (256 * 4)); sh_video->bih->biCompression = sh_video->format; sh_video->bih->biBitCount = avs_bits_per_pixel(AVS->video_info); //sh_video->bih->biPlanes = 2; sh_video->bih->biWidth = AVS->video_info->width; sh_video->bih->biHeight = AVS->video_info->height; sh_video->num_frames = 0; sh_video->num_frames_decoded = 0; } /* Audio */ if (avs_has_audio(AVS->video_info)) switch (AVS->video_info->sample_type) { case AVS_SAMPLE_INT8: audio_samplesize = 1; break; case AVS_SAMPLE_INT16: audio_samplesize = 2; break; case AVS_SAMPLE_INT24: audio_samplesize = 3; break; case AVS_SAMPLE_INT32: case AVS_SAMPLE_FLOAT: audio_samplesize = 4; break; default: mp_msg(MSGT_DEMUX, MSGL_ERR, "AVS: unknown audio type, disabling\n"); } if (audio_samplesize) { sh_audio_t *sh_audio = new_sh_audio(demuxer, 0); found = 1; mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Clip has audio -> Channels = %d - Freq = %d\n", AVS->video_info->nchannels, AVS->video_info->audio_samples_per_second); if (demuxer->audio->id == -1) demuxer->audio->id = 0; if (demuxer->audio->id == 0) demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); sh_audio->wf->wFormatTag = sh_audio->format = (AVS->video_info->sample_type == AVS_SAMPLE_FLOAT) ? 0x3 : 0x1; sh_audio->wf->nChannels = sh_audio->channels = AVS->video_info->nchannels; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate = AVS->video_info->audio_samples_per_second; sh_audio->samplesize = audio_samplesize; sh_audio->wf->nAvgBytesPerSec = sh_audio->channels * sh_audio->samplesize * sh_audio->samplerate; sh_audio->wf->nBlockAlign = sh_audio->channels * sh_audio->samplesize; sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8; sh_audio->wf->cbSize = 0; sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; } AVS->init = 1; if (found) return demuxer; else return NULL; }
static HRESULT AVIFILE_LoadSunFile(IAVIFileImpl *This) { SUNAUDIOHEADER auhdr; mmioSeek(This->hmmio, 0, SEEK_SET); if (mmioRead(This->hmmio, (HPSTR)&auhdr, sizeof(auhdr)) != sizeof(auhdr)) return AVIERR_FILEREAD; if (auhdr.fccType == 0x0064732E) { /* header in little endian */ This->ckData.dwDataOffset = LE2H_DWORD(auhdr.offset); This->ckData.cksize = LE2H_DWORD(auhdr.size); auhdr.encoding = LE2H_DWORD(auhdr.encoding); auhdr.sampleRate = LE2H_DWORD(auhdr.sampleRate); auhdr.channels = LE2H_DWORD(auhdr.channels); } else if (auhdr.fccType == mmioFOURCC('.','s','n','d')) { /* header in big endian */ This->ckData.dwDataOffset = BE2H_DWORD(auhdr.offset); This->ckData.cksize = BE2H_DWORD(auhdr.size); auhdr.encoding = BE2H_DWORD(auhdr.encoding); auhdr.sampleRate = BE2H_DWORD(auhdr.sampleRate); auhdr.channels = BE2H_DWORD(auhdr.channels); } else return AVIERR_FILEREAD; if (auhdr.channels < 1) return AVIERR_BADFORMAT; /* get size of header */ switch(auhdr.encoding) { case AU_ENCODING_ADPCM_G721_32: This->cbFormat = sizeof(G721_ADPCMWAVEFORMAT); break; case AU_ENCODING_ADPCM_G723_24: This->cbFormat = sizeof(G723_ADPCMWAVEFORMAT); break; case AU_ENCODING_ADPCM_G722: case AU_ENCODING_ADPCM_G723_5: WARN("unsupported Sun audio format %d\n", auhdr.encoding); return AVIERR_UNSUPPORTED; /* FIXME */ default: This->cbFormat = sizeof(WAVEFORMATEX); break; }; This->lpFormat = HeapAlloc(GetProcessHeap(), 0, This->cbFormat); if (This->lpFormat == NULL) return AVIERR_MEMORY; This->lpFormat->nChannels = auhdr.channels; This->lpFormat->nSamplesPerSec = auhdr.sampleRate; switch(auhdr.encoding) { case AU_ENCODING_ULAW_8: This->lpFormat->wFormatTag = WAVE_FORMAT_MULAW; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_PCM_8: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_PCM_16: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 16; break; case AU_ENCODING_PCM_24: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 24; break; case AU_ENCODING_PCM_32: This->lpFormat->wFormatTag = WAVE_FORMAT_PCM; This->lpFormat->wBitsPerSample = 32; break; case AU_ENCODING_ALAW_8: This->lpFormat->wFormatTag = WAVE_FORMAT_ALAW; This->lpFormat->wBitsPerSample = 8; break; case AU_ENCODING_ADPCM_G721_32: This->lpFormat->wFormatTag = WAVE_FORMAT_G721_ADPCM; This->lpFormat->wBitsPerSample = (3*5*8); This->lpFormat->nBlockAlign = 15*15*8; This->lpFormat->cbSize = sizeof(WORD); ((LPG721_ADPCMWAVEFORMAT)This->lpFormat)->nAuxBlockSize = 0; break; case AU_ENCODING_ADPCM_G723_24: This->lpFormat->wFormatTag = WAVE_FORMAT_G723_ADPCM; This->lpFormat->wBitsPerSample = (3*5*8); This->lpFormat->nBlockAlign = 15*15*8; This->lpFormat->cbSize = 2*sizeof(WORD); ((LPG723_ADPCMWAVEFORMAT)This->lpFormat)->cbExtraSize = 0; ((LPG723_ADPCMWAVEFORMAT)This->lpFormat)->nAuxBlockSize = 0; break; default: WARN("unsupported Sun audio format %d\n", auhdr.encoding); return AVIERR_UNSUPPORTED; }; This->lpFormat->nBlockAlign = (This->lpFormat->nChannels * This->lpFormat->wBitsPerSample) / 8; if (This->lpFormat->nBlockAlign == 0 && This->lpFormat->wBitsPerSample < 8) This->lpFormat->nBlockAlign++; This->lpFormat->nAvgBytesPerSec = This->lpFormat->nBlockAlign * This->lpFormat->nSamplesPerSec; This->fDirty = FALSE; This->sInfo.fccType = streamtypeAUDIO; This->sInfo.fccHandler = 0; This->sInfo.dwFlags = 0; This->sInfo.wPriority = 0; This->sInfo.wLanguage = 0; This->sInfo.dwInitialFrames = 0; This->sInfo.dwScale = This->lpFormat->nBlockAlign; This->sInfo.dwRate = This->lpFormat->nAvgBytesPerSec; This->sInfo.dwStart = 0; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->sInfo.dwLength; This->sInfo.dwSampleSize = This->lpFormat->nBlockAlign; This->fInfo.dwStreams = 1; This->fInfo.dwScale = 1; This->fInfo.dwRate = This->lpFormat->nSamplesPerSec; This->fInfo.dwLength = MulDiv(This->ckData.cksize, This->lpFormat->nSamplesPerSec, This->lpFormat->nAvgBytesPerSec); return AVIERR_OK; }