[PATCH 2/2] winegstreamer: Add helper for GstBuffer <-> IMFSample conversion.
Zebediah Figura
zfigura at codeweavers.com
Tue Mar 24 15:37:37 CDT 2020
On 3/24/20 2:39 PM, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
> ---
> dlls/winegstreamer/gst_private.h | 2 +
> dlls/winegstreamer/mfplat.c | 162 +++++++++++++++++++++++++++++++
> 2 files changed, 164 insertions(+)
>
> diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
> index a6c3fd3784..13ba467a9e 100644
> --- a/dlls/winegstreamer/gst_private.h
> +++ b/dlls/winegstreamer/gst_private.h
> @@ -57,5 +57,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
>
> IMFMediaType* media_type_from_caps(GstCaps *caps);
> GstCaps *caps_from_media_type(IMFMediaType *type);
> +IMFSample* mf_sample_from_gst_buffer(GstBuffer *in);
> +GstBuffer* gst_buffer_from_mf_sample(IMFSample *in);
>
> #endif /* __GST_PRIVATE_INCLUDED__ */
> diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
> index a6f4fbc2ec..e66bc3ffe6 100644
> --- a/dlls/winegstreamer/mfplat.c
> +++ b/dlls/winegstreamer/mfplat.c
> @@ -964,3 +964,165 @@ GstCaps *caps_from_media_type(IMFMediaType *type)
> ERR("Unrecognized major type %s\n", debugstr_guid(&major_type));
> return NULL;
> }
> +
> +/* IMFSample = GstBuffer
> + IMFBuffer = GstMemory */
IMFBuffer isn't an interface.
I'm not sure that this comment is especially useful anyway, though.
> +
> +/* TODO: Future optimization could be to create a custom
> + IMFMediaBuffer wrapper around GstMemory, and to utilize
> + gst_memory_new_wrapped on IMFMediaBuffer data */
This seems like a better idea than what's done below; any particular
reason why not?
> +
> +IMFSample* mf_sample_from_gst_buffer(GstBuffer *gst_buffer)
> +{
> + IMFSample *out = NULL;
> + LONGLONG duration, time;
> + int buffer_count;
> + HRESULT hr;
> +
> + if (FAILED(hr = MFCreateSample(&out)))
> + goto fail;
> +
> + duration = GST_BUFFER_DURATION(gst_buffer);
> + time = GST_BUFFER_PTS(gst_buffer);
> +
> + if (FAILED(IMFSample_SetSampleDuration(out, duration / 100)))
> + goto fail;
> +
> + if (FAILED(IMFSample_SetSampleTime(out, time / 100)))
> + goto fail;
> +
> + buffer_count = gst_buffer_n_memory(gst_buffer);
> +
> + for (unsigned int i = 0; i < buffer_count; i++)
> + {
> + GstMemory *memory = gst_buffer_get_memory(gst_buffer, i);
> + IMFMediaBuffer *mf_buffer = NULL;
> + GstMapInfo map_info;
> + BYTE *buf_data;
> +
> + if (!memory)
> + {
> + hr = ERROR_INTERNAL_ERROR;
That's not an HRESULT.
> + goto loop_done;
> + }
> +
> + if (!(gst_memory_map(memory, &map_info, GST_MAP_READ)))
> + {
> + hr = ERROR_INTERNAL_ERROR;
> + goto loop_done;
> + }
> +
> + if (FAILED(hr = MFCreateMemoryBuffer(map_info.maxsize, &mf_buffer)))
> + {
> + gst_memory_unmap(memory, &map_info);
> + goto loop_done;
> + }
> +
> + if (FAILED(hr = IMFMediaBuffer_Lock(mf_buffer, &buf_data, NULL, NULL)))
> + {
> + gst_memory_unmap(memory, &map_info);
> + goto loop_done;
> + }
> +
> + memcpy(buf_data, map_info.data, map_info.size);
> +
> + gst_memory_unmap(memory, &map_info);
> +
> + if (FAILED(hr = IMFMediaBuffer_Unlock(mf_buffer)))
> + goto loop_done;
> +
> + if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(mf_buffer, map_info.size)))
> + goto loop_done;
> +
> + if (FAILED(hr = IMFSample_AddBuffer(out, mf_buffer)))
> + goto loop_done;
> +
> + loop_done:
> + if (mf_buffer)
> + IMFMediaBuffer_Release(mf_buffer);
> + if (memory)
> + gst_memory_unref(memory);
> + if (FAILED(hr))
> + goto fail;
> + }
> +
> + return out;
> + fail:
> + ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
> + IMFSample_Release(out);
> + return NULL;
> +}
> +
> +GstBuffer* gst_buffer_from_mf_sample(IMFSample *mf_sample)
> +{
> + GstBuffer *out = gst_buffer_new();
> + IMFMediaBuffer *mf_buffer = NULL;
> + LONGLONG duration, time;
> + DWORD buffer_count;
> + HRESULT hr;
> +
> + if (FAILED(hr = IMFSample_GetSampleDuration(mf_sample, &duration)))
> + goto fail;
> +
> + if (FAILED(hr = IMFSample_GetSampleTime(mf_sample, &time)))
> + goto fail;
> +
> + GST_BUFFER_DURATION(out) = duration;
> + GST_BUFFER_PTS(out) = time * 100;
> +
> + if (FAILED(hr = IMFSample_GetBufferCount(mf_sample, &buffer_count)))
> + goto fail;
> +
> + for (unsigned int i = 0; i < buffer_count; i++)
> + {
> + DWORD buffer_max_size, buffer_size;
> + GstMapInfo map_info;
> + GstMemory *memory;
> + BYTE *buf_data;
> +
> + if (FAILED(hr = IMFSample_GetBufferByIndex(mf_sample, i, &mf_buffer)))
> + goto fail;
> +
> + if (FAILED(hr = IMFMediaBuffer_GetMaxLength(mf_buffer, &buffer_max_size)))
> + goto fail;
> +
> + if (FAILED(hr = IMFMediaBuffer_GetCurrentLength(mf_buffer, &buffer_size)))
> + goto fail;
> +
> + memory = gst_allocator_alloc(NULL, buffer_size, NULL);
> + gst_memory_resize(memory, 0, buffer_size);
Why is this call to gst_memory_resize() here?
> +
> + if (!(gst_memory_map(memory, &map_info, GST_MAP_WRITE)))
> + {
> + hr = ERROR_INTERNAL_ERROR;
> + goto fail;
> + }
> +
> + if (FAILED(hr = IMFMediaBuffer_Lock(mf_buffer, &buf_data, NULL, NULL)))
> + goto fail;
> +
> + memcpy(map_info.data, buf_data, buffer_size);
> +
> + if (FAILED(hr = IMFMediaBuffer_Unlock(mf_buffer)))
> + goto fail;
> +
> + if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(mf_buffer, buffer_size)))
> + goto fail;
> +
> + gst_memory_unmap(memory, &map_info);
> +
> + gst_buffer_append_memory(out, memory);
> +
> + IMFMediaBuffer_Release(mf_buffer);
> + mf_buffer = NULL;
> + }
> +
> + return out;
> +
> + fail:
> + ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
> + if (mf_buffer)
> + IMFMediaBuffer_Release(mf_buffer);
> + gst_buffer_unref(out);
> + return NULL;
> +}
>
More information about the wine-devel
mailing list