On Freitag, 21. Juli 2023 04:16:05 CEST you wrote:
>  The cairoblend transition has an optimization that if the b frame is
> opaque, it will never request the a frame
> imagehttps://github.com/mltframework/mlt/blob/master/src/modules/frei0r/tra
> nsition_frei0r.c#L61 When this optimization is triggered, get_frame is never
> called on the a frame. As a result, the field order filter never has a
> chance to set the top_field_first flag on the a
> frame.https://github.com/mltframework/mlt/blob/master/src/modules/core/filt
> er_fieldorder.c#L115
> 
> As a test, you can defeat the optimization in a couple of ways:* Set
> invert=1 on the transition* Set the color to be slightly transparent*
> Comment out the optimization in the code What should be done in this
> optimization case? I am not sure. Maybe copy the key image properties from
> the b frame to the a frame. There are many others that could be included.
> This might be a pretty good list here:
> https://github.com/mltframework/mlt/blob/master/src/framework/mlt_tractor.c
> #L379

Thanks a lot for the help and analysis, that helped. I was able to fix the 
problem by moving the mlt_tractor 's frame properties stuff (as linked above) 
to a new function called mlt_tractor_pass_properties, and then call this 
function in the cairoblend and qtblend optimisation.

Attached is my patch. If that approach seems ok for you, I can create a pull 
request.

Best regards,

Jean-Baptiste

> Or maybe there could be a different trick like all the contents of the
> a_frame and b_frame could be swapped when performing this optimization.
> ~Brian
> 
> 
>     On Thursday, July 20, 2023 at 02:42:47 AM CDT, Jean-Baptiste Mardelle
> <j...@kdenlive.org> wrote:
> 
>  Hi all,
> 
> I was recently made aware of an issue in interlaced rendering that seems
> like a bug but I am not exactly sure where the problem lies.
> 
> The problem is that in some cases, MLT renders an interlaced video with
> bottom field first, even when asked for a top field first result. I tracked
> down the issue to some transitions. For example with a simple 2 track color
> sample :
> 
> melt color:red out=20 -track color:blue out=20 -consumer avformat:test.mp4
> f=mxf progressive=0 real_time=-1 threads=0 top_field_first=1
> vcodec=mpeg2video
> 
> Produces a correct top field first video. Now if you add a transition but
> keep the exact same rendering parameters:
> 
> melt color:red out=20 -track color:blue out=20 -transition frei0r.cairoblend
> a_track=0 b_track=1 out=20 -consumer avformat:test.mp4 f=mxf progressive=0
> real_time=-1 threads=0 top_field_first=1 vcodec=mpeg2video
> 
> You get an interlaced video with bottom field first!
> Not all transition seem to have this problem, but at least frei0r.cairoblend
> and qtblend do break the field order.
> 
> FYI, I used mediainfo to detect the field order of the rendered videos.
> 
> Do you have any hint on where / how to fix this ?
> Thanks a lot,
> 
> Jean-Baptiste_______________________________________________
> Mlt-devel mailing list
> Mlt-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/mlt-devel

diff --git a/src/framework/mlt.vers b/src/framework/mlt.vers
index 6cd3d394..5999bf4b 100644
--- a/src/framework/mlt.vers
+++ b/src/framework/mlt.vers
@@ -680,4 +680,5 @@ MLT_7.16.0 {
 MLT_7.18.0 {
   global:
     mlt_audio_free_data;
+    mlt_tractor_pass_properties;
 } MLT_7.16.0;
diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c
index 287913f8..b1306c3e 100644
--- a/src/framework/mlt_tractor.c
+++ b/src/framework/mlt_tractor.c
@@ -345,41 +345,14 @@ mlt_producer mlt_tractor_get_track(mlt_tractor self, int index)
     return mlt_multitrack_track(mlt_tractor_multitrack(self), index);
 }
 
-static int producer_get_image(mlt_frame self,
-                              uint8_t **buffer,
-                              mlt_image_format *format,
-                              int *width,
-                              int *height,
-                              int writable)
-{
-    uint8_t *data = NULL;
-    int size = 0;
-    mlt_properties properties = MLT_FRAME_PROPERTIES(self);
-    mlt_frame frame = mlt_frame_pop_service(self);
-    mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);
-
-    mlt_properties_set_int(frame_properties,
-                           "resize_alpha",
-                           mlt_properties_get_int(properties, "resize_alpha"));
-    mlt_properties_set_int(frame_properties,
-                           "distort",
-                           mlt_properties_get_int(properties, "distort"));
-    mlt_properties_copy(frame_properties, properties, "consumer.");
-    // WebVfx uses this to setup a consumer-stopping event handler.
-    mlt_properties_set_data(frame_properties,
-                            "consumer",
-                            mlt_properties_get_data(properties, "consumer", NULL),
-                            0,
-                            NULL,
-                            NULL);
-
-    mlt_frame_get_image(frame, buffer, format, width, height, writable);
-    mlt_frame_set_image(self, *buffer, 0, NULL);
+/** Pass the consumer defined frame values from one frame to another
+ *
+ * \param properties The destination frame properties
+ * \param frame_properties The source frame properties
+ */
 
-    mlt_properties_set_int(properties, "width", *width);
-    mlt_properties_set_int(properties, "height", *height);
-    mlt_properties_set_int(properties, "format", *format);
-    mlt_properties_set_double(properties, "aspect_ratio", mlt_frame_get_aspect_ratio(frame));
+void mlt_tractor_pass_properties(mlt_properties properties, mlt_properties frame_properties)
+{
     mlt_properties_set_int(properties,
                            "progressive",
                            mlt_properties_get_int(frame_properties, "progressive"));
@@ -426,6 +399,45 @@ static int producer_get_image(mlt_frame self,
                                     NULL);
         }
     }
+}
+
+static int producer_get_image(mlt_frame self,
+                              uint8_t **buffer,
+                              mlt_image_format *format,
+                              int *width,
+                              int *height,
+                              int writable)
+{
+    uint8_t *data = NULL;
+    int size = 0;
+    mlt_properties properties = MLT_FRAME_PROPERTIES(self);
+    mlt_frame frame = mlt_frame_pop_service(self);
+    mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);
+
+    mlt_properties_set_int(frame_properties,
+                           "resize_alpha",
+                           mlt_properties_get_int(properties, "resize_alpha"));
+    mlt_properties_set_int(frame_properties,
+                           "distort",
+                           mlt_properties_get_int(properties, "distort"));
+    mlt_properties_copy(frame_properties, properties, "consumer.");
+    // WebVfx uses this to setup a consumer-stopping event handler.
+    mlt_properties_set_data(frame_properties,
+                            "consumer",
+                            mlt_properties_get_data(properties, "consumer", NULL),
+                            0,
+                            NULL,
+                            NULL);
+
+    mlt_frame_get_image(frame, buffer, format, width, height, writable);
+    mlt_frame_set_image(self, *buffer, 0, NULL);
+
+    mlt_properties_set_int(properties, "width", *width);
+    mlt_properties_set_int(properties, "height", *height);
+    mlt_properties_set_int(properties, "format", *format);
+    mlt_properties_set_double(properties, "aspect_ratio", mlt_frame_get_aspect_ratio(frame));
+
+    mlt_tractor_pass_properties(properties, frame_properties);
 
     data = mlt_frame_get_alpha_size(frame, &size);
     if (data) {
diff --git a/src/framework/mlt_tractor.h b/src/framework/mlt_tractor.h
index e8206ed9..c4d41a2b 100644
--- a/src/framework/mlt_tractor.h
+++ b/src/framework/mlt_tractor.h
@@ -60,5 +60,6 @@ extern int mlt_tractor_insert_track(mlt_tractor self, mlt_producer producer, int
 extern int mlt_tractor_remove_track(mlt_tractor self, int index);
 extern mlt_producer mlt_tractor_get_track(mlt_tractor self, int index);
 extern void mlt_tractor_close(mlt_tractor self);
+extern void mlt_tractor_pass_properties(mlt_properties properties, mlt_properties frame_properties);
 
 #endif
diff --git a/src/modules/frei0r/transition_frei0r.c b/src/modules/frei0r/transition_frei0r.c
index 1dc4e2ed..756e5148 100644
--- a/src/modules/frei0r/transition_frei0r.c
+++ b/src/modules/frei0r/transition_frei0r.c
@@ -68,9 +68,12 @@ static int transition_get_image(mlt_frame a_frame,
         // Check if the alpha channel is entirely opaque.
         && mlt_image_rgba_opaque(images[1], *width, *height)) {
         if (invert)
+        {
             error = mlt_frame_get_image(a_frame, image, format, width, height, 0);
-        else
+        } else {
+            mlt_tractor_pass_properties(a_props, b_props);
             *image = images[1];
+        }
     } else {
         error = mlt_frame_get_image(a_frame, &images[0], format, width, height, 0);
         if (error)
diff --git a/src/modules/qt/transition_qtblend.cpp b/src/modules/qt/transition_qtblend.cpp
index 9ed48c04..162ab21d 100644
--- a/src/modules/qt/transition_qtblend.cpp
+++ b/src/modules/qt/transition_qtblend.cpp
@@ -189,6 +189,7 @@ static int get_image(mlt_frame a_frame,
         }
         if (!hasAlpha) {
             // Prepare output image
+            mlt_tractor_pass_properties(properties, b_properties);
             if (b_frame->convert_image && (b_width != request_width || b_height != request_height)) {
                 mlt_properties_set_int(b_properties, "convert_image_width", request_width);
                 mlt_properties_set_int(b_properties, "convert_image_height", request_height);

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Mlt-devel mailing list
Mlt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlt-devel

Reply via email to