From: Paul Gofman pgofman@codeweavers.com
--- dlls/winegstreamer/h264_decoder.c | 79 +++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 9 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index aa776326e19..c32e715d749 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -63,6 +63,7 @@ struct h264_decoder struct wg_sample_queue *wg_sample_queue;
IMFDXGIDeviceManager *dxgi_manager; + IMFVideoSampleAllocatorEx *allocator; };
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface) @@ -234,6 +235,15 @@ static ULONG WINAPI transform_AddRef(IMFTransform *iface) return refcount; }
+static void free_allocator(struct h264_decoder *decoder) +{ + if (decoder->allocator) + { + IMFVideoSampleAllocatorEx_Release(decoder->allocator); + decoder->allocator = NULL; + } +} + static ULONG WINAPI transform_Release(IMFTransform *iface) { struct h264_decoder *decoder = impl_from_IMFTransform(iface); @@ -255,7 +265,7 @@ static ULONG WINAPI transform_Release(IMFTransform *iface) IMFAttributes_Release(decoder->attributes); if (decoder->dxgi_manager) IMFDXGIDeviceManager_Release(decoder->dxgi_manager); - + free_allocator(decoder); wg_sample_queue_destroy(decoder->wg_sample_queue); free(decoder); } @@ -526,6 +536,9 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF decoder->output_type = NULL; }
+ if (SUCCEEDED(hr)) + free_allocator(decoder); + return hr; }
@@ -594,8 +607,6 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_ IMFDXGIDeviceManager *dxgi_manager = NULL; IUnknown *unk = (IUnknown *)param;
- FIXME("MFT_MESSAGE_SET_D3D_MANAGER.\n"); - if (unk && FAILED(hr = IUnknown_QueryInterface(unk, &IID_IMFDXGIDeviceManager, (void **)&dxgi_manager))) { FIXME("Query IMFDXGIDeviceManager failed.\n"); @@ -603,7 +614,11 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_ } if (decoder->dxgi_manager) IMFDXGIDeviceManager_Release(decoder->dxgi_manager); - decoder->dxgi_manager = dxgi_manager; + free_allocator(decoder); + if ((decoder->dxgi_manager = dxgi_manager)) + decoder->output_info.dwFlags |= MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + else + decoder->output_info.dwFlags &= ~MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; }
FIXME("Ignoring message %#x.\n", message); @@ -622,12 +637,33 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS return wg_transform_push_mf(decoder->wg_transform, sample, decoder->wg_sample_queue); }
+static HRESULT initialize_allocator(struct h264_decoder *decoder) +{ + IMFAttributes *attributes = NULL; + HRESULT hr; + + if (FAILED(hr = MFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&decoder->allocator))) + return hr; + if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(decoder->allocator, (IUnknown *)decoder->dxgi_manager))) + goto done; + if (FAILED(hr = MFCreateAttributes(&attributes, 0))) + goto done; + hr = IMFVideoSampleAllocatorEx_InitializeSampleAllocatorEx(decoder->allocator, 10, 10, attributes, decoder->output_type); +done: + if (attributes) + IMFAttributes_Release(attributes); + if (FAILED(hr)) + free_allocator(decoder); + return hr; +} + static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct h264_decoder *decoder = impl_from_IMFTransform(iface); struct wg_format wg_format; UINT32 sample_size; + IMFSample *sample; UINT64 frame_rate; GUID subtype; HRESULT hr; @@ -641,16 +677,32 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_TRANSFORM_TYPE_NOT_SET;
*status = samples->dwStatus = 0; - if (!samples->pSample) - return E_INVALIDARG; + if (decoder->dxgi_manager) + { + if (!decoder->allocator && FAILED(hr = initialize_allocator(decoder))) + { + ERR("Failed to initialize allocator, hr %#lx.\n", hr); + return hr; + } + if (FAILED(hr = IMFVideoSampleAllocatorEx_AllocateSample(decoder->allocator, &sample))) + { + ERR("Failed to allocate sample, hr %#lx.\n", hr); + return hr; + } + } + else + { + if (!(sample = samples->pSample)) + return E_INVALIDARG; + }
if (FAILED(hr = IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &subtype))) - return hr; + goto done; if (FAILED(hr = MFCalculateImageSize(&subtype, decoder->wg_format.u.video.width, decoder->wg_format.u.video.height, &sample_size))) - return hr; + goto done;
- if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, + if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, sample_size, &wg_format, &samples->dwStatus))) wg_sample_queue_flush(decoder->wg_sample_queue, false);
@@ -671,6 +723,15 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; }
+done: + if (decoder->dxgi_manager) + { + if (hr == S_OK) + samples->pSample = sample; + else + IMFSample_Release(sample); + } + return hr; }