From e8401bf8047aa31c802adb4e66a188b63079b78e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 21 Mar 2008 14:55:03 -0700 Subject: [PATCH] quartz: Make acmwrapper code aware of time, and get rid of its internal buffer --- dlls/quartz/acmwrapper.c | 75 +++++++++++++++++++--------------------------- 1 files changed, 31 insertions(+), 44 deletions(-) diff --git a/dlls/quartz/acmwrapper.c b/dlls/quartz/acmwrapper.c index de90b81..4d5fbc9 100644 --- a/dlls/quartz/acmwrapper.c +++ b/dlls/quartz/acmwrapper.c @@ -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; } -- 1.5.4.1