-
Notifications
You must be signed in to change notification settings - Fork 303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix melt not allowing profile change from embeded consumer #453
Conversation
…mer embeded in xml playlist
There is code that already exists in mlt_consumer.c (and consumer_avformat.c for the "s" property) that is already supposed to handle this. For example, the following works: but not Also, if you replace
The s property is expanded to width and height properties, which are mlt_consumer (base level) properties that update the profile. If I add
|
P.S. If you prefer to supply a sample aspect ratio supply properties "sample_aspect_num" and "sample_aspect_den" as integers (real numbers will be truncated). Also, this means you can fix it Kdenlive without waiting for MLT release. |
Hi Dan, thanks for the answer. However the issue you mention is different than what I reported (maybe I was not clear enough). My point it that when doing: melt playlist.mlt -consumer avformat:test.mp4 s="320x200" playlist.mlt is processed with its own profile. For example if the "profile" info contains a 1080p profile, frames are requested at 1080p resolution, then resized by the consumer. If we do: melt playlist.mlt This means that if we have a filter/transition resizing to 300x300, in the first case it will produce a result using 1/3 of the image, and in the second case it will be bigger than full frame. My patch allows processing the playlist with its own profile when using embedded consumer tag |
I understand now. In the first case, the loader producer that melt is using notices the profiles are different and then loads it with the "consumer" producer, which has the normalizing filters to scale. I ran into this use case with Shotcut too, and what I did was add a "multi" parameter to the xml producer to force it to use the "multi" consumer to try to achieve the same thing in a different way. Users are reporting that this introduces an a/v sync problem that I have not yet been able to fix. It seems your change is causing the "consumer" producer to kick in, and that might work better. Thanks, I will test it more soon. I have to look into what happens when the multi consumer is used within the xml producer whether automatically (multiple consumer elements) or explicitly (by parameter) after your change. |
@@ -1147,7 +1147,8 @@ static void on_end_consumer( deserialise_context context, const xmlChar *name ) | |||
{ | |||
// Instantiate the consumer | |||
char *id = trim( mlt_properties_get( properties, "mlt_service" ) ); | |||
context->consumer = mlt_factory_consumer( context->profile, id, resource ); | |||
mlt_profile consumer_profile = mlt_profile_clone( context->profile ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good except we are leaking the cloned profile here. It might be safe to store as a data property with destructor on the consumer. I will test that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is my change on top, and it is working OK (not segfaulting) for me.
--- src/modules/xml/producer_xml.c
+++ src/modules/xml/producer_xml.c
@@ -1149,6 +1149,8 @@ static void on_end_consumer( deserialise_context context, const xmlChar *name )
char *id = trim( mlt_properties_get( properties, "mlt_service" ) );
mlt_profile consumer_profile = mlt_profile_clone( context->profile );
context->consumer = mlt_factory_consumer( consumer_profile, id, resource );
+ mlt_properties_set_data(MLT_CONSUMER_PROPERTIES(context->consumer), "producer_xml.consumer_profile",
+ consumer_profile, 0, (mlt_destructor) mlt_profile_close, NULL);
if ( context->consumer )
{
// Track this consumer
During my tests, I also monitored some other aspects related to a/v sync and performance that I want to share with you about this approach. First of all, performance parameter in the form of real_time on the consumer element in the XML is not being relayed to the consumer in the consumer producer. It does appear, however, from a casual test that you can add "realtime=-N" to the melt command line before the XML filename. Secondly, I noticed a/v sync is way off when changing frame rate (in conjunction with resolution or aspect ratio to trigger the usage of the consumer producer). Frame rate conversion was never implemented in the consumer producer, mentioned here in the loader when injecting the consumer producer: The multi consumer, on the other hand, does handle frame rate conversion. xml producer also handles the performance aspect of real_time as an attribute on the first consumer element. I have not yet found a repro case for the reported a/v sync problem, and I did not run into either today while testing specifically for that. If you want to use the multi consumer to do this as I have done add "?multi=1" after the XML filename. |
Thanks for the detailed answer. I updated my pull request to include the fix for profile leak, works for me too. In the meantime I have applied the multi consumer workaround in Kdenlive, thanks. |
This occured when the s, width, or height properties are supplied with no "aspect."
When using melt to render a .mlt playlist file that contains a
consumer
tag, it does not support profile changes. For example if the consumer contains rescale info (like s=320x200), the rescaling is not correctly passed to the producer. Kdenlive bug: https://bugs.kde.org/show_bug.cgi?id=407678To reproduce, save the following playlist text in a file playlist.mlt file.
This playlist uses a PAL profile and has a red rectangle scaled to 200x200 with an affine filter. The consumer tag applies a rescale using s=320x200.
To reproduce issue, process the playlist with :
melt playlist.mlt
It will create a render in /tmp/test.mp4
You can see that the affine filter does not correctly apply scaling (it scales to 200x200 but ignores the fact that the consumer rescales to 320x200 using the "s=320x200" option), so it almost fills the frame.
This patch fixes the problem, and in the render, the rectangle is now less than a quarter of the frame size.
<mlt LC_NUMERIC="C" version="6.17.0" title="color:red"> <profile description="DV/DVD PAL" width="720" height="576" progressive="0" sample_aspect_num="16" sample_aspect_den="15" display_aspect_num="4" display_aspect_den="3" frame_rate_num="25" frame_rate_den="1" colorspace="601"/> <consumer f="mp4" g="15" crf="23" progressive="1" target="/tmp/test.mp4" threads="1" real_time="-8" mlt_service="avformat" vcodec="libx264" ab="192k" movflags="+faststart" s="320x200" bf="2" acodec="aac" in="0" out="74"/> <producer id="producer0" in="0" out="100"> <property name="length">15000</property> <property name="eof">pause</property> <property name="resource">red</property> <property name="aspect_ratio">1.06667</property> <property name="mlt_service">color</property> <filter id="filter0"> <property name="background">colour:0</property> <property name="mlt_service">affine</property> <property name="transition.geometry">0 0 200 200</property> </filter> </producer> <playlist id="playlist0"> <entry producer="producer0" in="0" out="100"/> </playlist> <tractor id="tractor0" title="color:red" global_feed="1" in="0" out="100"> <track producer="playlist0"/> </tractor> </mlt>