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 @@ ...@@ -41,19 +41,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz); WINE_DEFAULT_DEBUG_CHANNEL(quartz);
/* FIXME: Improve buffers management */
#define OUTPUT_BUFFER_SIZE 15000
#define INPUT_BUFFER_SIZE 4096
typedef struct ACMWrapperImpl typedef struct ACMWrapperImpl
{ {
TransformFilterImpl tf; TransformFilterImpl tf;
HACMSTREAM has; HACMSTREAM has;
LPWAVEFORMATEX pWfIn; LPWAVEFORMATEX pWfIn;
LPWAVEFORMATEX pWfOut; LPWAVEFORMATEX pWfOut;
BYTE buffer[INPUT_BUFFER_SIZE];
DWORD max_size;
DWORD current_size;
BOOL reinit_codec; /* FIXME: Should use sync points instead */ BOOL reinit_codec; /* FIXME: Should use sync points instead */
} ACMWrapperImpl; } ACMWrapperImpl;
...@@ -62,16 +55,14 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -62,16 +55,14 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter;
AM_MEDIA_TYPE amt; AM_MEDIA_TYPE amt;
IMediaSample* pOutSample = NULL; IMediaSample* pOutSample = NULL;
DWORD cbDstStream; DWORD cbDstStream, cbSrcStream;
LPBYTE pbDstStream; LPBYTE pbDstStream;
DWORD cbSrcStream = 0;
LPBYTE pbSrcStream = NULL; LPBYTE pbSrcStream = NULL;
ACMSTREAMHEADER ash; ACMSTREAMHEADER ash;
DWORD offset = 0;
BOOL stop = FALSE;
BOOL unprepare_header = FALSE; BOOL unprepare_header = FALSE;
MMRESULT res; MMRESULT res;
HRESULT hr; HRESULT hr;
LONGLONG tStart = -1, tStop = -1, tMed;
hr = IMediaSample_GetPointer(pSample, &pbSrcStream); hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr)) if (FAILED(hr))
...@@ -80,6 +71,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -80,6 +71,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
return hr; return hr;
} }
IMediaSample_GetTime(pSample, &tStart, &tStop);
cbSrcStream = IMediaSample_GetActualDataLength(pSample); cbSrcStream = IMediaSample_GetActualDataLength(pSample);
TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, (long)cbSrcStream); TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, (long)cbSrcStream);
...@@ -90,21 +82,11 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -90,21 +82,11 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
return hr; return hr;
} }
while(hr == S_OK && !stop) ash.pbSrc = pbSrcStream;
{ ash.cbSrcLength = cbSrcStream;
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;
while(hr == S_OK && ash.cbSrcLength)
{
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
ERR("Unable to get delivery buffer (%x)\n", hr); ERR("Unable to get delivery buffer (%x)\n", hr);
...@@ -124,8 +106,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -124,8 +106,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
ash.cbStruct = sizeof(ash); ash.cbStruct = sizeof(ash);
ash.fdwStatus = 0; ash.fdwStatus = 0;
ash.dwUser = 0; ash.dwUser = 0;
ash.pbSrc = This->buffer;
ash.cbSrcLength = This->current_size;
ash.pbDst = pbDstStream; ash.pbDst = pbDstStream;
ash.cbDstLength = cbDstStream; ash.cbDstLength = cbDstStream;
...@@ -133,7 +113,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -133,7 +113,6 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
ERR("Cannot prepare header %d\n", res); ERR("Cannot prepare header %d\n", res);
goto error; goto error;
} }
unprepare_header = TRUE; unprepare_header = TRUE;
if ((res = acmStreamConvert(This->has, &ash, This->reinit_codec ? ACM_STREAMCONVERTF_START : 0))) { if ((res = acmStreamConvert(This->has, &ash, This->reinit_codec ? ACM_STREAMCONVERTF_START : 0))) {
...@@ -143,17 +122,31 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte ...@@ -143,17 +122,31 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
} }
This->reinit_codec = FALSE; 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); hr = IMediaSample_SetActualDataLength(pOutSample, ash.cbDstLengthUsed);
assert(hr == S_OK); assert(hr == S_OK);
if (ash.cbSrcLengthUsed < ash.cbSrcLength) { assert(ash.cbSrcLengthUsed);
This->current_size = ash.cbSrcLength - ash.cbSrcLengthUsed; TRACE("Sample start time: %lld.%03lld\n", (tStart/10000000), (tStart/10000)%1000);
memmove(This->buffer, This->buffer + ash.cbSrcLengthUsed, This->current_size); 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 else
This->current_size = 0; {
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); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
...@@ -166,6 +159,8 @@ error: ...@@ -166,6 +159,8 @@ error:
if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0))) if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0)))
ERR("Cannot unprepare header %d\n", res); ERR("Cannot unprepare header %d\n", res);
unprepare_header = FALSE; unprepare_header = FALSE;
ash.pbSrc += ash.cbSrcLengthUsed;
ash.cbSrcLength -= ash.cbSrcLengthUsed;
if (pOutSample) if (pOutSample)
IMediaSample_Release(pOutSample); IMediaSample_Release(pOutSample);
...@@ -210,16 +205,8 @@ static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, co ...@@ -210,16 +205,8 @@ static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, co
{ {
This->has = drv; 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 */ /* 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"); TRACE("Connection accepted\n");
return S_OK; 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