[PATCH 3/5] winegstreamer: Implement WMA decoder ProcessInput.

Rémi Bernon rbernon at codeweavers.com
Tue Feb 22 16:48:17 CST 2022


Simply keeping a reference on the input sample for now, wrapped in a new
wg_sample struct.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/mf/tests/mf.c               |  6 ----
 dlls/winegstreamer/gst_private.h |  3 ++
 dlls/winegstreamer/mfplat.c      | 59 ++++++++++++++++++++++++++++++++
 dlls/winegstreamer/unixlib.h     |  8 +++++
 dlls/winegstreamer/wma_decoder.c | 37 ++++++++++++++++++--
 5 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 60d95529f97..be02a0909e8 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -5996,25 +5996,20 @@ static void test_wma_decoder(void)
 
     sample = create_sample(wma_encoded_data, wma_block_size / 2);
     hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
-    todo_wine
     ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
     ret = IMFSample_Release(sample);
     ok(ret == 0, "Release returned %u\n", ret);
     sample = create_sample(wma_encoded_data + wma_block_size, wma_block_size - wma_block_size / 2);
     hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
-    todo_wine
     ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
     ret = IMFSample_Release(sample);
     ok(ret == 0, "Release returned %u\n", ret);
     sample = create_sample(wma_encoded_data, wma_block_size);
     hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
-    todo_wine
     ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
     hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
-    todo_wine
     ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr);
     ret = IMFSample_Release(sample);
-    todo_wine
     ok(ret == 1, "Release returned %u\n", ret);
 
     /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
@@ -6037,7 +6032,6 @@ static void test_wma_decoder(void)
 
     sample = create_sample(wma_encoded_data, wma_block_size);
     hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
-    todo_wine
     ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr);
     ret = IMFSample_Release(sample);
     ok(ret == 0, "Release returned %u\n", ret);
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index a63daaf04b9..7ad3434fd1d 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -119,6 +119,9 @@ extern HRESULT mfplat_DllRegisterServer(void);
 IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format);
 void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
 
+HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out);
+void mf_destroy_wg_sample(struct wg_sample *wg_sample);
+
 HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
 
 HRESULT audio_converter_create(REFIID riid, void **ret);
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 9b3fc429d32..2ba1490f20b 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -827,3 +827,62 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
     else
         FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
 }
+
+HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
+{
+    DWORD current_length, max_length, count;
+    IMFMediaBuffer *media_buffer = NULL;
+    struct wg_sample *entry;
+    BYTE *buffer;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFSample_GetBufferCount(sample, &count)) || count != 1)
+    {
+        FIXME("Only samples with 1 buffer are supported!\n");
+        return hr ? hr : E_FAIL;
+    }
+
+    if (!(entry = calloc(1, sizeof(*entry))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = IMFSample_GetBufferByIndex(sample, 0, &media_buffer)))
+        goto failed;
+    if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &buffer, &max_length, &current_length)))
+        goto failed;
+
+    IMFSample_AddRef((entry->private = sample));
+    entry->data = buffer;
+    entry->size = current_length;
+    entry->max_size = max_length;
+
+    TRACE("Created sample entry %p.\n", entry);
+    *out = entry;
+    return S_OK;
+
+failed:
+    if (media_buffer)
+        IMFMediaBuffer_Release(media_buffer);
+    free(entry);
+    return hr;
+}
+
+void mf_destroy_wg_sample(struct wg_sample *sample)
+{
+    IMFMediaBuffer *media_buffer;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFSample_GetBufferByIndex(sample->private, 0, &media_buffer)))
+        WARN("Failed to get first buffer, sample %p\n", sample->private);
+    else
+    {
+        /* release lock and ref taken in mf_create_wg_sample */
+        IMFMediaBuffer_Unlock(media_buffer);
+        IMFMediaBuffer_SetCurrentLength(media_buffer, sample->size);
+        IMFMediaBuffer_Release(media_buffer);
+
+        IMFMediaBuffer_Release(media_buffer);
+    }
+
+    IMFSample_Release(sample->private);
+    free(sample);
+}
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 4adbb694766..59b15df7d08 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -103,6 +103,14 @@ struct wg_format
     } u;
 };
 
+struct wg_sample
+{
+    UINT32 max_size;
+    UINT32 size;
+    BYTE *data;
+    void *private;
+};
+
 enum wg_parser_event_type
 {
     WG_PARSER_EVENT_NONE = 0,
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 6c198706944..f84faad669d 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -55,6 +55,7 @@ struct wma_decoder
     IMFMediaType *output_type;
 
     struct wg_transform *wg_transform;
+    struct wg_sample *input_sample;
 };
 
 static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
@@ -134,6 +135,8 @@ static ULONG WINAPI unknown_Release(IUnknown *iface)
             IMFMediaType_Release(decoder->input_type);
         if (decoder->output_type)
             IMFMediaType_Release(decoder->output_type);
+        if (decoder->input_sample)
+            mf_destroy_wg_sample(decoder->input_sample);
         free(decoder);
     }
 
@@ -520,8 +523,38 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
 
 static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
 {
-    FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags);
-    return E_NOTIMPL;
+    struct wma_decoder *decoder = impl_from_IMFTransform(iface);
+    IMFMediaBuffer *media_buffer;
+    struct wg_sample *wg_sample;
+    MFT_INPUT_STREAM_INFO info;
+    HRESULT hr;
+
+    TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface, id, sample, flags);
+
+    if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
+        return hr;
+
+    if (!decoder->wg_transform)
+        return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+    if (decoder->input_sample)
+        return MF_E_NOTACCEPTING;
+
+    if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer)))
+        return hr;
+    IMFMediaBuffer_Release(media_buffer);
+
+    if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample)))
+        return hr;
+
+    if (!(wg_sample->size = (wg_sample->size / info.cbSize) * info.cbSize))
+    {
+        mf_destroy_wg_sample(wg_sample);
+        return S_OK;
+    }
+
+    decoder->input_sample = wg_sample;
+    return S_OK;
 }
 
 static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
-- 
2.34.1




More information about the wine-devel mailing list