📄 acmstream.c
字号:
return AVIERR_UNSUPPORTED;
return AVIERR_OK;
}
/* Does the nested stream support writing? */
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
return AVIERR_READONLY;
This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
if (This->lpInFormat == NULL)
return AVIERR_MEMORY;
This->cbInFormat = formatsize;
memcpy(This->lpInFormat, format, formatsize);
/* initialize formats and get compressor */
hr = AVIFILE_OpenCompressor(This);
if (FAILED(hr))
return hr;
CONVERT_THIS_to_STREAM(&pos);
/* tell the nested stream the new format */
return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
This->cbOutFormat);
}
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.pbDst = 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;
}
static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
LONG samples, LPVOID buffer,
LONG buffersize, DWORD flags,
LPLONG sampwritten,
LPLONG byteswritten)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
HRESULT hr;
ULONG size;
TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
buffer, buffersize, flags, sampwritten, byteswritten);
/* clear return parameters if given */
if (sampwritten != NULL)
*sampwritten = 0;
if (byteswritten != NULL)
*byteswritten = 0;
/* check parameters */
if (buffer == NULL && (buffersize > 0 || samples > 0))
return AVIERR_BADPARAM;
/* Have we write capability? */
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
return AVIERR_READONLY;
/* also need a compressor */
if (This->has == NULL)
return AVIERR_NOCOMPRESSOR;
/* map our sizes to pStream sizes */
size = buffersize;
CONVERT_THIS_to_STREAM(&size);
CONVERT_THIS_to_STREAM(&start);
/* no bytes to write? -- short circuit */
if (size == 0) {
return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
flags, sampwritten, byteswritten);
}
/* Need to free source buffer used for reading? */
if (This->acmStreamHdr.pbSrc != NULL) {
HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
This->acmStreamHdr.pbSrc = NULL;
This->acmStreamHdr.dwSrcUser = 0;
}
/* Need bigger destination buffer? */
if (This->acmStreamHdr.pbDst == NULL ||
This->acmStreamHdr.dwDstUser < size) {
if (This->acmStreamHdr.pbDst == NULL)
This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size);
else
This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size);
if (This->acmStreamHdr.pbDst == NULL)
return AVIERR_MEMORY;
This->acmStreamHdr.dwDstUser = size;
}
This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
This->acmStreamHdr.cbSrcLengthUsed = 0;
This->acmStreamHdr.cbDstLengthUsed = 0;
This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
/* need to prepare stream? */
This->acmStreamHdr.pbSrc = buffer;
This->acmStreamHdr.cbSrcLength = buffersize;
if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
This->acmStreamHdr.pbSrc = NULL;
This->acmStreamHdr.cbSrcLength = 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;
else
hr = AVIERR_OK;
This->acmStreamHdr.pbSrc = NULL;
This->acmStreamHdr.cbSrcLength = 0;
if (FAILED(hr))
return hr;
return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
byteswritten);
}
static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
LONG samples)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
TRACE("(%p,%d,%d)\n", iface, start, samples);
/* check parameters */
if (start < 0 || samples < 0)
return AVIERR_BADPARAM;
/* Delete before start of stream? */
if ((DWORD)(start + samples) < This->sInfo.dwStart)
return AVIERR_OK;
/* Delete after end of stream? */
if ((DWORD)start > This->sInfo.dwLength)
return AVIERR_OK;
/* For the rest we need write capability */
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
return AVIERR_READONLY;
/* A compressor is also necessary */
if (This->has == NULL)
return AVIERR_NOCOMPRESSOR;
/* map our positions to pStream positions */
CONVERT_THIS_to_STREAM(&start);
CONVERT_THIS_to_STREAM(&samples);
return IAVIStream_Delete(This->pStream, start, samples);
}
static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
LPVOID lp, LPLONG lpread)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
assert(This->pStream != NULL);
return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
}
static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
LPVOID lp, LONG size)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
assert(This->pStream != NULL);
return IAVIStream_WriteData(This->pStream, fcc, lp, size);
}
static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
LPAVISTREAMINFOW info, LONG infolen)
{
FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
return E_FAIL;
}
/***********************************************************************/
static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
{
HRESULT hr;
/* pre-conditions */
assert(This != NULL);
assert(This->pStream != NULL);
if (This->has != NULL)
return AVIERR_OK;
if (This->lpInFormat == NULL) {
/* decode or encode the data from pStream */
hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
if (FAILED(hr))
return hr;
This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat);
if (This->lpInFormat == NULL)
return AVIERR_MEMORY;
hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
This->lpInFormat, &This->cbInFormat);
if (FAILED(hr))
return hr;
if (This->lpOutFormat == NULL) {
/* we must decode to default format */
This->cbOutFormat = sizeof(PCMWAVEFORMAT);
This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
if (This->lpOutFormat == NULL)
return AVIERR_MEMORY;
This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
return AVIERR_NOCOMPRESSOR;
}
} else if (This->lpOutFormat == NULL)
return AVIERR_ERROR; /* To what should I encode? */
if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
return AVIERR_NOCOMPRESSOR;
/* update AVISTREAMINFO structure */
This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
SetRectEmpty(&This->sInfo.rcFrame);
/* convert positions ansd sizes to output format */
CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
return AVIERR_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -