static DWORD WINAPI ReadThread(LPVOID lParam) { Capture * capBox = lParam; HRESULT hr; IMediaSample *pSample = NULL; unsigned long framecount = 0; unsigned char *pTarget, *pInput, *pOutput; hr = V4l_Prepare(capBox); if (FAILED(hr)) goto fail; pOutput = CoTaskMemAlloc(capBox->width * capBox->height * capBox->bitDepth / 8); capBox->curframe = 0; do { V4l_FreeFrame(capBox); } while (capBox->curframe != 0); while (1) { EnterCriticalSection(&capBox->CritSect); if (capBox->stopped) break; hr = OutputPin_GetDeliveryBuffer((OutputPin *)capBox->pOut, &pSample, NULL, NULL, 0); if (SUCCEEDED(hr)) { int len; if (!capBox->swresize) len = capBox->height * capBox->width * capBox->bitDepth / 8; else len = capBox->outputheight * capBox->outputwidth * capBox->bitDepth / 8; IMediaSample_SetActualDataLength(pSample, len); len = IMediaSample_GetActualDataLength(pSample); TRACE("Data length: %d KB\n", len / 1024); IMediaSample_GetPointer(pSample, &pTarget); /* FIXME: Check return values.. */ V4l_GetFrame(capBox, &pInput); capBox->renderer(capBox, pOutput, pInput); Resize(capBox, pTarget, pOutput); hr = OutputPin_SendSample((OutputPin *)capBox->pOut, pSample); TRACE("%p -> Frame %lu: %x\n", capBox, ++framecount, hr); IMediaSample_Release(pSample); V4l_FreeFrame(capBox); } LeaveCriticalSection(&capBox->CritSect); if (FAILED(hr) && hr != VFW_E_NOT_CONNECTED) { ERR("Received error: %x\n", hr); goto cfail; } } LeaveCriticalSection(&capBox->CritSect); CoTaskMemFree(pOutput); return 0; cfail: CoTaskMemFree(pOutput); V4l_Unprepare(capBox); LeaveCriticalSection(&capBox->CritSect); fail: capBox->thread = 0; capBox->stopped = 1; FIXME("Stop IFilterGraph\n"); return 0; }
static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample) { ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; IMediaSample* pOutSample = NULL; DWORD cbDstStream, cbSrcStream; LPBYTE pbDstStream; LPBYTE pbSrcStream = NULL; ACMSTREAMHEADER ash; BOOL unprepare_header = FALSE, preroll; MMRESULT res; HRESULT hr; LONGLONG tStart = -1, tStop = -1, tMed; EnterCriticalSection(&This->tf.csFilter); if (This->tf.state == State_Stopped) { LeaveCriticalSection(&This->tf.csFilter); return VFW_E_WRONG_STATE; } if (pin->end_of_stream || pin->flushing) { LeaveCriticalSection(&This->tf.csFilter); return S_FALSE; } hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); LeaveCriticalSection(&This->tf.csFilter); return hr; } preroll = (IMediaSample_IsPreroll(pSample) == S_OK); IMediaSample_GetTime(pSample, &tStart, &tStop); cbSrcStream = IMediaSample_GetActualDataLength(pSample); /* Prevent discontinuities when codecs 'absorb' data but not give anything back in return */ if (IMediaSample_IsDiscontinuity(pSample) == S_OK) { This->lasttime_real = tStart; This->lasttime_sent = tStart; } else if (This->lasttime_real == tStart) tStart = This->lasttime_sent; else WARN("Discontinuity\n"); tMed = tStart; TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); LeaveCriticalSection(&This->tf.csFilter); return hr; } ash.pbSrc = pbSrcStream; ash.cbSrcLength = cbSrcStream; while(hr == S_OK && ash.cbSrcLength) { hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); LeaveCriticalSection(&This->tf.csFilter); return hr; } IMediaSample_SetPreroll(pOutSample, preroll); hr = IMediaSample_SetActualDataLength(pOutSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%x)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pOutSample); ash.cbStruct = sizeof(ash); ash.fdwStatus = 0; ash.dwUser = 0; ash.pbDst = pbDstStream; ash.cbDstLength = cbDstStream; if ((res = acmStreamPrepareHeader(This->has, &ash, 0))) { ERR("Cannot prepare header %d\n", res); goto error; } unprepare_header = TRUE; if (IMediaSample_IsDiscontinuity(pSample) == S_OK) { res = acmStreamConvert(This->has, &ash, ACM_STREAMCONVERTF_START); IMediaSample_SetDiscontinuity(pOutSample, TRUE); /* One sample could be converted to multiple packets */ IMediaSample_SetDiscontinuity(pSample, FALSE); } else { res = acmStreamConvert(This->has, &ash, 0); IMediaSample_SetDiscontinuity(pOutSample, FALSE); } if (res) { if(res != MMSYSERR_MOREDATA) ERR("Cannot convert data header %d\n", res); goto error; } 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); /* Bug in acm codecs? It apparantly uses the input, but doesn't necessarily output immediately kl*/ if (!ash.cbSrcLengthUsed) { WARN("Sample was skipped? Outputted: %u\n", ash.cbDstLengthUsed); ash.cbSrcLength = 0; goto error; } TRACE("Sample start time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); if (ash.cbSrcLengthUsed == cbSrcStream) { IMediaSample_SetTime(pOutSample, &tStart, &tStop); tStart = tMed = 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: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); LeaveCriticalSection(&This->tf.csFilter); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); EnterCriticalSection(&This->tf.csFilter); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (FAILED(hr)) ERR("Error sending sample (%x)\n", hr); goto error; } 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); pOutSample = NULL; } This->lasttime_real = tStop; This->lasttime_sent = tMed; LeaveCriticalSection(&This->tf.csFilter); return hr; }
static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) { AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; HRESULT hr; DWORD res; IMediaSample* pOutSample = NULL; DWORD cbDstStream; LPBYTE pbDstStream; DWORD cbSrcStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; EnterCriticalSection(&This->tf.csFilter); if (This->tf.state == State_Stopped) { LeaveCriticalSection(&This->tf.csFilter); return VFW_E_WRONG_STATE; } if (pin->end_of_stream || pin->flushing) { LeaveCriticalSection(&This->tf.csFilter); return S_FALSE; } hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); goto error; } cbSrcStream = IMediaSample_GetActualDataLength(pSample); TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); goto error; } /* Update input size to match sample size */ This->pBihIn->biSizeImage = cbSrcStream; hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); goto error; } hr = IMediaSample_SetActualDataLength(pOutSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%x)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pOutSample); if (cbDstStream < This->pBihOut->biSizeImage) { ERR("Sample size is too small %d < %d\n", cbDstStream, This->pBihOut->biSizeImage); hr = E_FAIL; goto error; } res = ICDecompress(This->hvid, 0, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); if (res != ICERR_OK) ERR("Error occurred during the decompression (%x)\n", res); IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage); IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK)); if (IMediaSample_GetTime(pSample, &tStart, &tStop) == S_OK) IMediaSample_SetTime(pOutSample, &tStart, &tStop); else IMediaSample_SetTime(pOutSample, NULL, NULL); LeaveCriticalSection(&This->tf.csFilter); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) ERR("Error sending sample (%x)\n", hr); IMediaSample_Release(pOutSample); return hr; error: if (pOutSample) IMediaSample_Release(pOutSample); LeaveCriticalSection(&This->tf.csFilter); return hr; }
static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) { ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; AM_MEDIA_TYPE amt; HRESULT hr; IMediaSample* pSample = NULL; DWORD cbDstStream; LPBYTE pbDstStream; ACMSTREAMHEADER ash; DWORD offset = 0; BOOL stop = FALSE; BOOL unprepare_header = FALSE; MMRESULT res; TRACE("(%p)->(%p,%ld)\n", This, data, size); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); goto error; } while(!stop) { DWORD rem_buf = This->max_size - This->current_size; DWORD rem_smp = size - offset; DWORD copy_size = min(rem_buf, rem_smp); memcpy(This->buffer + This->current_size, data + offset, copy_size); This->current_size += copy_size; offset += copy_size; if (offset == size) stop = TRUE; if (This->current_size < This->max_size) break; hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%lx)\n", hr); goto error; } hr = IMediaSample_SetActualDataLength(pSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%lx)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pSample); 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; if ((res = acmStreamPrepareHeader(This->has, &ash, 0))) { 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))) { ERR("Cannot convert data header %d\n", res); goto error; } This->reinit_codec = FALSE; TRACE("used in %lu, used out %lu\n", ash.cbSrcLengthUsed, ash.cbDstLengthUsed); hr = IMediaSample_SetActualDataLength(pSample, 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; hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pSample); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { ERR("Error sending sample (%lx)\n", hr); goto error; } error: if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0))) ERR("Cannot unprepare header %d\n", res); if (pSample) IMediaSample_Release(pSample); } return hr; }