Commit f8bb8384 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Alexandre Julliard

quartz: Make acmwrapper code aware of time, and get rid of its internal buffer.

parent c423511d
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment