static HRESULT WINAPI Gstreamer_transform_ProcessData(TransformFilter *iface, IMediaSample *sample) { GstTfImpl *This = (GstTfImpl*)iface; REFERENCE_TIME tStart, tStop; BYTE *data; GstBuffer *buf; HRESULT hr; DWORD bufsize; int ret; TRACE("%p, %p\n", This, sample); mark_wine_thread(); EnterCriticalSection(&This->tf.csReceive); IMediaSample_GetPointer(sample, &data); IMediaSample_AddRef(sample); bufsize = IMediaSample_GetActualDataLength(sample); buf = gst_buffer_new_wrapped_full(0, data, bufsize, 0, bufsize, sample, release_sample_wrapper); if (!buf) { IMediaSample_Release(sample); LeaveCriticalSection(&This->tf.csReceive); return S_OK; } IMediaSample_AddRef(sample); gst_mini_object_set_qdata(GST_MINI_OBJECT(buf), g_quark_from_static_string(media_quark_string), sample, release_sample_wrapper); buf->duration = buf->pts = -1; hr = IMediaSample_GetTime(sample, &tStart, &tStop); if (SUCCEEDED(hr)) { buf->pts = tStart * 100; if (hr == S_OK) buf->duration = (tStop - tStart)*100; } if (IMediaSample_GetMediaTime(sample, &tStart, &tStop) == S_OK) { buf->offset = tStart * 100; buf->offset_end = tStop * 100; } if (IMediaSample_IsDiscontinuity(sample) == S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_DISCONT); if (IMediaSample_IsPreroll(sample) == S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_LIVE); if (IMediaSample_IsSyncPoint(sample) != S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT); LeaveCriticalSection(&This->tf.csReceive); ret = gst_pad_push(This->my_src, buf); if (ret) WARN("Sending returned: %i\n", ret); if (ret == GST_FLOW_FLUSHING) return VFW_E_WRONG_STATE; return S_OK; }
static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSample ** pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr = S_OK; /* NOTE: The pStartTime and pEndTime parameters are not applied to the sample. * The allocator might use these values to determine which buffer it retrieves */ TRACE("(%p)->(%p, %p, %p, %x)\n", This, pSample, pStartTime, pEndTime, dwFlags); *pSample = NULL; EnterCriticalSection(This->pCritSect); if (!This->bCommitted || This->bDecommitQueued) { WARN("Not committed\n"); hr = VFW_E_NOT_COMMITTED; } else ++This->lWaiting; LeaveCriticalSection(This->pCritSect); if (FAILED(hr)) return hr; if (WaitForSingleObject(This->hSemWaiting, (dwFlags & AM_GBF_NOWAIT) ? 0 : INFINITE) != WAIT_OBJECT_0) { EnterCriticalSection(This->pCritSect); --This->lWaiting; LeaveCriticalSection(This->pCritSect); WARN("Timed out\n"); return VFW_E_TIMEOUT; } EnterCriticalSection(This->pCritSect); { --This->lWaiting; if (!This->bCommitted) hr = VFW_E_NOT_COMMITTED; else if (This->bDecommitQueued) hr = VFW_E_TIMEOUT; else { StdMediaSample2 *ms; struct list * free = list_head(&This->free_list); list_remove(free); list_add_head(&This->used_list, free); ms = LIST_ENTRY(free, StdMediaSample2, listentry); assert(ms->ref == 0); *pSample = (IMediaSample *)&ms->IMediaSample2_iface; IMediaSample_AddRef(*pSample); } } LeaveCriticalSection(This->pCritSect); if (hr != S_OK) WARN("%08x\n", hr); return hr; }
/* Helper that buffers data and/or calls installed sample callbacks */ static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample) { double time = 0.0; REFERENCE_TIME tStart, tEnd; if (This->bufferLen >= 0) { BYTE *data = 0; LONG size = IMediaSample_GetActualDataLength(sample); if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) { if (!data) size = 0; EnterCriticalSection(&This->filter.csFilter); if (This->bufferLen != size) { if (This->bufferData) CoTaskMemFree(This->bufferData); This->bufferData = size ? CoTaskMemAlloc(size) : NULL; This->bufferLen = size; } if (size) CopyMemory(This->bufferData, data, size); LeaveCriticalSection(&This->filter.csFilter); } } if (!This->grabberIface) return; if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd))) time = 1e-7 * tStart; switch (This->grabberMethod) { case 0: { ULONG ref = IMediaSample_AddRef(sample); ISampleGrabberCB_SampleCB(This->grabberIface, time, sample); ref = IMediaSample_Release(sample) + 1 - ref; if (ref) { ERR("(%p) Callback referenced sample %p by %u\n", This, sample, ref); /* ugly as hell but some apps are sooo buggy */ while (ref--) IMediaSample_Release(sample); } } break; case 1: { BYTE *data = 0; LONG size = IMediaSample_GetActualDataLength(sample); if (size && SUCCEEDED(IMediaSample_GetPointer(sample, &data)) && data) ISampleGrabberCB_BufferCB(This->grabberIface, time, data, size); } break; case -1: break; default: FIXME("unsupported method %d\n", This->grabberMethod); /* do not bother us again */ This->grabberMethod = -1; } }
static HRESULT WINAPI Gstreamer_transform_ProcessData(TransformFilter *iface, IMediaSample *sample) { GstTfImpl *This = (GstTfImpl*)iface; REFERENCE_TIME tStart, tStop; BYTE *data; GstBuffer *buf; HRESULT hr; int ret; TRACE("Reading %p\n", sample); EnterCriticalSection(&This->tf.filter.csFilter); IMediaSample_GetPointer(sample, &data); buf = gst_app_buffer_new(data, IMediaSample_GetActualDataLength(sample), release_sample, sample); if (!buf) { LeaveCriticalSection(&This->tf.filter.csFilter); return S_OK; } gst_buffer_set_caps(buf, gst_pad_get_caps_reffed(This->my_src)); IMediaSample_AddRef(sample); buf->duration = buf->timestamp = -1; hr = IMediaSample_GetTime(sample, &tStart, &tStop); if (SUCCEEDED(hr)) { buf->timestamp = tStart * 100; if (hr == S_OK) buf->duration = (tStop - tStart)*100; } if (IMediaSample_GetMediaTime(sample, &tStart, &tStop) == S_OK) { buf->offset = tStart * 100; buf->offset_end = tStop * 100; } if (IMediaSample_IsDiscontinuity(sample) == S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_DISCONT); if (IMediaSample_IsPreroll(sample) == S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_PREROLL); if (IMediaSample_IsSyncPoint(sample) != S_OK) GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT); LeaveCriticalSection(&This->tf.filter.csFilter); ret = gst_pad_push(This->my_src, buf); if (ret) WARN("Sending returned: %i\n", ret); if (ret == GST_FLOW_ERROR) return E_FAIL; if (ret == GST_FLOW_WRONG_STATE) return VFW_E_WRONG_STATE; if (ret == GST_FLOW_RESEND) return S_FALSE; return S_OK; }
static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSample ** pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags) { BaseMemAllocator *This = (BaseMemAllocator *)iface; HRESULT hr = S_OK; /* NOTE: The pStartTime and pEndTime parameters are not applied to the sample. * The allocator might use these values to determine which buffer it retrieves */ TRACE("(%p)->(%p, %p, %p, %lx)\n", This, pSample, pStartTime, pEndTime, dwFlags); *pSample = NULL; if (!This->bCommitted) return VFW_E_NOT_COMMITTED; This->lWaiting++; if (WaitForSingleObject(This->hSemWaiting, (dwFlags & AM_GBF_NOWAIT) ? 0 : INFINITE) != WAIT_OBJECT_0) { This->lWaiting--; return VFW_E_TIMEOUT; } This->lWaiting--; EnterCriticalSection(&This->csState); { if (!This->bCommitted) hr = VFW_E_NOT_COMMITTED; else if (This->bDecommitQueued) hr = VFW_E_TIMEOUT; else { struct list * free = list_head(&This->free_list); list_remove(free); list_add_head(&This->used_list, free); *pSample = (IMediaSample *)LIST_ENTRY(free, StdMediaSample2, listentry); assert(((StdMediaSample2 *)*pSample)->ref == 0); IMediaSample_AddRef(*pSample); } } LeaveCriticalSection(&This->csState); return hr; }
static HRESULT IMemAllocator_LockUnusedBuffer(CMemoryAllocator* This,IMediaSample** ppSample) { HRESULT hr = E_FAIL; LONG i; TRACE("(%p) try to enter critical section\n",This); EnterCriticalSection( &This->csMem ); TRACE("(%p) enter critical section\n",This); if ( This->pData == NULL || This->ppSamples == NULL || This->prop.cBuffers <= 0 ) { hr = VFW_E_NOT_COMMITTED; goto end; } for ( i = 0; i < This->prop.cBuffers; i++ ) { if ( This->ppSamples[i] == NULL ) { hr = VFW_E_NOT_COMMITTED; goto end; } if ( This->ppSamples[i]->ref == 0 ) { *ppSample = (IMediaSample*)(This->ppSamples[i]); IMediaSample_AddRef( *ppSample ); hr = NOERROR; goto end; } } hr = VFW_E_TIMEOUT; end: LeaveCriticalSection( &This->csMem ); TRACE("(%p) leave critical section\n",This); return hr; }
HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSample) { HRESULT hr = S_OK; REFERENCE_TIME start, stop; AM_MEDIA_TYPE *pmt; TRACE("(%p)->%p\n", This, pSample); if (This->pInputPin->end_of_stream || This->pInputPin->flushing) return S_FALSE; if (This->filter.state == State_Stopped) return VFW_E_WRONG_STATE; if (IMediaSample_GetMediaType(pSample, &pmt) == S_OK) { if (FAILED(This->pFuncsTable->pfnCheckMediaType(This, pmt))) { return VFW_E_TYPE_NOT_ACCEPTED; } } This->pMediaSample = pSample; IMediaSample_AddRef(pSample); if (This->pFuncsTable->pfnPrepareReceive) hr = This->pFuncsTable->pfnPrepareReceive(This, pSample); if (FAILED(hr)) { if (hr == VFW_E_SAMPLE_REJECTED) return S_OK; else return hr; } if (This->pFuncsTable->pfnPrepareRender) This->pFuncsTable->pfnPrepareRender(This); EnterCriticalSection(&This->csRenderLock); if ( This->filter.state == State_Paused ) { if (This->pFuncsTable->pfnOnReceiveFirstSample) This->pFuncsTable->pfnOnReceiveFirstSample(This, pSample); SetEvent(This->evComplete); } /* Wait for render Time */ if (SUCCEEDED(IMediaSample_GetMediaTime(pSample, &start, &stop))) { hr = S_FALSE; RendererPosPassThru_RegisterMediaTime(This->pPosition, start); if (This->pFuncsTable->pfnShouldDrawSampleNow) hr = This->pFuncsTable->pfnShouldDrawSampleNow(This, pSample, &start, &stop); if (hr == S_OK) ;/* Do not wait: drop through */ else if (hr == S_FALSE) { if (This->pFuncsTable->pfnOnWaitStart) This->pFuncsTable->pfnOnWaitStart(This); hr = QualityControlRender_WaitFor(This->qcimpl, pSample, This->RenderEvent); if (This->pFuncsTable->pfnOnWaitEnd) This->pFuncsTable->pfnOnWaitEnd(This); } else { LeaveCriticalSection(&This->csRenderLock); /* Drop Sample */ return S_OK; } } if (SUCCEEDED(hr)) { QualityControlRender_BeginRender(This->qcimpl); hr = This->pFuncsTable->pfnDoRenderSample(This, pSample); QualityControlRender_EndRender(This->qcimpl); } QualityControlRender_DoQOS(This->qcimpl); BaseRendererImpl_ClearPendingSample(This); LeaveCriticalSection(&This->csRenderLock); return hr; }