[PATCH] Extending dynamic text capabilities

alcinos french.ebook.lover at gmail.com
Mon Feb 20 19:29:25 UTC 2017


Hi Timon,

Thank you for your contribution.
This mailing list only discusses kdenlive-specific issues or code, and your
patch is essentially a patch to mlt.
I would suggest that you open a Pull-Request on their GitHub:
https://github.com/mltframework/mlt/pulls. There, it can get reviewed and
merged if appropriate.

Then, if your patch is accepted by mlt, we will look into merging you patch
to the effect file.

Best regards,
Nicolas

2017-02-19 12:55 GMT+01:00 Timon <timon37 at gmail.com>:

> Hi,
>
> Currently dynamic text is extremely limited, I hacked it up to support
> more use-cases, mainly:
>  - having an in-clip stopwatch (the docs mention this should work but
> it didn't for me with 16.12.2)
>  - negative countdowns (e.g. rocket launch)
>
> One other case I think would be very useful, but I didn't take a look
> at (I don't need it atm):
>  - scaled time for slow-motion video or time lapse (then you should
> also add year-month-day)
>
> I just added an origin-frame property (that's the frame at which the time
> is 0).
> The formatting is split into separate keywords for hours, minutes,
> seconds, and milliseconds.
> These can be chained, so if you set "#time_m#:#time_s#" the seconds
> will never go beyond 59 (since minutes count that), but if you only
> specify #time_s# the seconds will count arbitrarily large. The main
> limitation is that the keywords have to be in most-significant-first
> order for this to work.
>
> There's a few issues with the patches though:
> 1. using an origin-time might be better than an origin-frame since it
> doesn't depend on the framerate
> 2. I wasn't sure what the right type would be to specify the
> origin-frame/time, and currently it's primitive and limiting
> (min/max), also not very convenient
> 3. how is compatibility/versioning handled between mlt and other
> programs including kdenlive
> 4. getting the profile_fps as part of substitute_keywords is probably not
> nice?
>
>
> I'm not very familiar with either kdenlive nor mlt, so I'd appreciate
> if someone would take this over and do whatever needs doing, including
> discussing and pushing the patch to mlt.
>
>
> From 60f483a6d037bce3a1f99045776ba5a30b987855 Mon Sep 17 00:00:00 2001
> From: timon37 <timon37 at gmail.com>
> Date: Sun, 19 Feb 2017 11:43:08 +0100
> Subject: [PATCH] extend filter_dynamictext with an origin frame and more
>  formatting options
>
> ---
>  data/effects/dynamictext.xml | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/data/effects/dynamictext.xml b/data/effects/dynamictext.xml
> index 3de4570..64911c0 100644
> --- a/data/effects/dynamictext.xml
> +++ b/data/effects/dynamictext.xml
> @@ -38,9 +38,12 @@
>          <paramlistdisplay>Top,Middle,Bottom</paramlistdisplay>
>          <name>Vertical Alignment</name>
>      </parameter>
> +    <parameter type="constant" name="originframe" max="1000000"
> min="-1000000" default="0">
> +        <name>Origin Frame</name>
> +    </parameter>
>      <parameter type="keywords" name="argument" default="#timecode#">
>          <name>Text</name>
>          <keywords>#timecode#;#frame#;#filedate#;#localfiledate#;#
> meta.media.0.stream.frame_rate#;#meta.media.0.codec.
> name#;#meta.media.0.codec.bit_rate#;#meta.media.width#;#
> meta.media.height#;#meta.attr.comment.markup#</keywords>
> -        <keywordsdisplay>timecode;frame;file date;local file
> date;source frame rate;source codec;source bit rate;source
> width;source height;source comment</keywordsdisplay>
> +        <keywordsdisplay>timecode;time_h;time_m;time_s;time_ms;
> time_sign;frame;file
> date;local file date;source frame rate;source codec;source bit
> rate;source width;source height;source comment</keywordsdisplay>
>      </parameter>
>  </effect>
> --
> 2.10.2
>
>
> From 385599b3ea7e51ba559d509cc2df108f76db2525 Mon Sep 17 00:00:00 2001
> From: timon37 <timon37 at gmail.com>
> Date: Sun, 19 Feb 2017 12:28:02 +0100
> Subject: [PATCH] extend filter_dynamictext with an origin frame and more
>  formatting options
>
> ---
>  src/modules/plus/filter_dynamictext.c   | 56
> ++++++++++++++++++++++++++++++---
>  src/modules/plus/filter_dynamictext.yml | 12 +++++++
>  2 files changed, 63 insertions(+), 5 deletions(-)
>
> diff --git a/src/modules/plus/filter_dynamictext.c
> b/src/modules/plus/filter_dynamictext.c
> index 412c13a..d367073 100644
> --- a/src/modules/plus/filter_dynamictext.c
> +++ b/src/modules/plus/filter_dynamictext.c
> @@ -167,17 +167,59 @@ static void get_resource_str( mlt_filter filter,
> mlt_frame frame, char* text )
>
>  /** Perform substitution for keywords that are enclosed in "# #".
>  */
> -static void substitute_keywords(mlt_filter filter, char* result,
> char* value, mlt_frame frame)
> +static void substitute_keywords(mlt_filter filter, char* result,
> char* value, mlt_frame frame, mlt_position origin)
>  {
>         char keyword[MAX_TEXT_LEN] = "";
>         int pos = 0;
>         int is_keyword = 0;
> -
> +
> +       mlt_position frames = mlt_frame_get_position( frame ) - origin;
> +       int frames_negative = frames < 0 ? 1 : 0;
> +       frames = abs( frames );
> +
> +       double fps = 0;
> +       {
> +               mlt_profile profile = mlt_properties_get_data(
> MLT_FILTER_PROPERTIES( filter ), "_profile", NULL );
> +               if ( profile )
> +                       fps = mlt_profile_fps( profile );
> +       }
> +
>         while ( get_next_token(value, &pos, keyword, &is_keyword) )
>         {
> +               size_t len = strlen( result );
> +               size_t left = MAX_TEXT_LEN - len;
>                 if(!is_keyword)
>                 {
> -                       strncat( result, keyword, MAX_TEXT_LEN - strlen(
> result ) - 1 );
> +                       strncat( result, keyword, left - 1 );
> +               }
> +               else if ( !strcmp( keyword, "time_sign" ) )
> +               {
> +                       if ( frames_negative )
> +                               strncat( result, "-", left - 1 );
> +               }
> +               else if ( !strcmp( keyword, "time_h" ) )
> +               {
> +                       int num = frames / ( fps * 60 * 60 );
> +                       snprintf( result + len, left, "%02d", num );
> +                       frames -= num * fps * 60 * 60;
> +               }
> +               else if ( !strcmp( keyword, "time_m" ) )
> +               {
> +                       int num = frames / ( fps * 60 );
> +                       snprintf( result + len, left, "%02d", num );
> +                       frames -= num * fps * 60;
> +               }
> +               else if ( !strcmp( keyword, "time_s" ) )
> +               {
> +                       int num = frames / fps;
> +                       snprintf( result + len, left, "%02d", num );
> +                       frames -= num * fps;
> +               }
> +               else if ( !strcmp( keyword, "time_ms" ) )
> +               {
> +                       int num = ( frames / fps ) * 1000;
> +                       snprintf( result + len, left, "%03d", num );
> +                       frames -= num / 1000 * fps;
>                 }
>                 else if ( !strcmp( keyword, "timecode" ) || !strcmp(
> keyword, "smpte_df" ) )
>                 {
> @@ -214,7 +256,7 @@ static void substitute_keywords(mlt_filter filter,
> char* result, char* value, ml
>                         char *frame_value = mlt_properties_get(
> frame_properties, keyword );
>                         if( frame_value )
>                         {
> -                               strncat( result, frame_value, MAX_TEXT_LEN
> - strlen(result) - 1 );
> +                               strncat( result, frame_value, left - 1 );
>                         }
>                 }
>         }
> @@ -232,9 +274,12 @@ static int setup_producer( mlt_filter filter,
> mlt_producer producer, mlt_frame f
>         // Check for keywords in dynamic text
>         if ( dynamic_text )
>         {
> +               int origin = 0;
> +               if ( mlt_properties_get( my_properties, "originframe" ) )
> +                       origin = mlt_properties_get_int( my_properties,
> "originframe" );
>                 // Apply keyword substitution before passing the text to
> the filter.
>                 char result[MAX_TEXT_LEN] = "";
> -               substitute_keywords( filter, result, dynamic_text, frame );
> +               substitute_keywords( filter, result, dynamic_text, frame,
> origin );
>                 mlt_properties_set( producer_properties, "text",
> (char*)result );
>         }
>
> @@ -386,6 +431,7 @@ mlt_filter filter_dynamictext_init( mlt_profile
> profile, mlt_service_type type,
>                 mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ),
> "eof", "loop" );
>
>                 // Assign default values
> +               mlt_properties_set( my_properties, "originframe", "0" );
>                 mlt_properties_set( my_properties, "argument", arg ? arg:
> "#timecode#" );
>                 mlt_properties_set( my_properties, "geometry",
> "0%/0%:100%x100%:100" );
>                 mlt_properties_set( my_properties, "family", "Sans" );
> diff --git a/src/modules/plus/filter_dynamictext.yml
> b/src/modules/plus/filter_dynamictext.yml
> index 4035ee7..2e4fb90 100644
> --- a/src/modules/plus/filter_dynamictext.yml
> +++ b/src/modules/plus/filter_dynamictext.yml
> @@ -24,6 +24,11 @@ parameters:
>          * #smpte_df#      - SMPTE drop-frame timecode of the frame
>          * #smpte_ndf#     - SMPTE non-drop-frame timecode of the frame
>          * #timecode#      - same as #smpte_df#
> +        * #time_h#        - time in hours
> +        * #time_m#        - time in minutes
> +        * #time_s#        - time in seconds
> +        * #time_ms#       - time in miliseconds
> +        * #time_sign#     - a minus if the Origin Frame is in the future
>          * #frame#         - frame number of the frame
>          * #filedate#      - modification date of the file (GMT)
>          * #localfiledate# - modification date of the file (local)
> @@ -42,6 +47,13 @@ parameters:
>        #timecode#
>      widget: text
>
> +  - identifier: originframe
> +    title: Origin Frame
> +    type: integer
> +    default: 0
> +    unit: frames
> +    widget: spinner
> +
>    - identifier: geometry
>      title: Geometry
>      type: geometry
> --
> 2.10.2
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kdenlive/attachments/20170220/6af13cb5/attachment-0001.html>


More information about the kdenlive mailing list