quartz: Make acmwrapper code aware of time, and get rid of its internal buffer.
This commit is contained in:
parent
c423511d2e
commit
f8bb838455
|
@ -41,19 +41,12 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
||||
/* FIXME: Improve buffers management */
|
||||
#define OUTPUT_BUFFER_SIZE 15000
|
||||
#define INPUT_BUFFER_SIZE 4096
|
||||
|
||||
typedef struct ACMWrapperImpl
|
||||
{
|
||||
TransformFilterImpl tf;
|
||||
HACMSTREAM has;
|
||||
LPWAVEFORMATEX pWfIn;
|
||||
LPWAVEFORMATEX pWfOut;
|
||||
BYTE buffer[INPUT_BUFFER_SIZE];
|
||||
DWORD max_size;
|
||||
DWORD current_size;
|
||||
BOOL reinit_codec; /* FIXME: Should use sync points instead */
|
||||
} ACMWrapperImpl;
|
||||
|
||||
|
@ -62,16 +55,14 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
|
||||
AM_MEDIA_TYPE amt;
|
||||
IMediaSample* pOutSample = NULL;
|
||||
DWORD cbDstStream;
|
||||
DWORD cbDstStream, cbSrcStream;
|
||||
LPBYTE pbDstStream;
|
||||
DWORD cbSrcStream = 0;
|
||||
LPBYTE pbSrcStream = NULL;
|
||||
ACMSTREAMHEADER ash;
|
||||
DWORD offset = 0;
|
||||
BOOL stop = FALSE;
|
||||
BOOL unprepare_header = FALSE;
|
||||
MMRESULT res;
|
||||
HRESULT hr;
|
||||
LONGLONG tStart = -1, tStop = -1, tMed;
|
||||
|
||||
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
|
||||
if (FAILED(hr))
|
||||
|
@ -80,6 +71,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
return hr;
|
||||
}
|
||||
|
||||
IMediaSample_GetTime(pSample, &tStart, &tStop);
|
||||
cbSrcStream = IMediaSample_GetActualDataLength(pSample);
|
||||
|
||||
TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, (long)cbSrcStream);
|
||||
|
@ -90,21 +82,11 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
return hr;
|
||||
}
|
||||
|
||||
while(hr == S_OK && !stop)
|
||||
ash.pbSrc = pbSrcStream;
|
||||
ash.cbSrcLength = cbSrcStream;
|
||||
|
||||
while(hr == S_OK && ash.cbSrcLength)
|
||||
{
|
||||
DWORD rem_buf = This->max_size - This->current_size;
|
||||
DWORD rem_smp = cbSrcStream - offset;
|
||||
DWORD copy_size = min(rem_buf, rem_smp);
|
||||
|
||||
memcpy(This->buffer + This->current_size, pbSrcStream + offset, copy_size);
|
||||
This->current_size += copy_size;
|
||||
offset += copy_size;
|
||||
|
||||
if (offset >= cbSrcStream)
|
||||
stop = TRUE;
|
||||
if (This->current_size < This->max_size)
|
||||
break;
|
||||
|
||||
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
|
||||
if (FAILED(hr)) {
|
||||
ERR("Unable to get delivery buffer (%x)\n", hr);
|
||||
|
@ -124,8 +106,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
ash.cbStruct = sizeof(ash);
|
||||
ash.fdwStatus = 0;
|
||||
ash.dwUser = 0;
|
||||
ash.pbSrc = This->buffer;
|
||||
ash.cbSrcLength = This->current_size;
|
||||
ash.pbDst = pbDstStream;
|
||||
ash.cbDstLength = cbDstStream;
|
||||
|
||||
|
@ -133,7 +113,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
ERR("Cannot prepare header %d\n", res);
|
||||
goto error;
|
||||
}
|
||||
|
||||
unprepare_header = TRUE;
|
||||
|
||||
if ((res = acmStreamConvert(This->has, &ash, This->reinit_codec ? ACM_STREAMCONVERTF_START : 0))) {
|
||||
|
@ -143,17 +122,31 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
|
|||
}
|
||||
This->reinit_codec = FALSE;
|
||||
|
||||
TRACE("used in %u, used out %u\n", ash.cbSrcLengthUsed, ash.cbDstLengthUsed);
|
||||
TRACE("used in %u/%u, used out %u/%u\n", ash.cbSrcLengthUsed, ash.cbSrcLength, ash.cbDstLengthUsed, ash.cbDstLength);
|
||||
|
||||
hr = IMediaSample_SetActualDataLength(pOutSample, ash.cbDstLengthUsed);
|
||||
assert(hr == S_OK);
|
||||
|
||||
if (ash.cbSrcLengthUsed < ash.cbSrcLength) {
|
||||
This->current_size = ash.cbSrcLength - ash.cbSrcLengthUsed;
|
||||
memmove(This->buffer, This->buffer + ash.cbSrcLengthUsed, This->current_size);
|
||||
}
|
||||
else
|
||||
This->current_size = 0;
|
||||
assert(ash.cbSrcLengthUsed);
|
||||
TRACE("Sample start time: %lld.%03lld\n", (tStart/10000000), (tStart/10000)%1000);
|
||||
if (ash.cbSrcLengthUsed == cbSrcStream)
|
||||
{
|
||||
IMediaSample_SetTime(pOutSample, &tStart, &tStop);
|
||||
tStart = tStop;
|
||||
}
|
||||
else if (tStop != tStart)
|
||||
{
|
||||
tMed = tStop - tStart;
|
||||
tMed = tStart + tMed * ash.cbSrcLengthUsed / cbSrcStream;
|
||||
IMediaSample_SetTime(pOutSample, &tStart, &tMed);
|
||||
tStart = tMed;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("No valid timestamp found\n");
|
||||
IMediaSample_SetTime(pOutSample, NULL, NULL);
|
||||
}
|
||||
TRACE("Sample stop time: %lld.%03lld\n", (tStart/10000000), (tStart/10000)%1000);
|
||||
|
||||
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
|
||||
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
|
||||
|
@ -166,6 +159,8 @@ error:
|
|||
if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0)))
|
||||
ERR("Cannot unprepare header %d\n", res);
|
||||
unprepare_header = FALSE;
|
||||
ash.pbSrc += ash.cbSrcLengthUsed;
|
||||
ash.cbSrcLength -= ash.cbSrcLengthUsed;
|
||||
|
||||
if (pOutSample)
|
||||
IMediaSample_Release(pOutSample);
|
||||
|
@ -210,16 +205,8 @@ static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, co
|
|||
{
|
||||
This->has = drv;
|
||||
|
||||
if ((res = acmStreamSize(drv, OUTPUT_BUFFER_SIZE, &This->max_size, ACM_STREAMSIZEF_DESTINATION))) {
|
||||
ERR("Cannot retrieve input buffer size error %d!\n", res);
|
||||
This->max_size = INPUT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
TRACE("input buffer size %d\n", This->max_size);
|
||||
|
||||
/* Update buffer size of media samples in output */
|
||||
((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = OUTPUT_BUFFER_SIZE;
|
||||
|
||||
((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pWfOut->nAvgBytesPerSec / 2;
|
||||
TRACE("Connection accepted\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue