static LONG WINAPI ICMStream_fnFindSample(IAVIStream *iface, LONG pos, LONG flags) { IAVIStreamImpl *This = impl_from_IAVIStream(iface); TRACE("(%p,%d,0x%08X)\n",iface,pos,flags); if (flags & FIND_FROM_START) { pos = This->sInfo.dwStart; flags &= ~(FIND_FROM_START|FIND_PREV); flags |= FIND_NEXT; } if (flags & FIND_RET) WARN(": FIND_RET flags will be ignored!\n"); if (flags & FIND_KEY) { if (This->hic == NULL) return pos; /* we decompress so every frame is a keyframe */ if (flags & FIND_PREV) { /* need to read old or new frames? */ if (This->lLastKey <= pos || pos < This->lCurrent) IAVIStream_Read(iface, pos, 1, NULL, 0, NULL, NULL); return This->lLastKey; } } else if (flags & FIND_ANY) { return pos; /* We really don't know, reread is too expensive, so guess. */ } else if (flags & FIND_FORMAT) { if (flags & FIND_PREV) return 0; } return -1; }
static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start, LONG samples,LPVOID buffer, LONG buffersize,LONG*bytesread, LONG*samplesread) { IAVIEditStreamImpl *This = impl_from_IAVIStream( iface ); PAVISTREAM stream; DWORD streamPos, streamNr; LONG readBytes, readSamples, count; HRESULT hr; TRACE("(%p,%d,%d,%p,%d,%p,%p) -- 0x%08X\n",iface,start,samples, buffer,buffersize,bytesread,samplesread,This->sInfo.fccType); /* check parameters */ if (bytesread != NULL) *bytesread = 0; if (samplesread != NULL) *samplesread = 0; if (buffersize < 0) return AVIERR_BADSIZE; if ((DWORD)start < This->sInfo.dwStart || This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start) return AVIERR_BADPARAM; if (! This->bDecompress) { /* audio like data -- sample-based */ do { if (samples == 0) return AVIERR_OK; /* nothing at all or already done */ if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream, &streamPos, &streamNr, FALSE))) return AVIERR_ERROR; /* limit to end of the stream */ count = samples; if (streamPos + count > EditStreamEnd(This, streamNr)) count = EditStreamEnd(This, streamNr) - streamPos; hr = IAVIStream_Read(stream, streamPos, count, buffer, buffersize, &readBytes, &readSamples); if (FAILED(hr)) return hr; if (readBytes == 0 && readSamples == 0 && count != 0) return AVIERR_FILEREAD; /* for bad stream implementations */ if (samplesread != NULL) *samplesread += readSamples; if (bytesread != NULL) *bytesread += readBytes; if (buffer != NULL) { buffer = ((LPBYTE)buffer)+readBytes; buffersize -= readBytes; } start += count; samples -= count; } while (This->sInfo.dwStart + This->sInfo.dwLength > start); } else { /* video like data -- frame-based */ LPBITMAPINFOHEADER lp; if (samples == 0) return AVIERR_OK; if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream, &streamPos, &streamNr, FALSE))) return AVIERR_ERROR; lp = AVIFILE_ReadFrame(This, stream, streamPos); if (lp == NULL) return AVIERR_ERROR; if (buffer != NULL) { /* need size of format to skip */ if (lp->biBitCount <= 8) { count = lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount; count *= sizeof(RGBQUAD); } else count = 0; count += lp->biSize; if (buffersize < lp->biSizeImage) return AVIERR_BUFFERTOOSMALL; memcpy(buffer, (LPBYTE)lp + count, lp->biSizeImage); } if (bytesread != NULL) *bytesread = lp->biSizeImage; if (samplesread != NULL) *samplesread = 1; } return AVIERR_OK; }
static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start, LONG samples, LPVOID buffer, LONG buffersize, LPLONG bytesread, LPLONG samplesread) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; HRESULT hr; DWORD size; TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer, buffersize, bytesread, samplesread); /* clear return parameters if given */ if (bytesread != NULL) *bytesread = 0; if (samplesread != NULL) *samplesread = 0; /* Do we have our compressor? */ if (This->has == NULL) { hr = AVIFILE_OpenCompressor(This); if (FAILED(hr)) return hr; } /* only need to pass through? */ if (This->cbInFormat == This->cbOutFormat && memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) { return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize, bytesread, samplesread); } /* read as much as fit? */ if (samples == -1) samples = buffersize / This->lpOutFormat->nBlockAlign; /* limit to buffersize */ if (samples * This->lpOutFormat->nBlockAlign > buffersize) samples = buffersize / This->lpOutFormat->nBlockAlign; /* only return needed size? */ if (buffer == NULL || buffersize <= 0 || samples == 0) { if (bytesread == NULL && samplesread == NULL) return AVIERR_BADPARAM; if (bytesread != NULL) *bytesread = samples * This->lpOutFormat->nBlockAlign; if (samplesread != NULL) *samplesread = samples; return AVIERR_OK; } /* map our positions to pStream positions */ CONVERT_THIS_to_STREAM(&start); /* our needed internal buffersize */ size = samples * This->lpInFormat->nBlockAlign; /* Need to free destination buffer used for writing? */ if (This->acmStreamHdr.pbDst != NULL) { HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst); This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.dwDstUser = 0; } /* need bigger source buffer? */ if (This->acmStreamHdr.pbSrc == NULL || This->acmStreamHdr.dwSrcUser < size) { if (This->acmStreamHdr.pbSrc == NULL) This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size); else This->acmStreamHdr.pbSrc = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size); if (This->acmStreamHdr.pbSrc == NULL) return AVIERR_MEMORY; This->acmStreamHdr.dwSrcUser = size; } This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr); This->acmStreamHdr.cbSrcLengthUsed = 0; This->acmStreamHdr.cbDstLengthUsed = 0; This->acmStreamHdr.cbSrcLength = size; /* read source data */ hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc, This->acmStreamHdr.cbSrcLength, (LONG *)&This->acmStreamHdr.cbSrcLength, NULL); if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0) return hr; /* need to prepare stream? */ This->acmStreamHdr.pbDst = buffer; This->acmStreamHdr.cbDstLength = buffersize; if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) { if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) { This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.cbDstLength = 0; return AVIERR_COMPRESSOR; } } /* now do the conversion */ /* FIXME: use ACM_CONVERTF_* flags */ if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK) hr = AVIERR_COMPRESSOR; This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.cbDstLength = 0; /* fill out return parameters if given */ if (bytesread != NULL) *bytesread = This->acmStreamHdr.cbDstLengthUsed; if (samplesread != NULL) *samplesread = This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign; return hr; }