[PATCH 06/16] Introduce GstBuffer -> IMFSample converter.

Derek Lesho dlesho at codeweavers.com
Wed Mar 25 19:12:31 CDT 2020


Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
 dlls/winegstreamer/gst_private.h |  1 +
 dlls/winegstreamer/mfplat.c      | 90 ++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 7d693ced9a..1e5c5afbd4 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -56,5 +56,6 @@ void start_dispatch_thread(void) DECLSPEC_HIDDEN;
 extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
 
 IMFMediaType* media_type_from_caps(GstCaps *caps);
+IMFSample* mf_sample_from_gst_buffer(GstBuffer *in);
 
 #endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 16c1f3c6f9..156f2578b3 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -744,3 +744,93 @@ IMFMediaType* media_type_from_caps(GstCaps *caps)
     IMFMediaType_Release(media_type);
     return NULL;
 }
+
+/* IMFSample = GstBuffer
+   IMFBuffer = GstMemory */
+
+/* TODO: Future optimization could be to create a custom
+   IMFMediaBuffer wrapper around GstMemory, and to utilize
+   gst_memory_new_wrapped on IMFMediaBuffer data.  However,
+   this wouldn't work if we allow the callers to allocate
+   the buffers. */
+
+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 = E_FAIL;
+            goto loop_done;
+        }
+
+        if (!(gst_memory_map(memory, &map_info, GST_MAP_READ)))
+        {
+            hr = E_FAIL;
+            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;
+}
-- 
2.25.1




More information about the wine-devel mailing list