[PATCH v2 6/6] winegstreamer: Add timestamp and duration to struct wg_sample.

Rémi Bernon rbernon at codeweavers.com
Tue Apr 5 03:36:59 CDT 2022


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/mf/tests/mf.c                | 10 +---------
 dlls/winegstreamer/mfplat.c       | 17 +++++++++++++++++
 dlls/winegstreamer/unixlib.h      |  5 +++++
 dlls/winegstreamer/wg_transform.c | 25 +++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index d300b2a4d82..db08eb680db 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6361,19 +6361,15 @@ static void test_wma_decoder(void)
         ok(flags == 0, "got flags %#lx\n", flags);
         time = 0xdeadbeef;
         hr = IMFSample_GetSampleTime(sample, &time);
-        todo_wine
         ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
-        todo_wine
         ok(time == i * 928798, "got time %I64d\n", time);
         duration = 0xdeadbeef;
         hr = IMFSample_GetSampleDuration(sample, &duration);
-        todo_wine
         ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
         if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
                 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
         {
             ok(length == wmadec_block_size, "got length %lu\n", length);
-            todo_wine
             ok(duration == 928798, "got duration %I64d\n", duration);
             check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
             wmadec_data += wmadec_block_size;
@@ -7033,16 +7029,12 @@ static void test_h264_decoder(void)
         ok(flags == 0, "got flags %#lx\n", flags);
         time = 0xdeadbeef;
         hr = IMFSample_GetSampleTime(output.pSample, &time);
-        todo_wine
         ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
-        todo_wine
         ok(time == 0, "got time %I64d\n", time);
         duration = 0xdeadbeef;
         hr = IMFSample_GetSampleDuration(output.pSample, &duration);
-        todo_wine
         ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
-        todo_wine
-        ok(duration == 333667, "got duration %I64d\n", duration);
+        ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
 
         /* Win8 and before pad the data with garbage instead of original
          * buffer data, make sure it's consistent.  */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 97e27bb7301..9dcfc558963 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -903,6 +903,7 @@ HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
 {
     DWORD current_length, max_length;
     struct mf_sample *mf_sample;
+    LONGLONG time, duration;
     BYTE *buffer;
     HRESULT hr;
 
@@ -913,6 +914,17 @@ HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
     if (FAILED(hr = IMFMediaBuffer_Lock(mf_sample->media_buffer, &buffer, &max_length, &current_length)))
         goto out;
 
+    if (SUCCEEDED(IMFSample_GetSampleTime(sample, &time)))
+    {
+        mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
+        mf_sample->wg_sample.pts = time;
+    }
+    if (SUCCEEDED(IMFSample_GetSampleDuration(sample, &duration)))
+    {
+        mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+        mf_sample->wg_sample.duration = duration;
+    }
+
     IMFSample_AddRef((mf_sample->sample = sample));
     mf_sample->wg_sample.data = buffer;
     mf_sample->wg_sample.size = current_length;
@@ -937,6 +949,11 @@ void mf_destroy_wg_sample(struct wg_sample *wg_sample)
     IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size);
     IMFMediaBuffer_Release(mf_sample->media_buffer);
 
+    if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+        IMFSample_SetSampleTime(mf_sample->sample, wg_sample->pts);
+    if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+        IMFSample_SetSampleDuration(mf_sample->sample, wg_sample->duration);
+
     IMFSample_Release(mf_sample->sample);
     free(mf_sample);
 }
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index f4e2ea4966b..32e5b068187 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -114,10 +114,15 @@ struct wg_format
 enum wg_sample_flag
 {
     WG_SAMPLE_FLAG_INCOMPLETE = 1,
+    WG_SAMPLE_FLAG_HAS_PTS = 2,
+    WG_SAMPLE_FLAG_HAS_DURATION = 4,
 };
 
 struct wg_sample
 {
+    /* timestamp and duration are in 100-nanosecond units. */
+    UINT64 pts;
+    UINT64 duration;
     UINT32 flags;
     UINT32 max_size;
     UINT32 size;
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 0327b92ce8e..c247a470e75 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -223,6 +223,9 @@ NTSTATUS wg_transform_create(void *args)
              * to match its expectations.
              */
             transform->input_max_length = 16;
+            if (!(element = create_element("h264parse", "base"))
+                    || !transform_append_element(transform, element, &first, &last))
+                goto out;
             /* fallthrough */
         case WG_MAJOR_TYPE_WMA:
             if (!(element = transform_find_element(GST_ELEMENT_FACTORY_TYPE_DECODER, src_caps, raw_caps))
@@ -362,6 +365,10 @@ NTSTATUS wg_transform_push_data(void *args)
         return STATUS_NO_MEMORY;
     }
     gst_buffer_fill(buffer, 0, sample->data, sample->size);
+    if (sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+        GST_BUFFER_PTS(buffer) = sample->pts * 100;
+    if (sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+        GST_BUFFER_DURATION(buffer) = sample->duration * 100;
     gst_buffer_list_insert(transform->input, -1, buffer);
 
     GST_INFO("Copied %u bytes from sample %p to input buffer list", sample->size, sample);
@@ -391,6 +398,24 @@ static NTSTATUS read_transform_output_data(GstBuffer *buffer, struct wg_sample *
     gst_buffer_unmap(buffer, &info);
     gst_buffer_resize(buffer, sample->size, -1);
 
+    if (GST_BUFFER_PTS_IS_VALID(buffer))
+    {
+        sample->flags |= WG_SAMPLE_FLAG_HAS_PTS;
+        sample->pts = GST_BUFFER_PTS(buffer) / 100;
+    }
+    if (GST_BUFFER_DURATION_IS_VALID(buffer))
+    {
+        GstClockTime duration = GST_BUFFER_DURATION(buffer) / 100;
+
+        duration = (duration * sample->size) / info.size;
+        GST_BUFFER_DURATION(buffer) -= duration * 100;
+        if (GST_BUFFER_PTS_IS_VALID(buffer))
+            GST_BUFFER_PTS(buffer) += duration * 100;
+
+        sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+        sample->duration = duration;
+    }
+
     GST_INFO("Copied %u bytes, sample %p, flags %#x", sample->size, sample, sample->flags);
     return STATUS_SUCCESS;
 }
-- 
2.35.1




More information about the wine-devel mailing list