[PATCH 1/2] evr/mixer: Implement repainting requests.

Nikolay Sivov nsivov at codeweavers.com
Wed Nov 10 06:33:21 CST 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/evr/mixer.c | 75 ++++++++++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 28 deletions(-)

diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index 4f5837a49a4..b9a28c4ad75 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -95,7 +95,8 @@ struct video_mixer
     IMFAttributes *attributes;
     IMFAttributes *internal_attributes;
     unsigned int mixing_flags;
-    unsigned int is_streaming;
+    unsigned int is_streaming : 1;
+    unsigned int output_rendered : 1;
     struct
     {
         COLORREF rgba;
@@ -207,6 +208,20 @@ static void video_mixer_update_zorder_map(struct video_mixer *mixer)
     qsort(mixer->zorder, mixer->input_count, sizeof(*mixer->zorder), video_mixer_zorder_sort_compare);
 }
 
+static void video_mixer_flush_input(struct video_mixer *mixer)
+{
+    unsigned int i;
+
+    for (i = 0; i < mixer->input_count; ++i)
+    {
+        if (mixer->inputs[i].sample)
+            IMFSample_Release(mixer->inputs[i].sample);
+        mixer->inputs[i].sample = NULL;
+        mixer->inputs[i].sample_requested = 0;
+    }
+    mixer->output_rendered = 0;
+}
+
 static void video_mixer_clear_types(struct video_mixer *mixer)
 {
     unsigned int i;
@@ -216,10 +231,8 @@ static void video_mixer_clear_types(struct video_mixer *mixer)
         if (mixer->inputs[i].media_type)
             IMFMediaType_Release(mixer->inputs[i].media_type);
         mixer->inputs[i].media_type = NULL;
-        if (mixer->inputs[i].sample)
-            IMFSample_Release(mixer->inputs[i].sample);
-        mixer->inputs[i].sample = NULL;
     }
+    video_mixer_flush_input(mixer);
     for (i = 0; i < mixer->output.rt_formats_count; ++i)
     {
         IMFMediaType_Release(mixer->output.rt_formats[i].media_type);
@@ -1129,17 +1142,7 @@ static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface,
         case MFT_MESSAGE_COMMAND_FLUSH:
 
             EnterCriticalSection(&mixer->cs);
-
-            for (i = 0; i < mixer->input_count; ++i)
-            {
-                if (mixer->inputs[i].sample)
-                {
-                    IMFSample_Release(mixer->inputs[i].sample);
-                    mixer->inputs[i].sample = NULL;
-                    mixer->inputs[i].sample_requested = 0;
-                }
-            }
-
+            video_mixer_flush_input(mixer);
             LeaveCriticalSection(&mixer->cs);
 
             break;
@@ -1189,10 +1192,12 @@ static HRESULT WINAPI video_mixer_transform_ProcessInput(IMFTransform *iface, DW
     {
         if (!input->media_type || !mixer->output.media_type)
             hr = MF_E_TRANSFORM_TYPE_NOT_SET;
-        else if (input->sample)
+        else if (input->sample && !mixer->output_rendered)
             hr = MF_E_NOTACCEPTING;
         else
         {
+            if (input->sample && mixer->output_rendered)
+                video_mixer_flush_input(mixer);
             mixer->is_streaming = 1;
             input->sample_requested = 0;
             input->sample = sample;
@@ -1361,6 +1366,7 @@ static HRESULT video_mixer_get_sample_desired_time(IMFSample *sample, LONGLONG *
     IMFDesiredSample *desired;
     HRESULT hr;
 
+    *timestamp = *duration = 0;
     if (SUCCEEDED(hr = IMFSample_QueryInterface(sample, &IID_IMFDesiredSample, (void **)&desired)))
     {
         hr = IMFDesiredSample_GetDesiredSampleTimeAndDuration(desired, timestamp, duration);
@@ -1370,6 +1376,18 @@ static HRESULT video_mixer_get_sample_desired_time(IMFSample *sample, LONGLONG *
     return hr;
 }
 
+static BOOL video_mixer_has_input(const struct video_mixer *mixer)
+{
+    unsigned int i;
+
+    for (i = 0; i < mixer->input_count; ++i)
+    {
+        if (!mixer->inputs[i].sample) return FALSE;
+    }
+
+    return TRUE;
+}
+
 static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
         MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
 {
@@ -1377,6 +1395,7 @@ static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, D
     LONGLONG timestamp, duration;
     IDirect3DSurface9 *surface;
     IDirect3DDevice9 *device;
+    BOOL repaint = FALSE;
     unsigned int i;
     HRESULT hr;
 
@@ -1396,15 +1415,20 @@ static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, D
     {
         if (mixer->is_streaming)
         {
-            for (i = 0; i < mixer->input_count; ++i)
+            /* Desired timestamp is ignored, duration is required to be non-zero but is not used either. */
+            if (SUCCEEDED(video_mixer_get_sample_desired_time(buffers->pSample, &timestamp, &duration)))
             {
-                if (!mixer->inputs[i].sample)
+                if (!(repaint = !!duration))
                 {
-                    hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
-                    break;
+                    WARN("Unexpected sample duration.\n");
+                    hr = E_INVALIDARG;
                 }
             }
 
+            /* Not enough input, or no new input. */
+            if (SUCCEEDED(hr) && (!video_mixer_has_input(mixer) || (!repaint && mixer->output_rendered)))
+                hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
+
             if (SUCCEEDED(hr))
             {
                 video_mixer_render(mixer, surface);
@@ -1412,22 +1436,17 @@ static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, D
                 timestamp = duration = 0;
                 if (SUCCEEDED(IMFSample_GetSampleTime(mixer->inputs[0].sample, &timestamp)))
                 {
-                    IMFSample_SetSampleTime(buffers->pSample, timestamp);
-
                     IMFSample_GetSampleDuration(mixer->inputs[0].sample, &duration);
+                    IMFSample_SetSampleTime(buffers->pSample, timestamp);
                     IMFSample_SetSampleDuration(buffers->pSample, duration);
                 }
+                mixer->output_rendered = 1;
             }
 
-            if (SUCCEEDED(hr))
+            if (SUCCEEDED(hr) && !repaint)
             {
                 for (i = 0; i < mixer->input_count; ++i)
-                {
-                    if (mixer->inputs[i].sample)
-                        IMFSample_Release(mixer->inputs[i].sample);
-                    mixer->inputs[i].sample = NULL;
                     video_mixer_request_sample(mixer, i);
-                }
             }
         }
         else
-- 
2.33.0




More information about the wine-devel mailing list