From e8986ddd57005459b7c803a469d680ec2bc388da Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 26 Nov 2021 16:12:16 +0100 Subject: [PATCH 001/130] implement seek --- src/melt/melt.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index f77aefeea..a32061c92 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -212,6 +212,63 @@ static void transport_action( mlt_producer producer, char *value ) fire_jack_seek_event(jack, position); } break; + default: + if (producer) { + mlt_position len = mlt_producer_get_length(producer); + switch (value[0]) { + case 'z': + position = len; + break; + case 'Z': + position = 2 * len; + break; + case 'x': + position = 3 * len; + break; + case 'X': + position = 4 * len; + break; + case 'c': + position = 5 * len; + break; + case 'C': + position = 6 * len; + break; + case 'v': + position = 7 * len; + break; + case 'V': + position = 8 * len; + break; + case 'b': + position = 9 * len; + break; + case 'B': + position = 10 * len; + break; + case 'n': + position = 11 * len; + break; + case 'N': + position = 12 * len; + break; + case 'm': + position = 13 * len; + break; + case 'M': + position = 14 * len; + break; + default: + len = 0; + } + if (len) { + position /= 15; + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, position ); + fire_jack_seek_event(jack, position); + } + } + break; } mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); From c5770e6c567e18cf80fc19278a66fe13512450f4 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 1 Mar 2022 10:28:45 +0100 Subject: [PATCH 002/130] better keyboard handling --- src/melt/melt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index a32061c92..5fcadfa0f 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -502,16 +502,21 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { + char string[2] = {0, 0}; int value = ( silent || progress || is_getc )? -1 : term_read( ); if ( is_getc ) { - value = getc( stdin ); - value = ( value == EOF )? 'q' : value; + do { + value = read(STDIN_FILENO, string, 1); + } while (value == 1 && string[0] < '!'); + if (value != 1) { + string[0] = 'q'; + } } if ( value != -1 ) { - char string[ 2 ] = { value, 0 }; + string[0] = value; transport_action( producer, string ); } From 26e3d3534e6c06196e84936d30c7dd078d1b6265 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 9 Mar 2022 10:53:07 +0100 Subject: [PATCH 003/130] bugfix --- src/melt/melt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 5fcadfa0f..13058225c 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -35,7 +35,7 @@ #include #endif -#include "io.h" +/* #include "io.h" */ static mlt_producer melt = NULL; @@ -509,8 +509,10 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) do { value = read(STDIN_FILENO, string, 1); } while (value == 1 && string[0] < '!'); - if (value != 1) { - string[0] = 'q'; + if (value == 1) { + value = string[0]; + } else { + value = 'q'; } } From 5c482e9dbc9aa8e6ca13fefcf75b7583d61a29ec Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 16 Mar 2022 08:53:12 +0100 Subject: [PATCH 004/130] protobuf --- src/melt/CMakeLists.txt | 4 +- src/melt/Jit.pb-c.c | 410 ++++++++++++++++++++++++++++++++++++++++ src/melt/Jit.pb-c.h | 184 ++++++++++++++++++ src/melt/Jit.proto | 26 +++ src/melt/melt.c | 68 ++++++- 5 files changed, 684 insertions(+), 8 deletions(-) create mode 100644 src/melt/Jit.pb-c.c create mode 100644 src/melt/Jit.pb-c.h create mode 100644 src/melt/Jit.proto diff --git a/src/melt/CMakeLists.txt b/src/melt/CMakeLists.txt index bb7969d7e..b04547e58 100644 --- a/src/melt/CMakeLists.txt +++ b/src/melt/CMakeLists.txt @@ -1,8 +1,8 @@ -add_executable(melt melt.c io.c) +add_executable(melt melt.c io.c Jit.pb-c.c) target_compile_options(melt PRIVATE ${MLT_COMPILE_OPTIONS}) -target_link_libraries(melt PRIVATE mlt Threads::Threads) +target_link_libraries(melt PRIVATE mlt Threads::Threads protobuf-c) target_compile_definitions(melt PRIVATE VERSION="${MLT_VERSION}") diff --git a/src/melt/Jit.pb-c.c b/src/melt/Jit.pb-c.c new file mode 100644 index 000000000..0f76cff52 --- /dev/null +++ b/src/melt/Jit.pb-c.c @@ -0,0 +1,410 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: Jit.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "Jit.pb-c.h" +void jit__init + (Jit *message) +{ + static const Jit init_value = JIT__INIT; + *message = init_value; +} +size_t jit__get_packed_size + (const Jit *message) +{ + assert(message->base.descriptor == &jit__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t jit__pack + (const Jit *message, + uint8_t *out) +{ + assert(message->base.descriptor == &jit__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t jit__pack_to_buffer + (const Jit *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &jit__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Jit * + jit__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Jit *) + protobuf_c_message_unpack (&jit__descriptor, + allocator, len, data); +} +void jit__free_unpacked + (Jit *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &jit__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void media_info__init + (MediaInfo *message) +{ + static const MediaInfo init_value = MEDIA_INFO__INIT; + *message = init_value; +} +size_t media_info__get_packed_size + (const MediaInfo *message) +{ + assert(message->base.descriptor == &media_info__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t media_info__pack + (const MediaInfo *message, + uint8_t *out) +{ + assert(message->base.descriptor == &media_info__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t media_info__pack_to_buffer + (const MediaInfo *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &media_info__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +MediaInfo * + media_info__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (MediaInfo *) + protobuf_c_message_unpack (&media_info__descriptor, + allocator, len, data); +} +void media_info__free_unpacked + (MediaInfo *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &media_info__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void stream__init + (Stream *message) +{ + static const Stream init_value = STREAM__INIT; + *message = init_value; +} +size_t stream__get_packed_size + (const Stream *message) +{ + assert(message->base.descriptor == &stream__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t stream__pack + (const Stream *message, + uint8_t *out) +{ + assert(message->base.descriptor == &stream__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t stream__pack_to_buffer + (const Stream *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &stream__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Stream * + stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Stream *) + protobuf_c_message_unpack (&stream__descriptor, + allocator, len, data); +} +void stream__free_unpacked + (Stream *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &stream__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void audio_stream__init + (AudioStream *message) +{ + static const AudioStream init_value = AUDIO_STREAM__INIT; + *message = init_value; +} +size_t audio_stream__get_packed_size + (const AudioStream *message) +{ + assert(message->base.descriptor == &audio_stream__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t audio_stream__pack + (const AudioStream *message, + uint8_t *out) +{ + assert(message->base.descriptor == &audio_stream__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t audio_stream__pack_to_buffer + (const AudioStream *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &audio_stream__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +AudioStream * + audio_stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (AudioStream *) + protobuf_c_message_unpack (&audio_stream__descriptor, + allocator, len, data); +} +void audio_stream__free_unpacked + (AudioStream *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &audio_stream__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor jit__field_descriptors[3] = +{ + { + "position", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Jit, position), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "playback", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FLOAT, + 0, /* quantifier_offset */ + offsetof(Jit, playback), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mediaInfo", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Jit, mediainfo), + &media_info__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned jit__field_indices_by_name[] = { + 2, /* field[2] = mediaInfo */ + 1, /* field[1] = playback */ + 0, /* field[0] = position */ +}; +static const ProtobufCIntRange jit__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor jit__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Jit", + "Jit", + "Jit", + "", + sizeof(Jit), + 3, + jit__field_descriptors, + jit__field_indices_by_name, + 1, jit__number_ranges, + (ProtobufCMessageInit) jit__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor media_info__field_descriptors[1] = +{ + { + "streams", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(MediaInfo, n_streams), + offsetof(MediaInfo, streams), + &stream__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned media_info__field_indices_by_name[] = { + 0, /* field[0] = streams */ +}; +static const ProtobufCIntRange media_info__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor media_info__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "MediaInfo", + "MediaInfo", + "MediaInfo", + "", + sizeof(MediaInfo), + 1, + media_info__field_descriptors, + media_info__field_indices_by_name, + 1, media_info__number_ranges, + (ProtobufCMessageInit) media_info__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor stream__field_descriptors[2] = +{ + { + "type", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Stream, type), + &stream_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "audio", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Stream, audio), + &audio_stream__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned stream__field_indices_by_name[] = { + 1, /* field[1] = audio */ + 0, /* field[0] = type */ +}; +static const ProtobufCIntRange stream__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor stream__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Stream", + "Stream", + "Stream", + "", + sizeof(Stream), + 2, + stream__field_descriptors, + stream__field_indices_by_name, + 1, stream__number_ranges, + (ProtobufCMessageInit) stream__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor audio_stream__field_descriptors[1] = +{ + { + "channels", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(AudioStream, channels), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned audio_stream__field_indices_by_name[] = { + 0, /* field[0] = channels */ +}; +static const ProtobufCIntRange audio_stream__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor audio_stream__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "AudioStream", + "AudioStream", + "AudioStream", + "", + sizeof(AudioStream), + 1, + audio_stream__field_descriptors, + audio_stream__field_indices_by_name, + 1, audio_stream__number_ranges, + (ProtobufCMessageInit) audio_stream__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue stream_type__enum_values_by_number[3] = +{ + { "UNKNOWN", "STREAM_TYPE__UNKNOWN", 0 }, + { "AUDIO", "STREAM_TYPE__AUDIO", 1 }, + { "VIDEO", "STREAM_TYPE__VIDEO", 2 }, +}; +static const ProtobufCIntRange stream_type__value_ranges[] = { +{0, 0},{0, 3} +}; +static const ProtobufCEnumValueIndex stream_type__enum_values_by_name[3] = +{ + { "AUDIO", 1 }, + { "UNKNOWN", 0 }, + { "VIDEO", 2 }, +}; +const ProtobufCEnumDescriptor stream_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "StreamType", + "StreamType", + "StreamType", + "", + 3, + stream_type__enum_values_by_number, + 3, + stream_type__enum_values_by_name, + 1, + stream_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/src/melt/Jit.pb-c.h b/src/melt/Jit.pb-c.h new file mode 100644 index 000000000..2ac1a1929 --- /dev/null +++ b/src/melt/Jit.pb-c.h @@ -0,0 +1,184 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: Jit.proto */ + +#ifndef PROTOBUF_C_Jit_2eproto__INCLUDED +#define PROTOBUF_C_Jit_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _Jit Jit; +typedef struct _MediaInfo MediaInfo; +typedef struct _Stream Stream; +typedef struct _AudioStream AudioStream; + + +/* --- enums --- */ + +typedef enum _StreamType { + STREAM_TYPE__UNKNOWN = 0, + STREAM_TYPE__AUDIO = 1, + STREAM_TYPE__VIDEO = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(STREAM_TYPE) +} StreamType; + +/* --- messages --- */ + +struct _Jit +{ + ProtobufCMessage base; + int64_t position; + float playback; + MediaInfo *mediainfo; +}; +#define JIT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&jit__descriptor) \ + , 0, 0, NULL } + + +struct _MediaInfo +{ + ProtobufCMessage base; + size_t n_streams; + Stream **streams; +}; +#define MEDIA_INFO__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&media_info__descriptor) \ + , 0,NULL } + + +struct _Stream +{ + ProtobufCMessage base; + StreamType type; + AudioStream *audio; +}; +#define STREAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ + , STREAM_TYPE__UNKNOWN, NULL } + + +struct _AudioStream +{ + ProtobufCMessage base; + int32_t channels; +}; +#define AUDIO_STREAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ + , 0 } + + +/* Jit methods */ +void jit__init + (Jit *message); +size_t jit__get_packed_size + (const Jit *message); +size_t jit__pack + (const Jit *message, + uint8_t *out); +size_t jit__pack_to_buffer + (const Jit *message, + ProtobufCBuffer *buffer); +Jit * + jit__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void jit__free_unpacked + (Jit *message, + ProtobufCAllocator *allocator); +/* MediaInfo methods */ +void media_info__init + (MediaInfo *message); +size_t media_info__get_packed_size + (const MediaInfo *message); +size_t media_info__pack + (const MediaInfo *message, + uint8_t *out); +size_t media_info__pack_to_buffer + (const MediaInfo *message, + ProtobufCBuffer *buffer); +MediaInfo * + media_info__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void media_info__free_unpacked + (MediaInfo *message, + ProtobufCAllocator *allocator); +/* Stream methods */ +void stream__init + (Stream *message); +size_t stream__get_packed_size + (const Stream *message); +size_t stream__pack + (const Stream *message, + uint8_t *out); +size_t stream__pack_to_buffer + (const Stream *message, + ProtobufCBuffer *buffer); +Stream * + stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void stream__free_unpacked + (Stream *message, + ProtobufCAllocator *allocator); +/* AudioStream methods */ +void audio_stream__init + (AudioStream *message); +size_t audio_stream__get_packed_size + (const AudioStream *message); +size_t audio_stream__pack + (const AudioStream *message, + uint8_t *out); +size_t audio_stream__pack_to_buffer + (const AudioStream *message, + ProtobufCBuffer *buffer); +AudioStream * + audio_stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void audio_stream__free_unpacked + (AudioStream *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*Jit_Closure) + (const Jit *message, + void *closure_data); +typedef void (*MediaInfo_Closure) + (const MediaInfo *message, + void *closure_data); +typedef void (*Stream_Closure) + (const Stream *message, + void *closure_data); +typedef void (*AudioStream_Closure) + (const AudioStream *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor stream_type__descriptor; +extern const ProtobufCMessageDescriptor jit__descriptor; +extern const ProtobufCMessageDescriptor media_info__descriptor; +extern const ProtobufCMessageDescriptor stream__descriptor; +extern const ProtobufCMessageDescriptor audio_stream__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_Jit_2eproto__INCLUDED */ diff --git a/src/melt/Jit.proto b/src/melt/Jit.proto new file mode 100644 index 000000000..d6b284111 --- /dev/null +++ b/src/melt/Jit.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +message Jit { + int64 position = 1; + float playback = 2; + MediaInfo mediaInfo = 3; +} + +message MediaInfo { + repeated Stream streams = 1; +} + +message Stream { + StreamType type = 1; + AudioStream audio = 2; +} + +message AudioStream { + int32 channels = 1; +} + +enum StreamType { + UNKNOWN = 0; + AUDIO = 1; + VIDEO = 2; +} diff --git a/src/melt/melt.c b/src/melt/melt.c index 13058225c..007c9e730 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -35,9 +35,11 @@ #include #endif -/* #include "io.h" */ +#include "io.h" +#include "Jit.pb-c.h" static mlt_producer melt = NULL; +static Jit jit = JIT__INIT; static void stop_handler(int signum) { @@ -471,6 +473,32 @@ static void event_handling( mlt_producer producer, mlt_consumer consumer ) #endif +static void write_status(Jit *const jit) { + static char *buf = NULL; + static int buf_len = 0; + + int len = jit__get_packed_size(jit) + 4; + if (buf_len < len) { + buf = realloc(buf, len); + buf_len = len; + if (!buf) { + exit(1); + } + } + + char *b = buf; + jit__pack(jit, b + 4); + *((int*) b) = len - 4; + while (len) { + const int w = write(STDERR_FILENO, b, len); + if (w < 1) { + exit(2); + } + b += w; + len -= w; + } +} + static void transport( mlt_producer producer, mlt_consumer consumer ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); @@ -480,6 +508,9 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) struct timespec tm = { 0, 40000000 }; int total_length = mlt_producer_get_playtime( producer ); int last_position = 0; + fd_set set; + struct timeval timeout; + int sel; if ( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { @@ -487,7 +518,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) { if ( !is_getc ) term_init( ); - +/* fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" ); fprintf( stderr, "|1=-10| |2= -5| |3= -2| |4= -1| |5= 0| |6= 1| |7= 2| |8= 5| |9= 10|\n" ); fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" ); @@ -498,10 +529,27 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) fprintf( stderr, "| g = start of clip, j = next clip, k = previous clip |\n" ); fprintf( stderr, "| 0 = restart, q = quit, space = play |\n" ); fprintf( stderr, "+---------------------------------------------------------------------+\n" ); +*/ } while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { + + char string[2] = {0, 0}; + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0) { + if (read(STDIN_FILENO, string, 1) != 1) { + string[0] = 'q'; + } + if (string[0] >= '!') { + transport_action( producer, string ); + } + } + + /* char string[2] = {0, 0}; int value = ( silent || progress || is_getc )? -1 : term_read( ); if ( is_getc ) @@ -521,6 +569,8 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) string[0] = value; transport_action( producer, string ); } + */ + #if defined(SDL_MAJOR_VERSION) event_handling( producer, consumer ); @@ -528,6 +578,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) if ( !silent && mlt_properties_get_int( properties, "stats_off" ) == 0 ) { + /* if ( progress ) { int current_position = mlt_producer_position( producer ); @@ -544,14 +595,19 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) fprintf( stderr, "Current Position: %10d\r", (int)mlt_consumer_position( consumer ) ); } fflush( stderr ); + */ + // MOFF + jit.position = mlt_producer_position( producer ); + write_status(&jit); + last_position = jit.position; } - if ( silent || progress ) - nanosleep( &tm, NULL ); + //if ( silent || progress ) + //nanosleep( &tm, NULL ); } - if ( !silent ) - fprintf( stderr, "\n" ); + //if ( !silent ) + //fprintf( stderr, "\n" ); } } From ded74924ea384c650c59ff51e6082e0bc14fe9d7 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 23 Mar 2022 15:57:03 +0100 Subject: [PATCH 005/130] protobuf i/o --- src/melt/CMakeLists.txt | 2 +- src/melt/Jit.pb-c.h | 184 ---------------------------------------- src/melt/Jit.proto | 26 ------ src/melt/melt.c | 87 ++++++++++++++++--- 4 files changed, 77 insertions(+), 222 deletions(-) delete mode 100644 src/melt/Jit.pb-c.h delete mode 100644 src/melt/Jit.proto diff --git a/src/melt/CMakeLists.txt b/src/melt/CMakeLists.txt index b04547e58..eb66f5b04 100644 --- a/src/melt/CMakeLists.txt +++ b/src/melt/CMakeLists.txt @@ -1,4 +1,4 @@ -add_executable(melt melt.c io.c Jit.pb-c.c) +add_executable(melt melt.c io.c JitControl.pb-c.c JitStatus.pb-c.c) target_compile_options(melt PRIVATE ${MLT_COMPILE_OPTIONS}) diff --git a/src/melt/Jit.pb-c.h b/src/melt/Jit.pb-c.h deleted file mode 100644 index 2ac1a1929..000000000 --- a/src/melt/Jit.pb-c.h +++ /dev/null @@ -1,184 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: Jit.proto */ - -#ifndef PROTOBUF_C_Jit_2eproto__INCLUDED -#define PROTOBUF_C_Jit_2eproto__INCLUDED - -#include - -PROTOBUF_C__BEGIN_DECLS - -#if PROTOBUF_C_VERSION_NUMBER < 1003000 -# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION -# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. -#endif - - -typedef struct _Jit Jit; -typedef struct _MediaInfo MediaInfo; -typedef struct _Stream Stream; -typedef struct _AudioStream AudioStream; - - -/* --- enums --- */ - -typedef enum _StreamType { - STREAM_TYPE__UNKNOWN = 0, - STREAM_TYPE__AUDIO = 1, - STREAM_TYPE__VIDEO = 2 - PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(STREAM_TYPE) -} StreamType; - -/* --- messages --- */ - -struct _Jit -{ - ProtobufCMessage base; - int64_t position; - float playback; - MediaInfo *mediainfo; -}; -#define JIT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&jit__descriptor) \ - , 0, 0, NULL } - - -struct _MediaInfo -{ - ProtobufCMessage base; - size_t n_streams; - Stream **streams; -}; -#define MEDIA_INFO__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&media_info__descriptor) \ - , 0,NULL } - - -struct _Stream -{ - ProtobufCMessage base; - StreamType type; - AudioStream *audio; -}; -#define STREAM__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ - , STREAM_TYPE__UNKNOWN, NULL } - - -struct _AudioStream -{ - ProtobufCMessage base; - int32_t channels; -}; -#define AUDIO_STREAM__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ - , 0 } - - -/* Jit methods */ -void jit__init - (Jit *message); -size_t jit__get_packed_size - (const Jit *message); -size_t jit__pack - (const Jit *message, - uint8_t *out); -size_t jit__pack_to_buffer - (const Jit *message, - ProtobufCBuffer *buffer); -Jit * - jit__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void jit__free_unpacked - (Jit *message, - ProtobufCAllocator *allocator); -/* MediaInfo methods */ -void media_info__init - (MediaInfo *message); -size_t media_info__get_packed_size - (const MediaInfo *message); -size_t media_info__pack - (const MediaInfo *message, - uint8_t *out); -size_t media_info__pack_to_buffer - (const MediaInfo *message, - ProtobufCBuffer *buffer); -MediaInfo * - media_info__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void media_info__free_unpacked - (MediaInfo *message, - ProtobufCAllocator *allocator); -/* Stream methods */ -void stream__init - (Stream *message); -size_t stream__get_packed_size - (const Stream *message); -size_t stream__pack - (const Stream *message, - uint8_t *out); -size_t stream__pack_to_buffer - (const Stream *message, - ProtobufCBuffer *buffer); -Stream * - stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void stream__free_unpacked - (Stream *message, - ProtobufCAllocator *allocator); -/* AudioStream methods */ -void audio_stream__init - (AudioStream *message); -size_t audio_stream__get_packed_size - (const AudioStream *message); -size_t audio_stream__pack - (const AudioStream *message, - uint8_t *out); -size_t audio_stream__pack_to_buffer - (const AudioStream *message, - ProtobufCBuffer *buffer); -AudioStream * - audio_stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void audio_stream__free_unpacked - (AudioStream *message, - ProtobufCAllocator *allocator); -/* --- per-message closures --- */ - -typedef void (*Jit_Closure) - (const Jit *message, - void *closure_data); -typedef void (*MediaInfo_Closure) - (const MediaInfo *message, - void *closure_data); -typedef void (*Stream_Closure) - (const Stream *message, - void *closure_data); -typedef void (*AudioStream_Closure) - (const AudioStream *message, - void *closure_data); - -/* --- services --- */ - - -/* --- descriptors --- */ - -extern const ProtobufCEnumDescriptor stream_type__descriptor; -extern const ProtobufCMessageDescriptor jit__descriptor; -extern const ProtobufCMessageDescriptor media_info__descriptor; -extern const ProtobufCMessageDescriptor stream__descriptor; -extern const ProtobufCMessageDescriptor audio_stream__descriptor; - -PROTOBUF_C__END_DECLS - - -#endif /* PROTOBUF_C_Jit_2eproto__INCLUDED */ diff --git a/src/melt/Jit.proto b/src/melt/Jit.proto deleted file mode 100644 index d6b284111..000000000 --- a/src/melt/Jit.proto +++ /dev/null @@ -1,26 +0,0 @@ -syntax = "proto3"; - -message Jit { - int64 position = 1; - float playback = 2; - MediaInfo mediaInfo = 3; -} - -message MediaInfo { - repeated Stream streams = 1; -} - -message Stream { - StreamType type = 1; - AudioStream audio = 2; -} - -message AudioStream { - int32 channels = 1; -} - -enum StreamType { - UNKNOWN = 0; - AUDIO = 1; - VIDEO = 2; -} diff --git a/src/melt/melt.c b/src/melt/melt.c index 007c9e730..df5a82644 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -36,10 +36,11 @@ #endif #include "io.h" -#include "Jit.pb-c.h" +#include "JitControl.pb-c.h" +#include "JitStatus.pb-c.h" static mlt_producer melt = NULL; -static Jit jit = JIT__INIT; +static JitStatus jit_status = JIT_STATUS__INIT; static void stop_handler(int signum) { @@ -74,6 +75,37 @@ static void transport_action( mlt_producer producer, char *value ) mlt_properties_set_int( properties, "stats_off", 1 ); + JitControl *const jit_control = (JitControl*) value; + switch (jit_control->type) { + case CONTROL_TYPE__PAUSE: + mlt_producer_set_speed( producer, 0 ); + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + jit_status.playing = 0; + break; + case CONTROL_TYPE__PLAY: + if ( !jack || mlt_producer_get_speed( producer ) != 0 ) + mlt_producer_set_speed( producer, 1 ); + mlt_consumer_purge( consumer ); + mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); + jit_status.playing = 1; + break; + case CONTROL_TYPE__SEEK: + //mlt_position len = mlt_producer_get_length(producer); + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, jit_control->seek->position ); + fire_jack_seek_event(jack, position); + break; + case CONTROL_TYPE__QUIT: + mlt_properties_set_int( properties, "done", 1 ); + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + break; + default: + break; + } + + /* if ( strlen( value ) == 1 ) { switch( value[ 0 ] ) @@ -274,7 +306,7 @@ static void transport_action( mlt_producer producer, char *value ) } mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); - } + } */ mlt_properties_set_int( properties, "stats_off", 0 ); } @@ -473,21 +505,47 @@ static void event_handling( mlt_producer producer, mlt_consumer consumer ) #endif -static void write_status(Jit *const jit) { +static JitControl *read_control() { + static char *buf = NULL; + static int buf_len = 0; + + int len; + if (read(STDIN_FILENO, &len, 4) != 4) { + exit(3); + } + if (buf_len < len) { + buf = realloc(buf, len); + if (!buf) { + exit(4); + } + buf_len = len; + } + + for (int i = 0; i < len; ) { + const int r = read(STDIN_FILENO, buf + i, len - i); + if (r < 1) { + exit(5); + } + i += r; + } + return jit_control__unpack(NULL, len, buf); +} + +static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; - int len = jit__get_packed_size(jit) + 4; + int len = jit_status__get_packed_size(jit_status) + 4; if (buf_len < len) { buf = realloc(buf, len); - buf_len = len; if (!buf) { exit(1); } + buf_len = len; } char *b = buf; - jit__pack(jit, b + 4); + jit_status__pack(jit_status, b + 4); *((int*) b) = len - 4; while (len) { const int w = write(STDERR_FILENO, b, len); @@ -535,18 +593,25 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { - char string[2] = {0, 0}; + //char string[2] = {0, 0}; FD_ZERO(&set); FD_SET(STDIN_FILENO, &set); timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0) { + /* if (read(STDIN_FILENO, string, 1) != 1) { string[0] = 'q'; } if (string[0] >= '!') { transport_action( producer, string ); } + */ + JitControl *const jit_control = read_control(); + if (jit_control) { + transport_action( producer, (char*) jit_control ); + jit_control__free_unpacked(jit_control, NULL); + } } /* @@ -597,9 +662,9 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) fflush( stderr ); */ // MOFF - jit.position = mlt_producer_position( producer ); - write_status(&jit); - last_position = jit.position; + jit_status.position = mlt_producer_position( producer ); + write_status(&jit_status); + last_position = jit_status.position; } //if ( silent || progress ) From 42b9247f1178aa39c5b56cf891d63b53c375f594 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 10:31:58 +0200 Subject: [PATCH 006/130] add missing files --- src/melt/JitControl.pb-c.c | 220 ++++++++++++++++++++++ src/melt/JitControl.pb-c.h | 114 +++++++++++ src/melt/JitControl.proto | 17 ++ src/melt/{Jit.pb-c.c => JitStatus.pb-c.c} | 97 +++++----- src/melt/JitStatus.pb-c.h | 185 ++++++++++++++++++ src/melt/JitStatus.proto | 27 +++ 6 files changed, 618 insertions(+), 42 deletions(-) create mode 100644 src/melt/JitControl.pb-c.c create mode 100644 src/melt/JitControl.pb-c.h create mode 100644 src/melt/JitControl.proto rename src/melt/{Jit.pb-c.c => JitStatus.pb-c.c} (84%) create mode 100644 src/melt/JitStatus.pb-c.h create mode 100644 src/melt/JitStatus.proto diff --git a/src/melt/JitControl.pb-c.c b/src/melt/JitControl.pb-c.c new file mode 100644 index 000000000..b741bc4d0 --- /dev/null +++ b/src/melt/JitControl.pb-c.c @@ -0,0 +1,220 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: JitControl.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "JitControl.pb-c.h" +void jit_control__init + (JitControl *message) +{ + static const JitControl init_value = JIT_CONTROL__INIT; + *message = init_value; +} +size_t jit_control__get_packed_size + (const JitControl *message) +{ + assert(message->base.descriptor == &jit_control__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t jit_control__pack + (const JitControl *message, + uint8_t *out) +{ + assert(message->base.descriptor == &jit_control__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t jit_control__pack_to_buffer + (const JitControl *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &jit_control__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +JitControl * + jit_control__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (JitControl *) + protobuf_c_message_unpack (&jit_control__descriptor, + allocator, len, data); +} +void jit_control__free_unpacked + (JitControl *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &jit_control__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void seek_control__init + (SeekControl *message) +{ + static const SeekControl init_value = SEEK_CONTROL__INIT; + *message = init_value; +} +size_t seek_control__get_packed_size + (const SeekControl *message) +{ + assert(message->base.descriptor == &seek_control__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t seek_control__pack + (const SeekControl *message, + uint8_t *out) +{ + assert(message->base.descriptor == &seek_control__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t seek_control__pack_to_buffer + (const SeekControl *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &seek_control__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +SeekControl * + seek_control__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (SeekControl *) + protobuf_c_message_unpack (&seek_control__descriptor, + allocator, len, data); +} +void seek_control__free_unpacked + (SeekControl *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &seek_control__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor jit_control__field_descriptors[2] = +{ + { + "type", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(JitControl, type), + &control_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "seek", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(JitControl, seek), + &seek_control__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned jit_control__field_indices_by_name[] = { + 1, /* field[1] = seek */ + 0, /* field[0] = type */ +}; +static const ProtobufCIntRange jit_control__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor jit_control__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "JitControl", + "JitControl", + "JitControl", + "", + sizeof(JitControl), + 2, + jit_control__field_descriptors, + jit_control__field_indices_by_name, + 1, jit_control__number_ranges, + (ProtobufCMessageInit) jit_control__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor seek_control__field_descriptors[1] = +{ + { + "position", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(SeekControl, position), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned seek_control__field_indices_by_name[] = { + 0, /* field[0] = position */ +}; +static const ProtobufCIntRange seek_control__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor seek_control__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "SeekControl", + "SeekControl", + "SeekControl", + "", + sizeof(SeekControl), + 1, + seek_control__field_descriptors, + seek_control__field_indices_by_name, + 1, seek_control__number_ranges, + (ProtobufCMessageInit) seek_control__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue control_type__enum_values_by_number[4] = +{ + { "PAUSE", "CONTROL_TYPE__PAUSE", 0 }, + { "PLAY", "CONTROL_TYPE__PLAY", 1 }, + { "SEEK", "CONTROL_TYPE__SEEK", 2 }, + { "QUIT", "CONTROL_TYPE__QUIT", 3 }, +}; +static const ProtobufCIntRange control_type__value_ranges[] = { +{0, 0},{0, 4} +}; +static const ProtobufCEnumValueIndex control_type__enum_values_by_name[4] = +{ + { "PAUSE", 0 }, + { "PLAY", 1 }, + { "QUIT", 3 }, + { "SEEK", 2 }, +}; +const ProtobufCEnumDescriptor control_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "ControlType", + "ControlType", + "ControlType", + "", + 4, + control_type__enum_values_by_number, + 4, + control_type__enum_values_by_name, + 1, + control_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h new file mode 100644 index 000000000..5357773e7 --- /dev/null +++ b/src/melt/JitControl.pb-c.h @@ -0,0 +1,114 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: JitControl.proto */ + +#ifndef PROTOBUF_C_JitControl_2eproto__INCLUDED +#define PROTOBUF_C_JitControl_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _JitControl JitControl; +typedef struct _SeekControl SeekControl; + + +/* --- enums --- */ + +typedef enum _ControlType { + CONTROL_TYPE__PAUSE = 0, + CONTROL_TYPE__PLAY = 1, + CONTROL_TYPE__SEEK = 2, + CONTROL_TYPE__QUIT = 3 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(CONTROL_TYPE) +} ControlType; + +/* --- messages --- */ + +struct _JitControl +{ + ProtobufCMessage base; + ControlType type; + SeekControl *seek; +}; +#define JIT_CONTROL__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&jit_control__descriptor) \ + , CONTROL_TYPE__PAUSE, NULL } + + +struct _SeekControl +{ + ProtobufCMessage base; + int64_t position; +}; +#define SEEK_CONTROL__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&seek_control__descriptor) \ + , 0 } + + +/* JitControl methods */ +void jit_control__init + (JitControl *message); +size_t jit_control__get_packed_size + (const JitControl *message); +size_t jit_control__pack + (const JitControl *message, + uint8_t *out); +size_t jit_control__pack_to_buffer + (const JitControl *message, + ProtobufCBuffer *buffer); +JitControl * + jit_control__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void jit_control__free_unpacked + (JitControl *message, + ProtobufCAllocator *allocator); +/* SeekControl methods */ +void seek_control__init + (SeekControl *message); +size_t seek_control__get_packed_size + (const SeekControl *message); +size_t seek_control__pack + (const SeekControl *message, + uint8_t *out); +size_t seek_control__pack_to_buffer + (const SeekControl *message, + ProtobufCBuffer *buffer); +SeekControl * + seek_control__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void seek_control__free_unpacked + (SeekControl *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*JitControl_Closure) + (const JitControl *message, + void *closure_data); +typedef void (*SeekControl_Closure) + (const SeekControl *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor control_type__descriptor; +extern const ProtobufCMessageDescriptor jit_control__descriptor; +extern const ProtobufCMessageDescriptor seek_control__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_JitControl_2eproto__INCLUDED */ diff --git a/src/melt/JitControl.proto b/src/melt/JitControl.proto new file mode 100644 index 000000000..22dd7e05b --- /dev/null +++ b/src/melt/JitControl.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +message JitControl { + ControlType type = 1; + SeekControl seek = 2; +} + +message SeekControl { + int64 position = 1; +} + +enum ControlType { + PAUSE = 0; + PLAY = 1; + SEEK = 2; + QUIT = 3; +} diff --git a/src/melt/Jit.pb-c.c b/src/melt/JitStatus.pb-c.c similarity index 84% rename from src/melt/Jit.pb-c.c rename to src/melt/JitStatus.pb-c.c index 0f76cff52..77e4e2103 100644 --- a/src/melt/Jit.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -1,55 +1,55 @@ /* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: Jit.proto */ +/* Generated from: JitStatus.proto */ /* Do not generate deprecated warnings for self */ #ifndef PROTOBUF_C__NO_DEPRECATED #define PROTOBUF_C__NO_DEPRECATED #endif -#include "Jit.pb-c.h" -void jit__init - (Jit *message) +#include "JitStatus.pb-c.h" +void jit_status__init + (JitStatus *message) { - static const Jit init_value = JIT__INIT; + static const JitStatus init_value = JIT_STATUS__INIT; *message = init_value; } -size_t jit__get_packed_size - (const Jit *message) +size_t jit_status__get_packed_size + (const JitStatus *message) { - assert(message->base.descriptor == &jit__descriptor); + assert(message->base.descriptor == &jit_status__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t jit__pack - (const Jit *message, +size_t jit_status__pack + (const JitStatus *message, uint8_t *out) { - assert(message->base.descriptor == &jit__descriptor); + assert(message->base.descriptor == &jit_status__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t jit__pack_to_buffer - (const Jit *message, +size_t jit_status__pack_to_buffer + (const JitStatus *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &jit__descriptor); + assert(message->base.descriptor == &jit_status__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -Jit * - jit__unpack +JitStatus * + jit_status__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (Jit *) - protobuf_c_message_unpack (&jit__descriptor, + return (JitStatus *) + protobuf_c_message_unpack (&jit_status__descriptor, allocator, len, data); } -void jit__free_unpacked - (Jit *message, +void jit_status__free_unpacked + (JitStatus *message, ProtobufCAllocator *allocator) { if(!message) return; - assert(message->base.descriptor == &jit__descriptor); + assert(message->base.descriptor == &jit_status__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void media_info__init @@ -187,7 +187,7 @@ void audio_stream__free_unpacked assert(message->base.descriptor == &audio_stream__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -static const ProtobufCFieldDescriptor jit__field_descriptors[3] = +static const ProtobufCFieldDescriptor jit_status__field_descriptors[4] = { { "position", @@ -195,19 +195,31 @@ static const ProtobufCFieldDescriptor jit__field_descriptors[3] = PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT64, 0, /* quantifier_offset */ - offsetof(Jit, position), + offsetof(JitStatus, position), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "playback", + "playing", 2, PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(JitStatus, playing), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "playback_rate", + 3, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_FLOAT, 0, /* quantifier_offset */ - offsetof(Jit, playback), + offsetof(JitStatus, playback_rate), NULL, NULL, 0, /* flags */ @@ -215,40 +227,41 @@ static const ProtobufCFieldDescriptor jit__field_descriptors[3] = }, { "mediaInfo", - 3, + 4, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(Jit, mediainfo), + offsetof(JitStatus, mediainfo), &media_info__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned jit__field_indices_by_name[] = { - 2, /* field[2] = mediaInfo */ - 1, /* field[1] = playback */ +static const unsigned jit_status__field_indices_by_name[] = { + 3, /* field[3] = mediaInfo */ + 2, /* field[2] = playback_rate */ + 1, /* field[1] = playing */ 0, /* field[0] = position */ }; -static const ProtobufCIntRange jit__number_ranges[1 + 1] = +static const ProtobufCIntRange jit_status__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 3 } + { 0, 4 } }; -const ProtobufCMessageDescriptor jit__descriptor = +const ProtobufCMessageDescriptor jit_status__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "Jit", - "Jit", - "Jit", + "JitStatus", + "JitStatus", + "JitStatus", "", - sizeof(Jit), - 3, - jit__field_descriptors, - jit__field_indices_by_name, - 1, jit__number_ranges, - (ProtobufCMessageInit) jit__init, + sizeof(JitStatus), + 4, + jit_status__field_descriptors, + jit_status__field_indices_by_name, + 1, jit_status__number_ranges, + (ProtobufCMessageInit) jit_status__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCFieldDescriptor media_info__field_descriptors[1] = diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h new file mode 100644 index 000000000..7e388bd75 --- /dev/null +++ b/src/melt/JitStatus.pb-c.h @@ -0,0 +1,185 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: JitStatus.proto */ + +#ifndef PROTOBUF_C_JitStatus_2eproto__INCLUDED +#define PROTOBUF_C_JitStatus_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _JitStatus JitStatus; +typedef struct _MediaInfo MediaInfo; +typedef struct _Stream Stream; +typedef struct _AudioStream AudioStream; + + +/* --- enums --- */ + +typedef enum _StreamType { + STREAM_TYPE__UNKNOWN = 0, + STREAM_TYPE__AUDIO = 1, + STREAM_TYPE__VIDEO = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(STREAM_TYPE) +} StreamType; + +/* --- messages --- */ + +struct _JitStatus +{ + ProtobufCMessage base; + int64_t position; + protobuf_c_boolean playing; + float playback_rate; + MediaInfo *mediainfo; +}; +#define JIT_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ + , 0, 0, 0, NULL } + + +struct _MediaInfo +{ + ProtobufCMessage base; + size_t n_streams; + Stream **streams; +}; +#define MEDIA_INFO__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&media_info__descriptor) \ + , 0,NULL } + + +struct _Stream +{ + ProtobufCMessage base; + StreamType type; + AudioStream *audio; +}; +#define STREAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ + , STREAM_TYPE__UNKNOWN, NULL } + + +struct _AudioStream +{ + ProtobufCMessage base; + int32_t channels; +}; +#define AUDIO_STREAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ + , 0 } + + +/* JitStatus methods */ +void jit_status__init + (JitStatus *message); +size_t jit_status__get_packed_size + (const JitStatus *message); +size_t jit_status__pack + (const JitStatus *message, + uint8_t *out); +size_t jit_status__pack_to_buffer + (const JitStatus *message, + ProtobufCBuffer *buffer); +JitStatus * + jit_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void jit_status__free_unpacked + (JitStatus *message, + ProtobufCAllocator *allocator); +/* MediaInfo methods */ +void media_info__init + (MediaInfo *message); +size_t media_info__get_packed_size + (const MediaInfo *message); +size_t media_info__pack + (const MediaInfo *message, + uint8_t *out); +size_t media_info__pack_to_buffer + (const MediaInfo *message, + ProtobufCBuffer *buffer); +MediaInfo * + media_info__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void media_info__free_unpacked + (MediaInfo *message, + ProtobufCAllocator *allocator); +/* Stream methods */ +void stream__init + (Stream *message); +size_t stream__get_packed_size + (const Stream *message); +size_t stream__pack + (const Stream *message, + uint8_t *out); +size_t stream__pack_to_buffer + (const Stream *message, + ProtobufCBuffer *buffer); +Stream * + stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void stream__free_unpacked + (Stream *message, + ProtobufCAllocator *allocator); +/* AudioStream methods */ +void audio_stream__init + (AudioStream *message); +size_t audio_stream__get_packed_size + (const AudioStream *message); +size_t audio_stream__pack + (const AudioStream *message, + uint8_t *out); +size_t audio_stream__pack_to_buffer + (const AudioStream *message, + ProtobufCBuffer *buffer); +AudioStream * + audio_stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void audio_stream__free_unpacked + (AudioStream *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*JitStatus_Closure) + (const JitStatus *message, + void *closure_data); +typedef void (*MediaInfo_Closure) + (const MediaInfo *message, + void *closure_data); +typedef void (*Stream_Closure) + (const Stream *message, + void *closure_data); +typedef void (*AudioStream_Closure) + (const AudioStream *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor stream_type__descriptor; +extern const ProtobufCMessageDescriptor jit_status__descriptor; +extern const ProtobufCMessageDescriptor media_info__descriptor; +extern const ProtobufCMessageDescriptor stream__descriptor; +extern const ProtobufCMessageDescriptor audio_stream__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_JitStatus_2eproto__INCLUDED */ diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto new file mode 100644 index 000000000..ffb6a5f8a --- /dev/null +++ b/src/melt/JitStatus.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +message JitStatus { + int64 position = 1; + bool playing = 2; + float playback_rate = 3; + MediaInfo mediaInfo = 4; +} + +message MediaInfo { + repeated Stream streams = 1; +} + +message Stream { + StreamType type = 1; + AudioStream audio = 2; +} + +message AudioStream { + int32 channels = 1; +} + +enum StreamType { + UNKNOWN = 0; + AUDIO = 1; + VIDEO = 2; +} From 47a247919fa2728256046c4d5a83fc2466213c0d Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 14:11:42 +0200 Subject: [PATCH 007/130] fix seek --- src/melt/melt.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index df5a82644..5ccc48685 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -85,17 +85,23 @@ static void transport_action( mlt_producer producer, char *value ) jit_status.playing = 0; break; case CONTROL_TYPE__PLAY: - if ( !jack || mlt_producer_get_speed( producer ) != 0 ) - mlt_producer_set_speed( producer, 1 ); + //if ( !jack || mlt_producer_get_speed( producer ) != 0 ) + mlt_producer_set_speed( producer, 1 ); mlt_consumer_purge( consumer ); mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); jit_status.playing = 1; break; case CONTROL_TYPE__SEEK: + FILE *f = fopen("/tmp/moff.log", "a"); + fprintf("seek: %d\n", (int) jit_control->seek->position); + fclose(f); + //mlt_position len = mlt_producer_get_length(producer); + mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, jit_control->seek->position ); - fire_jack_seek_event(jack, position); + //fire_jack_seek_event(jack, position); + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); break; case CONTROL_TYPE__QUIT: mlt_properties_set_int( properties, "done", 1 ); From b2a16f3c1633e4fea31b0026d01f916b6926bd11 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 14:35:57 +0200 Subject: [PATCH 008/130] bugfix --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 5ccc48685..ee7747f29 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -93,7 +93,7 @@ static void transport_action( mlt_producer producer, char *value ) break; case CONTROL_TYPE__SEEK: FILE *f = fopen("/tmp/moff.log", "a"); - fprintf("seek: %d\n", (int) jit_control->seek->position); + fprintf(f, "seek: %d\n", (int) jit_control->seek->position); fclose(f); //mlt_position len = mlt_producer_get_length(producer); From b18821f24c9b4a97c088f89e2cfd5258093323e1 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 14:47:07 +0200 Subject: [PATCH 009/130] fix seek --- src/melt/melt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index ee7747f29..9f3c51665 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -85,6 +85,10 @@ static void transport_action( mlt_producer producer, char *value ) jit_status.playing = 0; break; case CONTROL_TYPE__PLAY: + FILE *f1 = fopen("/tmp/moff.log", "a"); + fprintf(f1, "play\n"); + fclose(f1); + //if ( !jack || mlt_producer_get_speed( producer ) != 0 ) mlt_producer_set_speed( producer, 1 ); mlt_consumer_purge( consumer ); @@ -100,8 +104,9 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, jit_control->seek->position ); - //fire_jack_seek_event(jack, position); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + fire_jack_seek_event(jack, jit_control->seek->position); + jit_status.playing = 0; break; case CONTROL_TYPE__QUIT: mlt_properties_set_int( properties, "done", 1 ); From 5ec99f02e61db2712679f359462dc928a33680ec Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 14:56:38 +0200 Subject: [PATCH 010/130] refresh --- src/melt/melt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 9f3c51665..d1136401e 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -100,13 +100,13 @@ static void transport_action( mlt_producer producer, char *value ) fprintf(f, "seek: %d\n", (int) jit_control->seek->position); fclose(f); - //mlt_position len = mlt_producer_get_length(producer); mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, jit_control->seek->position ); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); fire_jack_seek_event(jack, jit_control->seek->position); jit_status.playing = 0; + break; case CONTROL_TYPE__QUIT: mlt_properties_set_int( properties, "done", 1 ); @@ -115,6 +115,7 @@ static void transport_action( mlt_producer producer, char *value ) default: break; } + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); /* if ( strlen( value ) == 1 ) From 6a943349c01d6f7eb77054fafa3b865feb554561 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 15:27:53 +0200 Subject: [PATCH 011/130] fix seek --- src/melt/melt.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index d1136401e..fda7d7ec9 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -76,8 +76,11 @@ static void transport_action( mlt_producer producer, char *value ) mlt_properties_set_int( properties, "stats_off", 1 ); JitControl *const jit_control = (JitControl*) value; + FILE *f = fopen("/tmp/moff.log", "a"); switch (jit_control->type) { case CONTROL_TYPE__PAUSE: + fprintf(f, "pause\n"); + mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); @@ -85,36 +88,37 @@ static void transport_action( mlt_producer producer, char *value ) jit_status.playing = 0; break; case CONTROL_TYPE__PLAY: - FILE *f1 = fopen("/tmp/moff.log", "a"); - fprintf(f1, "play\n"); - fclose(f1); + fprintf(f, "play\n"); - //if ( !jack || mlt_producer_get_speed( producer ) != 0 ) - mlt_producer_set_speed( producer, 1 ); + if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { + mlt_producer_set_speed( producer, 1 ); + } mlt_consumer_purge( consumer ); mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); jit_status.playing = 1; break; case CONTROL_TYPE__SEEK: - FILE *f = fopen("/tmp/moff.log", "a"); fprintf(f, "seek: %d\n", (int) jit_control->seek->position); - fclose(f); - mlt_producer_set_speed( producer, 0 ); + //mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, jit_control->seek->position ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + //mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); fire_jack_seek_event(jack, jit_control->seek->position); - jit_status.playing = 0; + //jit_status.playing = 0; break; case CONTROL_TYPE__QUIT: + fprintf(f, "quit\n"); + mlt_properties_set_int( properties, "done", 1 ); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); break; default: + fprintf(f, "argh!\n"); break; } + fclose(f); mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); /* From 163b97677bed9c5b95073253c2c99cdd0bf11696 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 15:42:37 +0200 Subject: [PATCH 012/130] seek to 0 --- src/melt/melt.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index fda7d7ec9..3993f7029 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -100,13 +100,9 @@ static void transport_action( mlt_producer producer, char *value ) case CONTROL_TYPE__SEEK: fprintf(f, "seek: %d\n", (int) jit_control->seek->position); - //mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, jit_control->seek->position ); - //mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - fire_jack_seek_event(jack, jit_control->seek->position); - //jit_status.playing = 0; - + mlt_producer_seek( producer, 0 /* jit_control->seek->position */); + fire_jack_seek_event(jack, 0 /* jit_control->seek->position */); break; case CONTROL_TYPE__QUIT: fprintf(f, "quit\n"); From f28d70ad2798b86bbee58e3f65ade4bb30f74731 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 15:51:14 +0200 Subject: [PATCH 013/130] fix --- src/melt/melt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 3993f7029..dd7152410 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -101,8 +101,8 @@ static void transport_action( mlt_producer producer, char *value ) fprintf(f, "seek: %d\n", (int) jit_control->seek->position); mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, 0 /* jit_control->seek->position */); - fire_jack_seek_event(jack, 0 /* jit_control->seek->position */); + mlt_producer_seek( producer, jit_control->seek->position); + fire_jack_seek_event(jack, jit_control->seek->position); break; case CONTROL_TYPE__QUIT: fprintf(f, "quit\n"); From d14bf6699075b5466aa12e5f2c7a2e43b7a8e189 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 16:08:59 +0200 Subject: [PATCH 014/130] moar logging --- src/melt/melt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index dd7152410..03ebe17ea 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -402,8 +402,9 @@ static int load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc, qglsl = 1; #if SDL_MAJOR_VERSION == 2 if ( !strcmp("sdl", argv[i]) || !strcmp("sdl_audio", argv[i]) || !strcmp("sdl_preview", argv[i]) || !strcmp("sdl_still", argv[i]) ) { + /* fprintf(stderr, -"Error: This program was linked against SDL2, which is incompatible with\nSDL1 consumers. Aborting.\n"); +"Error: This program was linked against SDL2, which is incompatible with\nSDL1 consumers. Aborting.\n");*/ return EXIT_FAILURE; } #endif @@ -548,6 +549,12 @@ static void write_status(JitStatus *const jit_status) { static int buf_len = 0; int len = jit_status__get_packed_size(jit_status) + 4; + if (len < 5) { + FILE *f = fopen("/tmp/moff.log", "a"); + fprintf(f, "Vafan? %d\n", len); + fclose(f); + exit(7); + } if (buf_len < len) { buf = realloc(buf, len); if (!buf) { @@ -1273,7 +1280,7 @@ int main( int argc, char **argv ) } else if ( store != NULL && store != stdout && name != NULL ) { - fprintf( stderr, "Project saved as %s.\n", name ); + //fprintf( stderr, "Project saved as %s.\n", name ); fclose( store ); } } From 1e47d18f86d5c1a625a77fa64eaadbbd638382ab Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 16:11:12 +0200 Subject: [PATCH 015/130] don't exit --- src/melt/melt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 03ebe17ea..fc6fb9ef7 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -553,7 +553,6 @@ static void write_status(JitStatus *const jit_status) { FILE *f = fopen("/tmp/moff.log", "a"); fprintf(f, "Vafan? %d\n", len); fclose(f); - exit(7); } if (buf_len < len) { buf = realloc(buf, len); From 7a0d82183a8c08aaf93159018df6071b855cec8f Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 16:42:14 +0200 Subject: [PATCH 016/130] don't advance one frame --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index fc6fb9ef7..0410ebd09 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -83,7 +83,7 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + //mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); jit_status.playing = 0; break; From 6b2926929de19b2cccea0397731326418795a0a5 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 16:47:38 +0200 Subject: [PATCH 017/130] better pause --- src/melt/melt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 0410ebd09..110848c5f 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -83,7 +83,9 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); - //mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + if (jit_status.playing) { + mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + } mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); jit_status.playing = 0; break; From 8d59634d44d8cc3c89208f05d512bd5a6276e53e Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 16:59:23 +0200 Subject: [PATCH 018/130] implement playback rate --- src/melt/JitControl.pb-c.c | 128 +++++++++---------------------------- src/melt/JitControl.pb-c.h | 44 ++----------- src/melt/JitControl.proto | 10 ++- src/melt/melt.c | 14 ++-- 4 files changed, 50 insertions(+), 146 deletions(-) diff --git a/src/melt/JitControl.pb-c.c b/src/melt/JitControl.pb-c.c index b741bc4d0..e64269ac9 100644 --- a/src/melt/JitControl.pb-c.c +++ b/src/melt/JitControl.pb-c.c @@ -52,52 +52,7 @@ void jit_control__free_unpacked assert(message->base.descriptor == &jit_control__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void seek_control__init - (SeekControl *message) -{ - static const SeekControl init_value = SEEK_CONTROL__INIT; - *message = init_value; -} -size_t seek_control__get_packed_size - (const SeekControl *message) -{ - assert(message->base.descriptor == &seek_control__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t seek_control__pack - (const SeekControl *message, - uint8_t *out) -{ - assert(message->base.descriptor == &seek_control__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t seek_control__pack_to_buffer - (const SeekControl *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &seek_control__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -SeekControl * - seek_control__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (SeekControl *) - protobuf_c_message_unpack (&seek_control__descriptor, - allocator, len, data); -} -void seek_control__free_unpacked - (SeekControl *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &seek_control__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -static const ProtobufCFieldDescriptor jit_control__field_descriptors[2] = +static const ProtobufCFieldDescriptor jit_control__field_descriptors[3] = { { "type", @@ -112,26 +67,39 @@ static const ProtobufCFieldDescriptor jit_control__field_descriptors[2] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "seek", + "play_rate", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_MESSAGE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(JitControl, play_rate), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "seek_position", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, 0, /* quantifier_offset */ - offsetof(JitControl, seek), - &seek_control__descriptor, + offsetof(JitControl, seek_position), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; static const unsigned jit_control__field_indices_by_name[] = { - 1, /* field[1] = seek */ + 1, /* field[1] = play_rate */ + 2, /* field[2] = seek_position */ 0, /* field[0] = type */ }; static const ProtobufCIntRange jit_control__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 3 } }; const ProtobufCMessageDescriptor jit_control__descriptor = { @@ -141,67 +109,31 @@ const ProtobufCMessageDescriptor jit_control__descriptor = "JitControl", "", sizeof(JitControl), - 2, + 3, jit_control__field_descriptors, jit_control__field_indices_by_name, 1, jit_control__number_ranges, (ProtobufCMessageInit) jit_control__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor seek_control__field_descriptors[1] = -{ - { - "position", - 1, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT64, - 0, /* quantifier_offset */ - offsetof(SeekControl, position), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned seek_control__field_indices_by_name[] = { - 0, /* field[0] = position */ -}; -static const ProtobufCIntRange seek_control__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor seek_control__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "SeekControl", - "SeekControl", - "SeekControl", - "", - sizeof(SeekControl), - 1, - seek_control__field_descriptors, - seek_control__field_indices_by_name, - 1, seek_control__number_ranges, - (ProtobufCMessageInit) seek_control__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCEnumValue control_type__enum_values_by_number[4] = +static const ProtobufCEnumValue control_type__enum_values_by_number[5] = { { "PAUSE", "CONTROL_TYPE__PAUSE", 0 }, { "PLAY", "CONTROL_TYPE__PLAY", 1 }, - { "SEEK", "CONTROL_TYPE__SEEK", 2 }, + { "PLAY_RATE", "CONTROL_TYPE__PLAY_RATE", 2 }, { "QUIT", "CONTROL_TYPE__QUIT", 3 }, + { "SEEK", "CONTROL_TYPE__SEEK", 4 }, }; static const ProtobufCIntRange control_type__value_ranges[] = { -{0, 0},{0, 4} +{0, 0},{0, 5} }; -static const ProtobufCEnumValueIndex control_type__enum_values_by_name[4] = +static const ProtobufCEnumValueIndex control_type__enum_values_by_name[5] = { { "PAUSE", 0 }, { "PLAY", 1 }, + { "PLAY_RATE", 2 }, { "QUIT", 3 }, - { "SEEK", 2 }, + { "SEEK", 4 }, }; const ProtobufCEnumDescriptor control_type__descriptor = { @@ -210,9 +142,9 @@ const ProtobufCEnumDescriptor control_type__descriptor = "ControlType", "ControlType", "", - 4, + 5, control_type__enum_values_by_number, - 4, + 5, control_type__enum_values_by_name, 1, control_type__value_ranges, diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h index 5357773e7..fefa73996 100644 --- a/src/melt/JitControl.pb-c.h +++ b/src/melt/JitControl.pb-c.h @@ -16,7 +16,6 @@ PROTOBUF_C__BEGIN_DECLS typedef struct _JitControl JitControl; -typedef struct _SeekControl SeekControl; /* --- enums --- */ @@ -24,8 +23,9 @@ typedef struct _SeekControl SeekControl; typedef enum _ControlType { CONTROL_TYPE__PAUSE = 0, CONTROL_TYPE__PLAY = 1, - CONTROL_TYPE__SEEK = 2, - CONTROL_TYPE__QUIT = 3 + CONTROL_TYPE__PLAY_RATE = 2, + CONTROL_TYPE__QUIT = 3, + CONTROL_TYPE__SEEK = 4 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(CONTROL_TYPE) } ControlType; @@ -35,21 +35,12 @@ struct _JitControl { ProtobufCMessage base; ControlType type; - SeekControl *seek; + int32_t play_rate; + int64_t seek_position; }; #define JIT_CONTROL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_control__descriptor) \ - , CONTROL_TYPE__PAUSE, NULL } - - -struct _SeekControl -{ - ProtobufCMessage base; - int64_t position; -}; -#define SEEK_CONTROL__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&seek_control__descriptor) \ - , 0 } + , CONTROL_TYPE__PAUSE, 0, 0 } /* JitControl methods */ @@ -71,33 +62,11 @@ JitControl * void jit_control__free_unpacked (JitControl *message, ProtobufCAllocator *allocator); -/* SeekControl methods */ -void seek_control__init - (SeekControl *message); -size_t seek_control__get_packed_size - (const SeekControl *message); -size_t seek_control__pack - (const SeekControl *message, - uint8_t *out); -size_t seek_control__pack_to_buffer - (const SeekControl *message, - ProtobufCBuffer *buffer); -SeekControl * - seek_control__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void seek_control__free_unpacked - (SeekControl *message, - ProtobufCAllocator *allocator); /* --- per-message closures --- */ typedef void (*JitControl_Closure) (const JitControl *message, void *closure_data); -typedef void (*SeekControl_Closure) - (const SeekControl *message, - void *closure_data); /* --- services --- */ @@ -106,7 +75,6 @@ typedef void (*SeekControl_Closure) extern const ProtobufCEnumDescriptor control_type__descriptor; extern const ProtobufCMessageDescriptor jit_control__descriptor; -extern const ProtobufCMessageDescriptor seek_control__descriptor; PROTOBUF_C__END_DECLS diff --git a/src/melt/JitControl.proto b/src/melt/JitControl.proto index 22dd7e05b..c68199b95 100644 --- a/src/melt/JitControl.proto +++ b/src/melt/JitControl.proto @@ -2,16 +2,14 @@ syntax = "proto3"; message JitControl { ControlType type = 1; - SeekControl seek = 2; -} - -message SeekControl { - int64 position = 1; + int32 play_rate = 2; + int64 seek_position = 3; } enum ControlType { PAUSE = 0; PLAY = 1; - SEEK = 2; + PLAY_RATE = 2; QUIT = 3; + SEEK = 4; } diff --git a/src/melt/melt.c b/src/melt/melt.c index 110848c5f..b807b9a02 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -93,18 +93,24 @@ static void transport_action( mlt_producer producer, char *value ) fprintf(f, "play\n"); if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { - mlt_producer_set_speed( producer, 1 ); + mlt_producer_set_speed( producer, jit_control->play_rate ); } mlt_consumer_purge( consumer ); mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); jit_status.playing = 1; break; + + case CONTROL_TYPE__PLAY_RATE: + fprintf(f, "play rate %d\n", jit_control->play_rate); + mlt_producer_set_speed( producer, jit_control->play_rate ); + break; + case CONTROL_TYPE__SEEK: - fprintf(f, "seek: %d\n", (int) jit_control->seek->position); + fprintf(f, "seek: %d\n", (int) jit_control->seek_position); mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, jit_control->seek->position); - fire_jack_seek_event(jack, jit_control->seek->position); + mlt_producer_seek( producer, jit_control->seek_position); + fire_jack_seek_event(jack, jit_control->seek_position); break; case CONTROL_TYPE__QUIT: fprintf(f, "quit\n"); From a5dd531879826378b0394d3b3cb7f13a73405e32 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 29 Mar 2022 17:39:22 +0200 Subject: [PATCH 019/130] send fps and duration --- src/melt/JitStatus.pb-c.c | 56 ++++++++++++++++++++++++++++----------- src/melt/JitStatus.pb-c.h | 8 +++--- src/melt/JitStatus.proto | 10 ++++--- src/melt/melt.c | 5 +++- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index 77e4e2103..a2689f743 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -187,24 +187,36 @@ void audio_stream__free_unpacked assert(message->base.descriptor == &audio_stream__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -static const ProtobufCFieldDescriptor jit_status__field_descriptors[4] = +static const ProtobufCFieldDescriptor jit_status__field_descriptors[6] = { { - "position", + "duration", 1, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT64, 0, /* quantifier_offset */ - offsetof(JitStatus, position), + offsetof(JitStatus, duration), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "playing", + "frame_rate", 2, PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(JitStatus, frame_rate), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "playing", + 3, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_BOOL, 0, /* quantifier_offset */ offsetof(JitStatus, playing), @@ -214,12 +226,24 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[4] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "playback_rate", - 3, + "play_rate", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(JitStatus, play_rate), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "position", + 5, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_FLOAT, + PROTOBUF_C_TYPE_INT64, 0, /* quantifier_offset */ - offsetof(JitStatus, playback_rate), + offsetof(JitStatus, position), NULL, NULL, 0, /* flags */ @@ -227,7 +251,7 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[4] = }, { "mediaInfo", - 4, + 6, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ @@ -239,15 +263,17 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[4] = }, }; static const unsigned jit_status__field_indices_by_name[] = { - 3, /* field[3] = mediaInfo */ - 2, /* field[2] = playback_rate */ - 1, /* field[1] = playing */ - 0, /* field[0] = position */ + 0, /* field[0] = duration */ + 1, /* field[1] = frame_rate */ + 5, /* field[5] = mediaInfo */ + 3, /* field[3] = play_rate */ + 2, /* field[2] = playing */ + 4, /* field[4] = position */ }; static const ProtobufCIntRange jit_status__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 4 } + { 0, 6 } }; const ProtobufCMessageDescriptor jit_status__descriptor = { @@ -257,7 +283,7 @@ const ProtobufCMessageDescriptor jit_status__descriptor = "JitStatus", "", sizeof(JitStatus), - 4, + 6, jit_status__field_descriptors, jit_status__field_indices_by_name, 1, jit_status__number_ranges, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 7e388bd75..97f1e22bc 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -35,14 +35,16 @@ typedef enum _StreamType { struct _JitStatus { ProtobufCMessage base; - int64_t position; + int64_t duration; + double frame_rate; protobuf_c_boolean playing; - float playback_rate; + int32_t play_rate; + int64_t position; MediaInfo *mediainfo; }; #define JIT_STATUS__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ - , 0, 0, 0, NULL } + , 0, 0, 0, 0, 0, NULL } struct _MediaInfo diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index ffb6a5f8a..b6fabaa44 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -1,10 +1,12 @@ syntax = "proto3"; message JitStatus { - int64 position = 1; - bool playing = 2; - float playback_rate = 3; - MediaInfo mediaInfo = 4; + int64 duration = 1; + double frame_rate = 2; + bool playing = 3; + int32 play_rate = 4; + int64 position = 5; + MediaInfo mediaInfo = 6; } message MediaInfo { diff --git a/src/melt/melt.c b/src/melt/melt.c index b807b9a02..9fea64a6a 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -688,7 +688,10 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) fflush( stderr ); */ // MOFF - jit_status.position = mlt_producer_position( producer ); + jit_status.duration = mlt_producer_get_length(producer); + jit_status.frame_rate = mlt_producer_get_fps(producer); + jit_status.position = mlt_producer_position(producer); + write_status(&jit_status); last_position = jit_status.position; } From 270d2ea94894154a77604a2dfa83b79b5e9f1187 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 30 Mar 2022 11:25:47 +0200 Subject: [PATCH 020/130] set playback speed in status --- src/melt/melt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index 9fea64a6a..23cf04272 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -690,6 +690,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) // MOFF jit_status.duration = mlt_producer_get_length(producer); jit_status.frame_rate = mlt_producer_get_fps(producer); + jit_status.play_rate = mlt_producer_get_speed(producer); jit_status.position = mlt_producer_position(producer); write_status(&jit_status); From 8ace2a9fc3829c24d569dcd0bd0b04f5a4a3f2d2 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 14:32:13 +0200 Subject: [PATCH 021/130] set total_channels --- src/melt/JitStatus.pb-c.c | 23 ++++++++++++++++++----- src/melt/JitStatus.pb-c.h | 3 ++- src/melt/JitStatus.proto | 3 ++- src/melt/melt.c | 35 ++++++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index a2689f743..e970aff37 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -187,7 +187,7 @@ void audio_stream__free_unpacked assert(message->base.descriptor == &audio_stream__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -static const ProtobufCFieldDescriptor jit_status__field_descriptors[6] = +static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { { "duration", @@ -250,9 +250,21 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[6] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mediaInfo", + "total_channels", 6, PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(JitStatus, total_channels), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mediaInfo", + 7, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ offsetof(JitStatus, mediainfo), @@ -265,15 +277,16 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[6] = static const unsigned jit_status__field_indices_by_name[] = { 0, /* field[0] = duration */ 1, /* field[1] = frame_rate */ - 5, /* field[5] = mediaInfo */ + 6, /* field[6] = mediaInfo */ 3, /* field[3] = play_rate */ 2, /* field[2] = playing */ 4, /* field[4] = position */ + 5, /* field[5] = total_channels */ }; static const ProtobufCIntRange jit_status__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 6 } + { 0, 7 } }; const ProtobufCMessageDescriptor jit_status__descriptor = { @@ -283,7 +296,7 @@ const ProtobufCMessageDescriptor jit_status__descriptor = "JitStatus", "", sizeof(JitStatus), - 6, + 7, jit_status__field_descriptors, jit_status__field_indices_by_name, 1, jit_status__number_ranges, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 97f1e22bc..0f4991e37 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -40,11 +40,12 @@ struct _JitStatus protobuf_c_boolean playing; int32_t play_rate; int64_t position; + int32_t total_channels; MediaInfo *mediainfo; }; #define JIT_STATUS__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ - , 0, 0, 0, 0, 0, NULL } + , 0, 0, 0, 0, 0, 0, NULL } struct _MediaInfo diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index b6fabaa44..d1edb2d29 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -6,7 +6,8 @@ message JitStatus { bool playing = 3; int32 play_rate = 4; int64 position = 5; - MediaInfo mediaInfo = 6; + int32 total_channels = 6; + MediaInfo mediaInfo = 7; } message MediaInfo { diff --git a/src/melt/melt.c b/src/melt/melt.c index 23cf04272..0bc157f7e 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -966,6 +966,22 @@ static void set_preview_scale(mlt_profile *profile, mlt_profile *backup_profile, } } +static mlt_producer find_producer_avformat(mlt_producer p) { + + mlt_tractor tractor = (mlt_tractor) p; + mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); + mlt_playlist playlist = mlt_multitrack_track(multitrack, 0); + mlt_producer clip = mlt_playlist_get_clip(playlist, 0); + return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); +} + +static void dump_properties(mlt_properties p) { + for (int i = 0; i < mlt_properties_count(p); i++) { + char *name = mlt_properties_get_name(p, i); + printf("%s\n", name); + } +} + int main( int argc, char **argv ) { int i; @@ -1200,7 +1216,24 @@ int main( int argc, char **argv ) if ( store == NULL && consumer == NULL ) consumer = create_consumer( profile, NULL ); } - + + // media info + mlt_producer av = find_producer_avformat(melt); + int nb_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); + for (int i = 0; i < nb_streams; i++) { + char key[100]; + sprintf(key, "meta.media.%d.stream.type", i); + char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (!value) { + continue; + } else if (!strcmp(value, "audio")) { + sprintf(key, "meta.media.%d.codec.channels", i); + jit_status.total_channels += mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + } + } + //dump_properties(av); + //exit(1); + // Set transport properties on consumer and produder if ( consumer != NULL && melt != NULL ) { From d01b322db3642c8b71fb67a0cce44caa1ddae2b6 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 16:24:41 +0200 Subject: [PATCH 022/130] add media tracks --- src/melt/JitStatus.pb-c.c | 121 ++++++++++++++++++++++++++++++++++++-- src/melt/JitStatus.pb-c.h | 38 +++++++++++- src/melt/JitStatus.proto | 6 ++ src/melt/melt.c | 27 ++++++--- 4 files changed, 177 insertions(+), 15 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index e970aff37..d9de9cba7 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -187,6 +187,51 @@ void audio_stream__free_unpacked assert(message->base.descriptor == &audio_stream__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void video_stream__init + (VideoStream *message) +{ + static const VideoStream init_value = VIDEO_STREAM__INIT; + *message = init_value; +} +size_t video_stream__get_packed_size + (const VideoStream *message) +{ + assert(message->base.descriptor == &video_stream__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t video_stream__pack + (const VideoStream *message, + uint8_t *out) +{ + assert(message->base.descriptor == &video_stream__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t video_stream__pack_to_buffer + (const VideoStream *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &video_stream__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +VideoStream * + video_stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (VideoStream *) + protobuf_c_message_unpack (&video_stream__descriptor, + allocator, len, data); +} +void video_stream__free_unpacked + (VideoStream *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &video_stream__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { { @@ -341,7 +386,7 @@ const ProtobufCMessageDescriptor media_info__descriptor = (ProtobufCMessageInit) media_info__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor stream__field_descriptors[2] = +static const ProtobufCFieldDescriptor stream__field_descriptors[3] = { { "type", @@ -367,15 +412,28 @@ static const ProtobufCFieldDescriptor stream__field_descriptors[2] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "video", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Stream, video), + &video_stream__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned stream__field_indices_by_name[] = { 1, /* field[1] = audio */ 0, /* field[0] = type */ + 2, /* field[2] = video */ }; static const ProtobufCIntRange stream__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 3 } }; const ProtobufCMessageDescriptor stream__descriptor = { @@ -385,14 +443,14 @@ const ProtobufCMessageDescriptor stream__descriptor = "Stream", "", sizeof(Stream), - 2, + 3, stream__field_descriptors, stream__field_indices_by_name, 1, stream__number_ranges, (ProtobufCMessageInit) stream__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor audio_stream__field_descriptors[1] = +static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = { { "channels", @@ -406,14 +464,27 @@ static const ProtobufCFieldDescriptor audio_stream__field_descriptors[1] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "language", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(AudioStream, language), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned audio_stream__field_indices_by_name[] = { 0, /* field[0] = channels */ + 1, /* field[1] = language */ }; static const ProtobufCIntRange audio_stream__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 1 } + { 0, 2 } }; const ProtobufCMessageDescriptor audio_stream__descriptor = { @@ -423,13 +494,51 @@ const ProtobufCMessageDescriptor audio_stream__descriptor = "AudioStream", "", sizeof(AudioStream), - 1, + 2, audio_stream__field_descriptors, audio_stream__field_indices_by_name, 1, audio_stream__number_ranges, (ProtobufCMessageInit) audio_stream__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor video_stream__field_descriptors[1] = +{ + { + "frame_rate", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(VideoStream, frame_rate), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned video_stream__field_indices_by_name[] = { + 0, /* field[0] = frame_rate */ +}; +static const ProtobufCIntRange video_stream__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor video_stream__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "VideoStream", + "VideoStream", + "VideoStream", + "", + sizeof(VideoStream), + 1, + video_stream__field_descriptors, + video_stream__field_indices_by_name, + 1, video_stream__number_ranges, + (ProtobufCMessageInit) video_stream__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCEnumValue stream_type__enum_values_by_number[3] = { { "UNKNOWN", "STREAM_TYPE__UNKNOWN", 0 }, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 0f4991e37..60dfad184 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -19,6 +19,7 @@ typedef struct _JitStatus JitStatus; typedef struct _MediaInfo MediaInfo; typedef struct _Stream Stream; typedef struct _AudioStream AudioStream; +typedef struct _VideoStream VideoStream; /* --- enums --- */ @@ -64,19 +65,31 @@ struct _Stream ProtobufCMessage base; StreamType type; AudioStream *audio; + VideoStream *video; }; #define STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ - , STREAM_TYPE__UNKNOWN, NULL } + , STREAM_TYPE__UNKNOWN, NULL, NULL } struct _AudioStream { ProtobufCMessage base; int32_t channels; + char *language; }; #define AUDIO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ + , 0, (char *)protobuf_c_empty_string } + + +struct _VideoStream +{ + ProtobufCMessage base; + double frame_rate; +}; +#define VIDEO_STREAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&video_stream__descriptor) \ , 0 } @@ -156,6 +169,25 @@ AudioStream * void audio_stream__free_unpacked (AudioStream *message, ProtobufCAllocator *allocator); +/* VideoStream methods */ +void video_stream__init + (VideoStream *message); +size_t video_stream__get_packed_size + (const VideoStream *message); +size_t video_stream__pack + (const VideoStream *message, + uint8_t *out); +size_t video_stream__pack_to_buffer + (const VideoStream *message, + ProtobufCBuffer *buffer); +VideoStream * + video_stream__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void video_stream__free_unpacked + (VideoStream *message, + ProtobufCAllocator *allocator); /* --- per-message closures --- */ typedef void (*JitStatus_Closure) @@ -170,6 +202,9 @@ typedef void (*Stream_Closure) typedef void (*AudioStream_Closure) (const AudioStream *message, void *closure_data); +typedef void (*VideoStream_Closure) + (const VideoStream *message, + void *closure_data); /* --- services --- */ @@ -181,6 +216,7 @@ extern const ProtobufCMessageDescriptor jit_status__descriptor; extern const ProtobufCMessageDescriptor media_info__descriptor; extern const ProtobufCMessageDescriptor stream__descriptor; extern const ProtobufCMessageDescriptor audio_stream__descriptor; +extern const ProtobufCMessageDescriptor video_stream__descriptor; PROTOBUF_C__END_DECLS diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index d1edb2d29..8a5b37f8a 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -17,10 +17,16 @@ message MediaInfo { message Stream { StreamType type = 1; AudioStream audio = 2; + VideoStream video = 3; } message AudioStream { int32 channels = 1; + string language = 2; +} + +message VideoStream { + double frame_rate = 1; } enum StreamType { diff --git a/src/melt/melt.c b/src/melt/melt.c index 0bc157f7e..d1ee08ddf 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -968,11 +968,11 @@ static void set_preview_scale(mlt_profile *profile, mlt_profile *backup_profile, static mlt_producer find_producer_avformat(mlt_producer p) { - mlt_tractor tractor = (mlt_tractor) p; - mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); - mlt_playlist playlist = mlt_multitrack_track(multitrack, 0); - mlt_producer clip = mlt_playlist_get_clip(playlist, 0); - return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); + mlt_tractor tractor = (mlt_tractor) p; + mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); + mlt_playlist playlist = mlt_multitrack_track(multitrack, 0); + mlt_producer clip = mlt_playlist_get_clip(playlist, 0); + return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); } static void dump_properties(mlt_properties p) { @@ -1219,16 +1219,27 @@ int main( int argc, char **argv ) // media info mlt_producer av = find_producer_avformat(melt); - int nb_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); - for (int i = 0; i < nb_streams; i++) { + jit_status.mediainfo = calloc(sizeof *jit_status.mediainfo, 1); + jit_status.mediainfo->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); + jit_status.mediainfo->streams = calloc(sizeof *jit_status.mediainfo->streams, jit_status.mediainfo->n_streams); + Stream *s = jit_status.mediainfo->streams; + for (int i = 0; i < jit_status.mediainfo->n_streams; i++) { + s[i].type = STREAM_TYPE__UNKNOWN; char key[100]; sprintf(key, "meta.media.%d.stream.type", i); char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); if (!value) { continue; } else if (!strcmp(value, "audio")) { + s[i].type = STREAM_TYPE__AUDIO; + s[i].audio = calloc(sizeof *s[i].audio, 1); sprintf(key, "meta.media.%d.codec.channels", i); - jit_status.total_channels += mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + s[i].audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + jit_status.total_channels += s[i].audio->channels; + sprintf(key, "meta.attr.%d.stream.language.markup", i); + s[i].audio->language = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + } else if (!strcmp(value, "video")) { + s[i].type = STREAM_TYPE__VIDEO; } } //dump_properties(av); From ad10b25a138df0683888e90e4ad8c4273d9f8fb2 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 17:01:09 +0200 Subject: [PATCH 023/130] FGIX --- src/melt/melt.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index d1ee08ddf..6bb37ab67 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1219,27 +1219,31 @@ int main( int argc, char **argv ) // media info mlt_producer av = find_producer_avformat(melt); - jit_status.mediainfo = calloc(sizeof *jit_status.mediainfo, 1); + jit_status.mediainfo = calloc(1, sizeof (MediaInfo)); + media_info__init(jit_status.mediainfo); jit_status.mediainfo->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); - jit_status.mediainfo->streams = calloc(sizeof *jit_status.mediainfo->streams, jit_status.mediainfo->n_streams); - Stream *s = jit_status.mediainfo->streams; + jit_status.mediainfo->streams = calloc(jit_status.mediainfo->n_streams, sizeof (Stream*)); for (int i = 0; i < jit_status.mediainfo->n_streams; i++) { - s[i].type = STREAM_TYPE__UNKNOWN; + Stream *s = calloc(sizeof (Stream), 1); + stream__init(s); + jit_status.mediainfo->streams[i] = s; + s->type = STREAM_TYPE__UNKNOWN; char key[100]; sprintf(key, "meta.media.%d.stream.type", i); char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); if (!value) { continue; } else if (!strcmp(value, "audio")) { - s[i].type = STREAM_TYPE__AUDIO; - s[i].audio = calloc(sizeof *s[i].audio, 1); + s->type = STREAM_TYPE__AUDIO; + s->audio = calloc(1, sizeof (AudioStream)); + audio_stream__init(s->audio); sprintf(key, "meta.media.%d.codec.channels", i); - s[i].audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - jit_status.total_channels += s[i].audio->channels; + s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + jit_status.total_channels += s->audio->channels; sprintf(key, "meta.attr.%d.stream.language.markup", i); - s[i].audio->language = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + s->audio->language = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); } else if (!strcmp(value, "video")) { - s[i].type = STREAM_TYPE__VIDEO; + s->type = STREAM_TYPE__VIDEO; } } //dump_properties(av); From b63957ecdf57b4f98e497027c51026d94c14c32d Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 17:11:31 +0200 Subject: [PATCH 024/130] bytes instead of char --- src/melt/JitStatus.pb-c.c | 4 ++-- src/melt/JitStatus.pb-c.h | 4 ++-- src/melt/JitStatus.proto | 2 +- src/melt/melt.c | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index d9de9cba7..43271462f 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -468,11 +468,11 @@ static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = "language", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_BYTES, 0, /* quantifier_offset */ offsetof(AudioStream, language), NULL, - &protobuf_c_empty_string, + NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 60dfad184..607e32a34 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -76,11 +76,11 @@ struct _AudioStream { ProtobufCMessage base; int32_t channels; - char *language; + ProtobufCBinaryData language; }; #define AUDIO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ - , 0, (char *)protobuf_c_empty_string } + , 0, {0,NULL} } struct _VideoStream diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index 8a5b37f8a..b65809222 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -22,7 +22,7 @@ message Stream { message AudioStream { int32 channels = 1; - string language = 2; + bytes language = 2; } message VideoStream { diff --git a/src/melt/melt.c b/src/melt/melt.c index 6bb37ab67..4e18a0494 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1241,7 +1241,8 @@ int main( int argc, char **argv ) s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); jit_status.total_channels += s->audio->channels; sprintf(key, "meta.attr.%d.stream.language.markup", i); - s->audio->language = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + s->audio->language.data = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + s->audio->language.len = strlen(s->audio->language.data); } else if (!strcmp(value, "video")) { s->type = STREAM_TYPE__VIDEO; } From 15ffa180754da8af53f4a928e287e5b35f9f780b Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 17:26:53 +0200 Subject: [PATCH 025/130] bugfix --- src/melt/melt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 4e18a0494..11440a6e5 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1241,8 +1241,12 @@ int main( int argc, char **argv ) s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); jit_status.total_channels += s->audio->channels; sprintf(key, "meta.attr.%d.stream.language.markup", i); - s->audio->language.data = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); - s->audio->language.len = strlen(s->audio->language.data); + value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (value) { + s->audio->language.len = strlen(value); + s->audio->language.data = calloc(1, s->audio->language.len + 1); + strcpy(s->audio->language.data, value); + } } else if (!strcmp(value, "video")) { s->type = STREAM_TYPE__VIDEO; } From ec893d2372e25177a81de0aef3699242a278e1f5 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 1 Apr 2022 17:28:17 +0200 Subject: [PATCH 026/130] fix compile error --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 11440a6e5..3a8938700 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -970,7 +970,7 @@ static mlt_producer find_producer_avformat(mlt_producer p) { mlt_tractor tractor = (mlt_tractor) p; mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); - mlt_playlist playlist = mlt_multitrack_track(multitrack, 0); + mlt_playlist playlist = (mlt_playlist) mlt_multitrack_track(multitrack, 0); mlt_producer clip = mlt_playlist_get_clip(playlist, 0); return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); } From a5ada6732c841de6b5e22fe7948e10041f9211ff Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 4 Apr 2022 15:40:30 +0200 Subject: [PATCH 027/130] set playing state --- src/melt/melt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index 3a8938700..6252b8d5d 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1217,6 +1217,9 @@ int main( int argc, char **argv ) consumer = create_consumer( profile, NULL ); } + // video plays automatically + jit_status.playing = 1; + // media info mlt_producer av = find_producer_avformat(melt); jit_status.mediainfo = calloc(1, sizeof (MediaInfo)); From 05ae0887ad95e332d510d5b9160a5797f98ea08e Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 4 Apr 2022 15:49:38 +0200 Subject: [PATCH 028/130] rename variable --- src/melt/JitStatus.pb-c.c | 6 +++--- src/melt/JitStatus.pb-c.h | 2 +- src/melt/JitStatus.proto | 2 +- src/melt/melt.c | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index 43271462f..c8138adcc 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -307,12 +307,12 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mediaInfo", + "media_info", 7, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(JitStatus, mediainfo), + offsetof(JitStatus, media_info), &media_info__descriptor, NULL, 0, /* flags */ @@ -322,7 +322,7 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = static const unsigned jit_status__field_indices_by_name[] = { 0, /* field[0] = duration */ 1, /* field[1] = frame_rate */ - 6, /* field[6] = mediaInfo */ + 6, /* field[6] = media_info */ 3, /* field[3] = play_rate */ 2, /* field[2] = playing */ 4, /* field[4] = position */ diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 607e32a34..cc877c07c 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -42,7 +42,7 @@ struct _JitStatus int32_t play_rate; int64_t position; int32_t total_channels; - MediaInfo *mediainfo; + MediaInfo *media_info; }; #define JIT_STATUS__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index b65809222..fc2596a9e 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -7,7 +7,7 @@ message JitStatus { int32 play_rate = 4; int64 position = 5; int32 total_channels = 6; - MediaInfo mediaInfo = 7; + MediaInfo media_info = 7; } message MediaInfo { diff --git a/src/melt/melt.c b/src/melt/melt.c index 6252b8d5d..5a1cf2c83 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1222,14 +1222,14 @@ int main( int argc, char **argv ) // media info mlt_producer av = find_producer_avformat(melt); - jit_status.mediainfo = calloc(1, sizeof (MediaInfo)); - media_info__init(jit_status.mediainfo); - jit_status.mediainfo->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); - jit_status.mediainfo->streams = calloc(jit_status.mediainfo->n_streams, sizeof (Stream*)); - for (int i = 0; i < jit_status.mediainfo->n_streams; i++) { + jit_status.media_info = calloc(1, sizeof (MediaInfo)); + media_info__init(jit_status.media_info); + jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); + jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); + for (int i = 0; i < jit_status.media_info->n_streams; i++) { Stream *s = calloc(sizeof (Stream), 1); stream__init(s); - jit_status.mediainfo->streams[i] = s; + jit_status.media_info->streams[i] = s; s->type = STREAM_TYPE__UNKNOWN; char key[100]; sprintf(key, "meta.media.%d.stream.type", i); From 8e2a5c2e88a554b69f94a287cacaffab81c808c5 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 4 Apr 2022 16:17:19 +0200 Subject: [PATCH 029/130] bytes -> string --- src/melt/JitStatus.pb-c.c | 4 ++-- src/melt/JitStatus.pb-c.h | 4 ++-- src/melt/JitStatus.proto | 2 +- src/melt/melt.c | 8 +++++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index c8138adcc..b5ec252c1 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -468,11 +468,11 @@ static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = "language", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ offsetof(AudioStream, language), NULL, - NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index cc877c07c..d3ded65c0 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -76,11 +76,11 @@ struct _AudioStream { ProtobufCMessage base; int32_t channels; - ProtobufCBinaryData language; + char *language; }; #define AUDIO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ - , 0, {0,NULL} } + , 0, (char *)protobuf_c_empty_string } struct _VideoStream diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index fc2596a9e..9986c8b5c 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -22,7 +22,7 @@ message Stream { message AudioStream { int32 channels = 1; - bytes language = 2; + string language = 2; } message VideoStream { diff --git a/src/melt/melt.c b/src/melt/melt.c index 5a1cf2c83..1d1154ce1 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1246,9 +1246,11 @@ int main( int argc, char **argv ) sprintf(key, "meta.attr.%d.stream.language.markup", i); value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); if (value) { - s->audio->language.len = strlen(value); - s->audio->language.data = calloc(1, s->audio->language.len + 1); - strcpy(s->audio->language.data, value); + //int l = strlen(value); + //s->audio->language.len = l; + //s->audio->language.data = calloc(1, l + 1); + s->audio->language = strdup(value); + //strcpy(s->audio->language.data, value); } } else if (!strcmp(value, "video")) { s->type = STREAM_TYPE__VIDEO; From 50d297b9d1ee4f3c32fb3845e0fb3c9f0b55e780 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 5 Apr 2022 13:33:29 +0200 Subject: [PATCH 030/130] write status to named pipe --- src/melt/melt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 1d1154ce1..0aeb31859 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include @@ -555,6 +558,11 @@ static JitControl *read_control() { static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; + static int fd = -1; + + if (fd < 0) { + fd = open("/tmp/jit-status", O_WRONLY); + } int len = jit_status__get_packed_size(jit_status) + 4; if (len < 5) { @@ -574,7 +582,7 @@ static void write_status(JitStatus *const jit_status) { jit_status__pack(jit_status, b + 4); *((int*) b) = len - 4; while (len) { - const int w = write(STDERR_FILENO, b, len); + const int w = write(fd, b, len); if (w < 1) { exit(2); } From 06aa5ab0d36aa36013347b8e0b77eae8f07e87d4 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 12 Apr 2022 10:25:58 +0200 Subject: [PATCH 031/130] debug logging --- src/melt/melt.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 0aeb31859..2a09ba128 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -79,11 +79,8 @@ static void transport_action( mlt_producer producer, char *value ) mlt_properties_set_int( properties, "stats_off", 1 ); JitControl *const jit_control = (JitControl*) value; - FILE *f = fopen("/tmp/moff.log", "a"); switch (jit_control->type) { case CONTROL_TYPE__PAUSE: - fprintf(f, "pause\n"); - mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); if (jit_status.playing) { @@ -93,8 +90,6 @@ static void transport_action( mlt_producer producer, char *value ) jit_status.playing = 0; break; case CONTROL_TYPE__PLAY: - fprintf(f, "play\n"); - if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { mlt_producer_set_speed( producer, jit_control->play_rate ); } @@ -104,28 +99,21 @@ static void transport_action( mlt_producer producer, char *value ) break; case CONTROL_TYPE__PLAY_RATE: - fprintf(f, "play rate %d\n", jit_control->play_rate); mlt_producer_set_speed( producer, jit_control->play_rate ); break; case CONTROL_TYPE__SEEK: - fprintf(f, "seek: %d\n", (int) jit_control->seek_position); - mlt_consumer_purge( consumer ); mlt_producer_seek( producer, jit_control->seek_position); fire_jack_seek_event(jack, jit_control->seek_position); break; case CONTROL_TYPE__QUIT: - fprintf(f, "quit\n"); - mlt_properties_set_int( properties, "done", 1 ); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); break; default: - fprintf(f, "argh!\n"); break; } - fclose(f); mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); /* @@ -561,18 +549,20 @@ static void write_status(JitStatus *const jit_status) { static int fd = -1; if (fd < 0) { + printf("Opening status pipe\n"); fd = open("/tmp/jit-status", O_WRONLY); + if (fd < 0) { + perror("open"); + exit(2); + } + printf("Status pipe opened\n"); } int len = jit_status__get_packed_size(jit_status) + 4; - if (len < 5) { - FILE *f = fopen("/tmp/moff.log", "a"); - fprintf(f, "Vafan? %d\n", len); - fclose(f); - } if (buf_len < len) { buf = realloc(buf, len); if (!buf) { + perror("realloc"); exit(1); } buf_len = len; From 2b9f4ce6777bfa5f01e2532a8153d9ccefb17bcf Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 12 Apr 2022 13:48:31 +0200 Subject: [PATCH 032/130] more logging --- src/melt/melt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 2a09ba128..ae23704f7 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -549,13 +549,15 @@ static void write_status(JitStatus *const jit_status) { static int fd = -1; if (fd < 0) { - printf("Opening status pipe\n"); + fprintf(stdout, "Opening status pipe\n"); + fflush(stdout); fd = open("/tmp/jit-status", O_WRONLY); if (fd < 0) { perror("open"); exit(2); } - printf("Status pipe opened\n"); + fprintf(stdout, "Status pipe opened\n"); + fflush(stdout); } int len = jit_status__get_packed_size(jit_status) + 4; @@ -1002,6 +1004,9 @@ int main( int argc, char **argv ) signal( SIGILL, abnormal_exit_handler ); signal( SIGABRT, abnormal_exit_handler ); + fprintf(stdout, "Melt starting\n"); + fflush(stdout); + for ( i = 1; i < argc; i ++ ) { // Check for serialisation switch From de3a97d5a7e0af18f1e41baead0ee000abb98b30 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 9 May 2022 15:56:58 +0200 Subject: [PATCH 033/130] improve pipes --- src/melt/melt.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index ae23704f7..7bf31f1ba 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -44,6 +44,7 @@ static mlt_producer melt = NULL; static JitStatus jit_status = JIT_STATUS__INIT; +static int jit_status_fd = -1; static void stop_handler(int signum) { @@ -546,19 +547,6 @@ static JitControl *read_control() { static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; - static int fd = -1; - - if (fd < 0) { - fprintf(stdout, "Opening status pipe\n"); - fflush(stdout); - fd = open("/tmp/jit-status", O_WRONLY); - if (fd < 0) { - perror("open"); - exit(2); - } - fprintf(stdout, "Status pipe opened\n"); - fflush(stdout); - } int len = jit_status__get_packed_size(jit_status) + 4; if (buf_len < len) { @@ -574,7 +562,7 @@ static void write_status(JitStatus *const jit_status) { jit_status__pack(jit_status, b + 4); *((int*) b) = len - 4; while (len) { - const int w = write(fd, b, len); + const int w = write(jit_status_fd, b, len); if (w < 1) { exit(2); } @@ -1005,6 +993,16 @@ int main( int argc, char **argv ) signal( SIGABRT, abnormal_exit_handler ); fprintf(stdout, "Melt starting\n"); + + // Open status pipe + fprintf(stdout, "Opening status pipe\n"); + fflush(stdout); + jit_status_fd = open("/tmp/jit-status", O_WRONLY); + if (jit_status_fd < 0) { + perror("open"); + exit(2); + } + fprintf(stdout, "Status pipe opened\n"); fflush(stdout); for ( i = 1; i < argc; i ++ ) From 3249fdd59728e81a7dad3955c1e77011d673a464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 12 May 2022 10:51:21 +0200 Subject: [PATCH 034/130] Don't pause when already paused --- src/melt/melt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index 7bf31f1ba..822683f7a 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -82,11 +82,13 @@ static void transport_action( mlt_producer producer, char *value ) JitControl *const jit_control = (JitControl*) value; switch (jit_control->type) { case CONTROL_TYPE__PAUSE: + if (mlt_producer_get_speed( producer ) != 0) { mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); if (jit_status.playing) { mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); } + } mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); jit_status.playing = 0; break; From f13faecc0430f95c673896918967aa0596a70c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 12 May 2022 10:52:19 +0200 Subject: [PATCH 035/130] Indent --- src/melt/melt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 822683f7a..580653866 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -83,11 +83,11 @@ static void transport_action( mlt_producer producer, char *value ) switch (jit_control->type) { case CONTROL_TYPE__PAUSE: if (mlt_producer_get_speed( producer ) != 0) { - mlt_producer_set_speed( producer, 0 ); - mlt_consumer_purge( consumer ); - if (jit_status.playing) { - mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); - } + mlt_producer_set_speed( producer, 0 ); + mlt_consumer_purge( consumer ); + if (jit_status.playing) { + mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + } } mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); jit_status.playing = 0; From ef7b5393550ac182c213325e0605d442e55b6d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 12 May 2022 10:53:25 +0200 Subject: [PATCH 036/130] Only silence audio when going backward This makes audio work when single stepping and fast forwarding --- src/modules/avformat/consumer_avformat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index f4af0d350..72e0f445d 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -1850,8 +1850,8 @@ static void *consumer_thread( void *arg ) } if ( pcm ) { - // Silence if not normal forward speed - if ( mlt_properties_get_double( frame_properties, "_speed" ) != 1.0 ) + // Silence only if going backward + if ( mlt_properties_get_double( frame_properties, "_speed" ) < 0 ) memset( pcm, 0, samples * enc_ctx->channels * enc_ctx->sample_bytes ); // Append the samples From 6d8fa2eb7c7cd9a47b44d9f9f7a81312393e6fb1 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 16 May 2022 11:05:12 +0200 Subject: [PATCH 037/130] unique named pipes --- src/melt/melt.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 580653866..1e746b878 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -997,15 +997,19 @@ int main( int argc, char **argv ) fprintf(stdout, "Melt starting\n"); // Open status pipe - fprintf(stdout, "Opening status pipe\n"); - fflush(stdout); - jit_status_fd = open("/tmp/jit-status", O_WRONLY); - if (jit_status_fd < 0) { - perror("open"); - exit(2); + { + char b[100]; + sprintf(b, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Opening status pipe: %s\n", b); + fflush(stdout); + jit_status_fd = open(b, O_WRONLY); + if (jit_status_fd < 0) { + perror("open"); + exit(2); + } + fprintf(stdout, "Status pipe opened\n"); + fflush(stdout); } - fprintf(stdout, "Status pipe opened\n"); - fflush(stdout); for ( i = 1; i < argc; i ++ ) { From 6b4c416dc3a7cfd74ab6536ea8e0e3937c971818 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 16 May 2022 14:25:13 +0200 Subject: [PATCH 038/130] revert to proto2 --- src/melt/JitControl.pb-c.c | 12 +++++----- src/melt/JitControl.pb-c.h | 7 ++++-- src/melt/JitControl.proto | 8 +++---- src/melt/JitStatus.pb-c.c | 46 +++++++++++++++++++------------------- src/melt/JitStatus.pb-c.h | 19 +++++++++++----- src/melt/JitStatus.proto | 28 +++++++++++------------ src/melt/melt.c | 8 +++++++ 7 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/melt/JitControl.pb-c.c b/src/melt/JitControl.pb-c.c index e64269ac9..2e0859224 100644 --- a/src/melt/JitControl.pb-c.c +++ b/src/melt/JitControl.pb-c.c @@ -57,9 +57,9 @@ static const ProtobufCFieldDescriptor jit_control__field_descriptors[3] = { "type", 1, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_ENUM, - 0, /* quantifier_offset */ + offsetof(JitControl, has_type), offsetof(JitControl, type), &control_type__descriptor, NULL, @@ -69,9 +69,9 @@ static const ProtobufCFieldDescriptor jit_control__field_descriptors[3] = { "play_rate", 2, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, - 0, /* quantifier_offset */ + offsetof(JitControl, has_play_rate), offsetof(JitControl, play_rate), NULL, NULL, @@ -81,9 +81,9 @@ static const ProtobufCFieldDescriptor jit_control__field_descriptors[3] = { "seek_position", 3, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT64, - 0, /* quantifier_offset */ + offsetof(JitControl, has_seek_position), offsetof(JitControl, seek_position), NULL, NULL, diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h index fefa73996..d97d7d8ed 100644 --- a/src/melt/JitControl.pb-c.h +++ b/src/melt/JitControl.pb-c.h @@ -8,7 +8,7 @@ PROTOBUF_C__BEGIN_DECLS -#if PROTOBUF_C_VERSION_NUMBER < 1003000 +#if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. #elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. @@ -34,13 +34,16 @@ typedef enum _ControlType { struct _JitControl { ProtobufCMessage base; + protobuf_c_boolean has_type; ControlType type; + protobuf_c_boolean has_play_rate; int32_t play_rate; + protobuf_c_boolean has_seek_position; int64_t seek_position; }; #define JIT_CONTROL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_control__descriptor) \ - , CONTROL_TYPE__PAUSE, 0, 0 } + , 0, CONTROL_TYPE__PAUSE, 0, 0, 0, 0 } /* JitControl methods */ diff --git a/src/melt/JitControl.proto b/src/melt/JitControl.proto index c68199b95..681ceeffa 100644 --- a/src/melt/JitControl.proto +++ b/src/melt/JitControl.proto @@ -1,9 +1,9 @@ -syntax = "proto3"; +syntax = "proto2"; message JitControl { - ControlType type = 1; - int32 play_rate = 2; - int64 seek_position = 3; + optional ControlType type = 1; + optional int32 play_rate = 2; + optional int64 seek_position = 3; } enum ControlType { diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index b5ec252c1..172da831c 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -237,9 +237,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "duration", 1, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT64, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_duration), offsetof(JitStatus, duration), NULL, NULL, @@ -249,9 +249,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "frame_rate", 2, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_DOUBLE, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_frame_rate), offsetof(JitStatus, frame_rate), NULL, NULL, @@ -261,9 +261,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "playing", 3, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_BOOL, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_playing), offsetof(JitStatus, playing), NULL, NULL, @@ -273,9 +273,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "play_rate", 4, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_play_rate), offsetof(JitStatus, play_rate), NULL, NULL, @@ -285,9 +285,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "position", 5, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT64, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_position), offsetof(JitStatus, position), NULL, NULL, @@ -297,9 +297,9 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "total_channels", 6, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, - 0, /* quantifier_offset */ + offsetof(JitStatus, has_total_channels), offsetof(JitStatus, total_channels), NULL, NULL, @@ -309,7 +309,7 @@ static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = { "media_info", 7, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ offsetof(JitStatus, media_info), @@ -391,9 +391,9 @@ static const ProtobufCFieldDescriptor stream__field_descriptors[3] = { "type", 1, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_ENUM, - 0, /* quantifier_offset */ + offsetof(Stream, has_type), offsetof(Stream, type), &stream_type__descriptor, NULL, @@ -403,7 +403,7 @@ static const ProtobufCFieldDescriptor stream__field_descriptors[3] = { "audio", 2, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ offsetof(Stream, audio), @@ -415,7 +415,7 @@ static const ProtobufCFieldDescriptor stream__field_descriptors[3] = { "video", 3, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ offsetof(Stream, video), @@ -455,9 +455,9 @@ static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = { "channels", 1, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, - 0, /* quantifier_offset */ + offsetof(AudioStream, has_channels), offsetof(AudioStream, channels), NULL, NULL, @@ -467,12 +467,12 @@ static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = { "language", 2, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ offsetof(AudioStream, language), NULL, - &protobuf_c_empty_string, + NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, @@ -506,9 +506,9 @@ static const ProtobufCFieldDescriptor video_stream__field_descriptors[1] = { "frame_rate", 1, - PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_DOUBLE, - 0, /* quantifier_offset */ + offsetof(VideoStream, has_frame_rate), offsetof(VideoStream, frame_rate), NULL, NULL, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index d3ded65c0..924983d4d 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -8,7 +8,7 @@ PROTOBUF_C__BEGIN_DECLS -#if PROTOBUF_C_VERSION_NUMBER < 1003000 +#if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. #elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. @@ -36,17 +36,23 @@ typedef enum _StreamType { struct _JitStatus { ProtobufCMessage base; + protobuf_c_boolean has_duration; int64_t duration; + protobuf_c_boolean has_frame_rate; double frame_rate; + protobuf_c_boolean has_playing; protobuf_c_boolean playing; + protobuf_c_boolean has_play_rate; int32_t play_rate; + protobuf_c_boolean has_position; int64_t position; + protobuf_c_boolean has_total_channels; int32_t total_channels; MediaInfo *media_info; }; #define JIT_STATUS__INIT \ { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ - , 0, 0, 0, 0, 0, 0, NULL } + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } struct _MediaInfo @@ -63,34 +69,37 @@ struct _MediaInfo struct _Stream { ProtobufCMessage base; + protobuf_c_boolean has_type; StreamType type; AudioStream *audio; VideoStream *video; }; #define STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ - , STREAM_TYPE__UNKNOWN, NULL, NULL } + , 0, STREAM_TYPE__UNKNOWN, NULL, NULL } struct _AudioStream { ProtobufCMessage base; + protobuf_c_boolean has_channels; int32_t channels; char *language; }; #define AUDIO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ - , 0, (char *)protobuf_c_empty_string } + , 0, 0, NULL } struct _VideoStream { ProtobufCMessage base; + protobuf_c_boolean has_frame_rate; double frame_rate; }; #define VIDEO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&video_stream__descriptor) \ - , 0 } + , 0, 0 } /* JitStatus methods */ diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index 9986c8b5c..5f92f7d72 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -1,13 +1,13 @@ -syntax = "proto3"; +syntax = "proto2"; message JitStatus { - int64 duration = 1; - double frame_rate = 2; - bool playing = 3; - int32 play_rate = 4; - int64 position = 5; - int32 total_channels = 6; - MediaInfo media_info = 7; + optional int64 duration = 1; + optional double frame_rate = 2; + optional bool playing = 3; + optional int32 play_rate = 4; + optional int64 position = 5; + optional int32 total_channels = 6; + optional MediaInfo media_info = 7; } message MediaInfo { @@ -15,18 +15,18 @@ message MediaInfo { } message Stream { - StreamType type = 1; - AudioStream audio = 2; - VideoStream video = 3; + optional StreamType type = 1; + optional AudioStream audio = 2; + optional VideoStream video = 3; } message AudioStream { - int32 channels = 1; - string language = 2; + optional int32 channels = 1; + optional string language = 2; } message VideoStream { - double frame_rate = 1; + optional double frame_rate = 1; } enum StreamType { diff --git a/src/melt/melt.c b/src/melt/melt.c index 1e746b878..42ab38494 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -678,9 +678,13 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) fflush( stderr ); */ // MOFF + jit_status.has_duration = 1; jit_status.duration = mlt_producer_get_length(producer); + jit_status.frame_rate = 1; jit_status.frame_rate = mlt_producer_get_fps(producer); + jit_status.has_play_rate = 1; jit_status.play_rate = mlt_producer_get_speed(producer); + jit_status.has_position = 1; jit_status.position = mlt_producer_position(producer); write_status(&jit_status); @@ -1225,6 +1229,7 @@ int main( int argc, char **argv ) } // video plays automatically + jit_status.has_playing = 1; jit_status.playing = 1; // media info @@ -1237,6 +1242,7 @@ int main( int argc, char **argv ) Stream *s = calloc(sizeof (Stream), 1); stream__init(s); jit_status.media_info->streams[i] = s; + s->has_type = 1; s->type = STREAM_TYPE__UNKNOWN; char key[100]; sprintf(key, "meta.media.%d.stream.type", i); @@ -1248,7 +1254,9 @@ int main( int argc, char **argv ) s->audio = calloc(1, sizeof (AudioStream)); audio_stream__init(s->audio); sprintf(key, "meta.media.%d.codec.channels", i); + s->audio->has_channels = 1; s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + jit_status.has_total_channels = 1; jit_status.total_channels += s->audio->channels; sprintf(key, "meta.attr.%d.stream.language.markup", i); value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); From d9d0ba452c1909530e27a0399397a7235202d0f1 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 16 May 2022 14:32:59 +0200 Subject: [PATCH 039/130] fix --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 42ab38494..81af25422 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -680,7 +680,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) // MOFF jit_status.has_duration = 1; jit_status.duration = mlt_producer_get_length(producer); - jit_status.frame_rate = 1; + jit_status.has_frame_rate = 1; jit_status.frame_rate = mlt_producer_get_fps(producer); jit_status.has_play_rate = 1; jit_status.play_rate = mlt_producer_get_speed(producer); From 338b5382433632c66e4b10c47264bd9e29330316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 25 May 2022 11:03:49 +0200 Subject: [PATCH 040/130] consumer_avformat: Dummy out apre and vpre stuff --- src/modules/avformat/consumer_avformat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index 72e0f445d..794021a5d 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -769,7 +769,7 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream // Process properties as AVOptions on the AVCodec if ( codec && codec->priv_class ) { - char *apre = mlt_properties_get( properties, "apre" ); + /*char *apre = mlt_properties_get( properties, "apre" ); if ( !c->priv_data && codec->priv_data_size ) { c->priv_data = av_mallocz( codec->priv_data_size ); @@ -782,7 +782,7 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream apply_properties( c->priv_data, p, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ); mlt_properties_close( p ); } - apply_properties( c->priv_data, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ); + apply_properties( c->priv_data, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM );*/ } // Continue if codec found and we can open it @@ -1112,7 +1112,7 @@ static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream // Process properties as AVOptions on the AVCodec if ( codec && codec->priv_class ) { - char *vpre = mlt_properties_get( properties, "vpre" ); + /*char *vpre = mlt_properties_get( properties, "vpre" ); if ( !video_enc->priv_data && codec->priv_data_size ) { video_enc->priv_data = av_mallocz( codec->priv_data_size ); @@ -1125,7 +1125,7 @@ static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream apply_properties( video_enc->priv_data, p, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ); mlt_properties_close( p ); } - apply_properties( video_enc->priv_data, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ); + apply_properties( video_enc->priv_data, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM );*/ } if( codec && codec->pix_fmts ) From 9630cfbf708b02946d1f621a5b54f798bb430dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 25 May 2022 11:05:57 +0200 Subject: [PATCH 041/130] producer_avformat: Use av_codec_is_decoder() instead of accessing codec->decode This fixes the build --- src/modules/avformat/producer_avformat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index be8d8b36c..2187cfb7f 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -251,7 +251,7 @@ int list_components( char* file ) void *state = NULL; const AVCodec *codec = NULL; while ((codec = av_codec_iterate(&state))) { - if ( codec->decode && codec->type == AVMEDIA_TYPE_AUDIO ) + if ( av_codec_is_decoder(codec) && codec->type == AVMEDIA_TYPE_AUDIO ) fprintf( stderr, " - %s\n", codec->name ); } fprintf( stderr, "...\n" ); @@ -263,7 +263,7 @@ int list_components( char* file ) void *state = NULL; const AVCodec *codec = NULL; while ((codec = av_codec_iterate(&state))) { - if ( codec->decode && codec->type == AVMEDIA_TYPE_VIDEO ) + if ( av_codec_is_decoder(codec) && codec->type == AVMEDIA_TYPE_VIDEO ) fprintf( stderr, " - %s\n", codec->name ); } fprintf( stderr, "...\n" ); From 0540e7e7fcfd0f954060dc82267f05ae7daaecc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 25 May 2022 11:06:43 +0200 Subject: [PATCH 042/130] producer_avformat: Set options before avcodec_open2() This fixes lowres and thread_type support --- src/modules/avformat/producer_avformat.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 2187cfb7f..814ccfb9b 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2166,6 +2166,12 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p skip_hwaccel: #endif + + // Process properties as AVOptions + apply_properties( codec_context, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); + if ( codec && codec->priv_class && codec_context->priv_data ) + apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); + // If we don't have a codec and we can't initialise it, we can't do much more... pthread_mutex_lock( &self->open_mutex ); if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 ) @@ -2194,10 +2200,6 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p } pthread_mutex_unlock( &self->open_mutex ); - // Process properties as AVOptions - apply_properties( codec_context, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); - if ( codec && codec->priv_class && codec_context->priv_data ) - apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); // Reset some image properties mlt_properties_set_int( properties, "width", codec_params->width ); @@ -2913,6 +2915,11 @@ static int audio_codec_init( producer_avformat self, int index, mlt_properties p return 0; } + // Process properties as AVOptions + apply_properties( codec_context, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); + if ( codec && codec->priv_class && codec_context->priv_data ) + apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); + // If we don't have a codec and we can't initialise it, we can't do much more... pthread_mutex_lock( &self->open_mutex ); if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 ) @@ -2929,11 +2936,6 @@ static int audio_codec_init( producer_avformat self, int index, mlt_properties p self->audio_index = -1; } pthread_mutex_unlock( &self->open_mutex ); - - // Process properties as AVOptions - apply_properties( codec_context, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); - if ( codec && codec->priv_class && codec_context->priv_data ) - apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM ); } return self->audio_codec[ index ] && self->audio_index > -1; } From 150b071479756c089c80f78ad0e96629f720f66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 25 May 2022 11:25:58 +0200 Subject: [PATCH 043/130] melt: Add -disable-status-fifo option --- src/melt/melt.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 81af25422..1b1b6e4c3 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -550,6 +550,10 @@ static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; + if (jit_status_fd < 0) { + return; + } + int len = jit_status__get_packed_size(jit_status) + 4; if (buf_len < len) { buf = realloc(buf, len); @@ -992,6 +996,7 @@ int main( int argc, char **argv ) mlt_repository repo = NULL; const char* repo_path = NULL; int is_consumer_explicit = 0; + int status_fifo = 1; // Handle abnormal exit situations. signal( SIGSEGV, abnormal_exit_handler ); @@ -1000,21 +1005,6 @@ int main( int argc, char **argv ) fprintf(stdout, "Melt starting\n"); - // Open status pipe - { - char b[100]; - sprintf(b, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Opening status pipe: %s\n", b); - fflush(stdout); - jit_status_fd = open(b, O_WRONLY); - if (jit_status_fd < 0) { - perror("open"); - exit(2); - } - fprintf(stdout, "Status pipe opened\n"); - fflush(stdout); - } - for ( i = 1; i < argc; i ++ ) { // Check for serialisation switch @@ -1154,7 +1144,28 @@ int main( int argc, char **argv ) { is_consumer_explicit = 1; } + else if ( !strcmp( argv[ i ], "-disable-status-fifo" ) ) + { + status_fifo = 0; + } } + + // Open status pipe + if (status_fifo) + { + char b[100]; + sprintf(b, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Opening status pipe: %s\n", b); + fflush(stdout); + jit_status_fd = open(b, O_WRONLY); + if (jit_status_fd < 0) { + perror("open"); + exit(2); + } + fprintf(stdout, "Status pipe opened\n"); + fflush(stdout); + } + if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress ) is_progress = 1; From c99e773501474def16f2cb386734061ec0b2aae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 25 Aug 2022 17:19:57 +0200 Subject: [PATCH 044/130] Fix seek on pause, reduce buffer -> faster pause --- src/melt/melt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 1b1b6e4c3..0f8329ab0 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -86,7 +86,7 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); if (jit_status.playing) { - mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); + mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); } } mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); @@ -1351,6 +1351,10 @@ int main( int argc, char **argv ) mlt_producer_set_in_and_out( melt, in, out ); mlt_producer_seek( melt, 0 ); } + + // smaller buffer -> faster pause + mlt_properties_set_int( properties, "buffer", 3 ); + // Connect consumer to melt mlt_consumer_connect( consumer, MLT_PRODUCER_SERVICE( melt ) ); From e21a37a5317b9763c09158d02a3c4ece807fe270 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 23 Sep 2022 14:08:48 +0200 Subject: [PATCH 045/130] seek on pause --- src/melt/melt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 0f8329ab0..af656f4b7 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -86,7 +86,11 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); if (jit_status.playing) { - mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); + if (jit_control->has_seek_position) { + mlt_producer_seek( producer, jit_control->seek_position); + } else { + mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); + } } } mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); From 43407f455247b52b99222a65c086fe9d48cd0c26 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 27 Sep 2022 15:15:53 +0200 Subject: [PATCH 046/130] start paused --- src/melt/melt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index af656f4b7..b44f2e1ea 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1243,9 +1243,9 @@ int main( int argc, char **argv ) consumer = create_consumer( profile, NULL ); } - // video plays automatically + // video is paused initially jit_status.has_playing = 1; - jit_status.playing = 1; + jit_status.playing = 0; // media info mlt_producer av = find_producer_avformat(melt); @@ -1374,6 +1374,10 @@ int main( int argc, char **argv ) signal( SIGPIPE, stop_handler ); #endif + // start in paused state + mlt_producer_set_speed( melt, 0 ); + mlt_producer_seek( melt, 0 ); + // Transport functionality transport( melt, consumer ); From c44ff2d89c649707d17f33be7d6fb8abff7e72f7 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 3 Oct 2022 17:04:35 +0200 Subject: [PATCH 047/130] fix build error --- src/melt/melt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index 92c40701f..2ed42c100 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -984,6 +984,8 @@ static void dump_properties(mlt_properties p) { char *name = mlt_properties_get_name(p, i); printf("%s\n", name); } +} + static mlt_repository setup_factory(const char* repo_path, int set_locale) { mlt_repository repo = mlt_factory_init(repo_path); From 9ae7249b91f2afa840e246af78e88a1bc37500de Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 6 Oct 2022 16:59:02 +0200 Subject: [PATCH 048/130] use unix domain socket --- src/melt/melt.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 2ed42c100..4c71bc001 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -30,7 +30,9 @@ #include #include #include +#include #include +#include #include #include @@ -559,7 +561,7 @@ static void write_status(JitStatus *const jit_status) { return; } - int len = jit_status__get_packed_size(jit_status) + 4; + int len = jit_status__get_packed_size(jit_status); if (buf_len < len) { buf = realloc(buf, len); if (!buf) { @@ -569,16 +571,10 @@ static void write_status(JitStatus *const jit_status) { buf_len = len; } - char *b = buf; - jit_status__pack(jit_status, b + 4); - *((int*) b) = len - 4; - while (len) { - const int w = write(jit_status_fd, b, len); - if (w < 1) { - exit(2); - } - b += w; - len -= w; + jit_status__pack(jit_status, buf); + if (write(jit_status_fd, buf, len) != len) { + perror("write"); + exit(1); } } @@ -1181,13 +1177,21 @@ int main( int argc, char **argv ) // Open status pipe if (status_fifo) { - char b[100]; - sprintf(b, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Opening status pipe: %s\n", b); - fflush(stdout); - jit_status_fd = open(b, O_WRONLY); + jit_status_fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (jit_status_fd < 0) { - perror("open"); + perror("socket"); + exit(2); + } + + struct sockaddr_un sun; + memset(&sun, 0, sizeof sun); + sun.sun_family = AF_UNIX; + sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Opening status socket: %s\n", sun.sun_path); + fflush(stdout); + + if (connect(jit_status_fd, (struct sockaddr *) &sun, sizeof sun) < 0) { + perror("connect"); exit(2); } fprintf(stdout, "Status pipe opened\n"); From 63b62f79d90d9d1cd080a47ee95983769b374dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 7 Oct 2022 15:58:02 +0200 Subject: [PATCH 049/130] producer_avformat: Always seek when file is intra-only --- src/modules/avformat/producer_avformat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index fc5bc59e5..a11561aa3 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1185,10 +1185,12 @@ static int seek_video( producer_avformat self, mlt_position position, int paused = 0; int seek_threshold = mlt_properties_get_int( properties, "seek_threshold" ); if ( seek_threshold <= 0 ) seek_threshold = 12; + // intra only -> always seek to exactly where we need to be + int intra_only = self->video_codec->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY; pthread_mutex_lock( &self->packets_mutex ); - if ( self->video_seekable && ( position != self->video_expected || self->last_position < 0 ) ) + if ( self->video_seekable && (( position != self->video_expected || self->last_position < 0 ) || intra_only) ) { // Fetch the video format context @@ -1206,7 +1208,7 @@ static int seek_video( producer_avformat self, mlt_position position, // We're paused - use last image paused = 1; } - else if ( position < self->video_expected || position - self->video_expected >= seek_threshold || self->last_position < 0 ) + else if ( position < self->video_expected || position - self->video_expected >= seek_threshold || self->last_position < 0 || intra_only ) { // Calculate the timestamp for the requested frame int64_t timestamp = req_position / ( av_q2d( self->video_time_base ) * source_fps ); From dc20ac674c16f66688636c71472feb65cb59c7a8 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 19 Oct 2022 10:30:52 +0200 Subject: [PATCH 050/130] support relative seek --- src/melt/JitControl.pb-c.c | 12 +++++++----- src/melt/JitControl.pb-c.h | 3 ++- src/melt/JitControl.proto | 1 + src/melt/melt.c | 6 ++++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/melt/JitControl.pb-c.c b/src/melt/JitControl.pb-c.c index 2e0859224..accf5fba9 100644 --- a/src/melt/JitControl.pb-c.c +++ b/src/melt/JitControl.pb-c.c @@ -116,24 +116,26 @@ const ProtobufCMessageDescriptor jit_control__descriptor = (ProtobufCMessageInit) jit_control__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCEnumValue control_type__enum_values_by_number[5] = +static const ProtobufCEnumValue control_type__enum_values_by_number[6] = { { "PAUSE", "CONTROL_TYPE__PAUSE", 0 }, { "PLAY", "CONTROL_TYPE__PLAY", 1 }, { "PLAY_RATE", "CONTROL_TYPE__PLAY_RATE", 2 }, { "QUIT", "CONTROL_TYPE__QUIT", 3 }, { "SEEK", "CONTROL_TYPE__SEEK", 4 }, + { "SEEK_REL", "CONTROL_TYPE__SEEK_REL", 5 }, }; static const ProtobufCIntRange control_type__value_ranges[] = { -{0, 0},{0, 5} +{0, 0},{0, 6} }; -static const ProtobufCEnumValueIndex control_type__enum_values_by_name[5] = +static const ProtobufCEnumValueIndex control_type__enum_values_by_name[6] = { { "PAUSE", 0 }, { "PLAY", 1 }, { "PLAY_RATE", 2 }, { "QUIT", 3 }, { "SEEK", 4 }, + { "SEEK_REL", 5 }, }; const ProtobufCEnumDescriptor control_type__descriptor = { @@ -142,9 +144,9 @@ const ProtobufCEnumDescriptor control_type__descriptor = "ControlType", "ControlType", "", - 5, + 6, control_type__enum_values_by_number, - 5, + 6, control_type__enum_values_by_name, 1, control_type__value_ranges, diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h index d97d7d8ed..117c80af9 100644 --- a/src/melt/JitControl.pb-c.h +++ b/src/melt/JitControl.pb-c.h @@ -25,7 +25,8 @@ typedef enum _ControlType { CONTROL_TYPE__PLAY = 1, CONTROL_TYPE__PLAY_RATE = 2, CONTROL_TYPE__QUIT = 3, - CONTROL_TYPE__SEEK = 4 + CONTROL_TYPE__SEEK = 4, + CONTROL_TYPE__SEEK_REL = 5 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(CONTROL_TYPE) } ControlType; diff --git a/src/melt/JitControl.proto b/src/melt/JitControl.proto index 681ceeffa..b8638bb85 100644 --- a/src/melt/JitControl.proto +++ b/src/melt/JitControl.proto @@ -12,4 +12,5 @@ enum ControlType { PLAY_RATE = 2; QUIT = 3; SEEK = 4; + SEEK_REL = 5; } diff --git a/src/melt/melt.c b/src/melt/melt.c index 4c71bc001..4221b5aec 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -117,6 +117,12 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_seek( producer, jit_control->seek_position); fire_jack_seek_event(jack, jit_control->seek_position); break; + case CONTROL_TYPE__SEEK_REL: + const mlt_position pos = mlt_producer_position(producer) + jit_control->seek_position; + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, pos); + fire_jack_seek_event(jack, pos); + break; case CONTROL_TYPE__QUIT: mlt_properties_set_int( properties, "done", 1 ); mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); From fc98b7df01605e3f02382ea3c8851cc915c68696 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 10:18:56 +0200 Subject: [PATCH 051/130] fps multiplier --- src/melt/CMakeLists.txt | 2 +- src/melt/melt.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/melt/CMakeLists.txt b/src/melt/CMakeLists.txt index 183fab3bc..c85355627 100644 --- a/src/melt/CMakeLists.txt +++ b/src/melt/CMakeLists.txt @@ -2,7 +2,7 @@ add_executable(melt melt.c io.c io.h JitControl.pb-c.c JitStatus.pb-c.c) target_compile_options(melt PRIVATE ${MLT_COMPILE_OPTIONS}) -target_link_libraries(melt PRIVATE mlt Threads::Threads protobuf-c) +target_link_libraries(melt PRIVATE mlt Threads::Threads protobuf-c m) target_compile_definitions(melt PRIVATE VERSION="${MLT_VERSION}") diff --git a/src/melt/melt.c b/src/melt/melt.c index 4221b5aec..f3c3bce30 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -20,6 +20,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include #include #include #include @@ -617,6 +618,19 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) */ } + // frame rate multiplier + double fps_multiplier; + { + const double pnum = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "frame_rate_num"); + const double pden = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "frame_rate_den"); + const double cnum = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); + const double cden = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); + fps_multiplier = (cnum * pden) / (pnum * cden); + if (fps_multiplier != 1) { + fprintf(stderr, "fps_multiplier: %f\n", fps_multiplier); + } + } + while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { @@ -696,7 +710,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) jit_status.has_play_rate = 1; jit_status.play_rate = mlt_producer_get_speed(producer); jit_status.has_position = 1; - jit_status.position = mlt_producer_position(producer); + jit_status.position = llround(mlt_producer_position(producer) / fps_multiplier); write_status(&jit_status); last_position = jit_status.position; From 683fe2aaaf96a52afb6e5b24fa85a2cc791cba8f Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 10:24:51 +0200 Subject: [PATCH 052/130] more logging --- src/melt/melt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index f3c3bce30..d93b1951f 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -625,6 +625,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) const double pden = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "frame_rate_den"); const double cnum = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); const double cden = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); + fprintf(stderr, "%f / %f\n%f / %f\n", pnum, pden, cnum, cden); fps_multiplier = (cnum * pden) / (pnum * cden); if (fps_multiplier != 1) { fprintf(stderr, "fps_multiplier: %f\n", fps_multiplier); From 9b99be6c0a8c8b3e099921ccffa33c209acc254b Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 10:28:13 +0200 Subject: [PATCH 053/130] fix --- src/melt/melt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index d93b1951f..e34dac61c 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -621,12 +621,9 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) // frame rate multiplier double fps_multiplier; { - const double pnum = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "frame_rate_num"); - const double pden = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "frame_rate_den"); const double cnum = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); const double cden = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); - fprintf(stderr, "%f / %f\n%f / %f\n", pnum, pden, cnum, cden); - fps_multiplier = (cnum * pden) / (pnum * cden); + fps_multiplier = (mlt_producer_get_fps(producer) * cden) / cnum; if (fps_multiplier != 1) { fprintf(stderr, "fps_multiplier: %f\n", fps_multiplier); } From 57a2d79cb9e8d31820e26084857bbfd284b71cd2 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 10:45:54 +0200 Subject: [PATCH 054/130] fix --- src/melt/melt.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index e34dac61c..354fc000c 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -620,10 +620,10 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) // frame rate multiplier double fps_multiplier; - { - const double cnum = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); - const double cden = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); - fps_multiplier = (mlt_producer_get_fps(producer) * cden) / cnum; + if (jit_status.has_frame_rate) { + const int num = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); + const int den = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); + fps_multiplier = num / (jit_status.frame_rate * den); if (fps_multiplier != 1) { fprintf(stderr, "fps_multiplier: %f\n", fps_multiplier); } @@ -703,8 +703,8 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) // MOFF jit_status.has_duration = 1; jit_status.duration = mlt_producer_get_length(producer); - jit_status.has_frame_rate = 1; - jit_status.frame_rate = mlt_producer_get_fps(producer); + //jit_status.has_frame_rate = 1; + //jit_status.frame_rate = mlt_producer_get_fps(producer); jit_status.has_play_rate = 1; jit_status.play_rate = mlt_producer_get_speed(producer); jit_status.has_position = 1; @@ -1330,6 +1330,15 @@ int main( int argc, char **argv ) } } else if (!strcmp(value, "video")) { s->type = STREAM_TYPE__VIDEO; + s->video = calloc(1, sizeof (VideoStream)); + video_stream__init(s->video); + sprintf(key, "meta.media.%d.stream.frame_rate", i); + s->video->has_frame_rate = 1; + s->video->frame_rate = mlt_properties_get_double(MLT_PRODUCER_PROPERTIES(av), key); + if (!jit_status.has_frame_rate) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = s->video->frame_rate; + } } } //dump_properties(av); From 3d0d36858f91024bee8f0c39d65598d33592d886 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 11:03:46 +0200 Subject: [PATCH 055/130] seek --- src/melt/melt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 354fc000c..d8ef96d42 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -49,6 +49,7 @@ static mlt_producer melt = NULL; static JitStatus jit_status = JIT_STATUS__INIT; static int jit_status_fd = -1; +static double fps_multiplier; static void stop_handler(int signum) { @@ -115,8 +116,8 @@ static void transport_action( mlt_producer producer, char *value ) case CONTROL_TYPE__SEEK: mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, jit_control->seek_position); - fire_jack_seek_event(jack, jit_control->seek_position); + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); + fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); break; case CONTROL_TYPE__SEEK_REL: const mlt_position pos = mlt_producer_position(producer) + jit_control->seek_position; @@ -619,7 +620,6 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) } // frame rate multiplier - double fps_multiplier; if (jit_status.has_frame_rate) { const int num = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_num"); const int den = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "frame_rate_den"); @@ -702,7 +702,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) */ // MOFF jit_status.has_duration = 1; - jit_status.duration = mlt_producer_get_length(producer); + jit_status.duration = llround(mlt_producer_get_length(producer) / fps_multiplier); //jit_status.has_frame_rate = 1; //jit_status.frame_rate = mlt_producer_get_fps(producer); jit_status.has_play_rate = 1; From 8fda63fb8ae577ff413665a1529c94a9cbc9b86a Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 11:16:35 +0200 Subject: [PATCH 056/130] ceil seek relativ --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index d8ef96d42..6c8c7323b 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -120,7 +120,7 @@ static void transport_action( mlt_producer producer, char *value ) fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); break; case CONTROL_TYPE__SEEK_REL: - const mlt_position pos = mlt_producer_position(producer) + jit_control->seek_position; + const mlt_position pos = mlt_producer_position(producer) + ceil(fps_multiplier * jit_control->seek_position); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, pos); fire_jack_seek_event(jack, pos); From c80a226ad9d8a5274be72516320cc01fcadbd325 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 11:34:07 +0200 Subject: [PATCH 057/130] more fix --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 6c8c7323b..95d0a1815 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -120,7 +120,7 @@ static void transport_action( mlt_producer producer, char *value ) fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); break; case CONTROL_TYPE__SEEK_REL: - const mlt_position pos = mlt_producer_position(producer) + ceil(fps_multiplier * jit_control->seek_position); + const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, pos); fire_jack_seek_event(jack, pos); From 08d27efa22610eadabf59bde1f23a0db3e445ad0 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 21 Oct 2022 14:47:43 +0200 Subject: [PATCH 058/130] fix seek-on-pause --- src/melt/melt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 95d0a1815..c5780043e 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -92,9 +92,9 @@ static void transport_action( mlt_producer producer, char *value ) mlt_consumer_purge( consumer ); if (jit_status.playing) { if (jit_control->has_seek_position) { - mlt_producer_seek( producer, jit_control->seek_position); + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); } else { - mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); + //mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); } } } From 354d170cee09ab16943ee9490dff3620d62bedef Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 31 Oct 2022 10:34:50 +0100 Subject: [PATCH 059/130] add resolution to video stream --- src/melt/JitControl.pb-c.h | 6 +++--- src/melt/JitStatus.pb-c.c | 32 +++++++++++++++++++++++++++++--- src/melt/JitStatus.pb-c.h | 28 ++++++++++++++++------------ src/melt/JitStatus.proto | 2 ++ src/melt/melt.c | 10 ++++++---- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h index 117c80af9..a47b676ea 100644 --- a/src/melt/JitControl.pb-c.h +++ b/src/melt/JitControl.pb-c.h @@ -10,12 +10,12 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif -typedef struct _JitControl JitControl; +typedef struct JitControl JitControl; /* --- enums --- */ @@ -32,7 +32,7 @@ typedef enum _ControlType { /* --- messages --- */ -struct _JitControl +struct JitControl { ProtobufCMessage base; protobuf_c_boolean has_type; diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c index 172da831c..8b546a9db 100644 --- a/src/melt/JitStatus.pb-c.c +++ b/src/melt/JitStatus.pb-c.c @@ -501,7 +501,7 @@ const ProtobufCMessageDescriptor audio_stream__descriptor = (ProtobufCMessageInit) audio_stream__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor video_stream__field_descriptors[1] = +static const ProtobufCFieldDescriptor video_stream__field_descriptors[3] = { { "frame_rate", @@ -515,14 +515,40 @@ static const ProtobufCFieldDescriptor video_stream__field_descriptors[1] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "width", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(VideoStream, has_width), + offsetof(VideoStream, width), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "height", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(VideoStream, has_height), + offsetof(VideoStream, height), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned video_stream__field_indices_by_name[] = { 0, /* field[0] = frame_rate */ + 2, /* field[2] = height */ + 1, /* field[1] = width */ }; static const ProtobufCIntRange video_stream__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 1 } + { 0, 3 } }; const ProtobufCMessageDescriptor video_stream__descriptor = { @@ -532,7 +558,7 @@ const ProtobufCMessageDescriptor video_stream__descriptor = "VideoStream", "", sizeof(VideoStream), - 1, + 3, video_stream__field_descriptors, video_stream__field_indices_by_name, 1, video_stream__number_ranges, diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h index 924983d4d..a6c3ade58 100644 --- a/src/melt/JitStatus.pb-c.h +++ b/src/melt/JitStatus.pb-c.h @@ -10,16 +10,16 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif -typedef struct _JitStatus JitStatus; -typedef struct _MediaInfo MediaInfo; -typedef struct _Stream Stream; -typedef struct _AudioStream AudioStream; -typedef struct _VideoStream VideoStream; +typedef struct JitStatus JitStatus; +typedef struct MediaInfo MediaInfo; +typedef struct Stream Stream; +typedef struct AudioStream AudioStream; +typedef struct VideoStream VideoStream; /* --- enums --- */ @@ -33,7 +33,7 @@ typedef enum _StreamType { /* --- messages --- */ -struct _JitStatus +struct JitStatus { ProtobufCMessage base; protobuf_c_boolean has_duration; @@ -55,7 +55,7 @@ struct _JitStatus , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } -struct _MediaInfo +struct MediaInfo { ProtobufCMessage base; size_t n_streams; @@ -66,7 +66,7 @@ struct _MediaInfo , 0,NULL } -struct _Stream +struct Stream { ProtobufCMessage base; protobuf_c_boolean has_type; @@ -79,7 +79,7 @@ struct _Stream , 0, STREAM_TYPE__UNKNOWN, NULL, NULL } -struct _AudioStream +struct AudioStream { ProtobufCMessage base; protobuf_c_boolean has_channels; @@ -91,15 +91,19 @@ struct _AudioStream , 0, 0, NULL } -struct _VideoStream +struct VideoStream { ProtobufCMessage base; protobuf_c_boolean has_frame_rate; double frame_rate; + protobuf_c_boolean has_width; + int32_t width; + protobuf_c_boolean has_height; + int32_t height; }; #define VIDEO_STREAM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&video_stream__descriptor) \ - , 0, 0 } + , 0, 0, 0, 0, 0, 0 } /* JitStatus methods */ diff --git a/src/melt/JitStatus.proto b/src/melt/JitStatus.proto index 5f92f7d72..735c64797 100644 --- a/src/melt/JitStatus.proto +++ b/src/melt/JitStatus.proto @@ -27,6 +27,8 @@ message AudioStream { message VideoStream { optional double frame_rate = 1; + optional int32 width = 2; + optional int32 height = 3; } enum StreamType { diff --git a/src/melt/melt.c b/src/melt/melt.c index c5780043e..1ca194ae2 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1322,11 +1322,7 @@ int main( int argc, char **argv ) sprintf(key, "meta.attr.%d.stream.language.markup", i); value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); if (value) { - //int l = strlen(value); - //s->audio->language.len = l; - //s->audio->language.data = calloc(1, l + 1); s->audio->language = strdup(value); - //strcpy(s->audio->language.data, value); } } else if (!strcmp(value, "video")) { s->type = STREAM_TYPE__VIDEO; @@ -1339,6 +1335,12 @@ int main( int argc, char **argv ) jit_status.has_frame_rate = 1; jit_status.frame_rate = s->video->frame_rate; } + sprintf(key, "meta.media.%d.codec.width", i); + s->video->has_width = 1; + s->video->width = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + sprintf(key, "meta.media.%d.codec.height", i); + s->video->has_height = 1; + s->video->height = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); } } //dump_properties(av); From 94c01526453c433cab5f962c1887243a9c212643 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Wed, 2 Nov 2022 11:55:03 +0100 Subject: [PATCH 060/130] pause when reaching beginning --- src/melt/melt.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 1ca194ae2..d6019266d 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -80,7 +80,7 @@ static void transport_action( mlt_producer producer, char *value ) mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); - mlt_position position = producer? mlt_producer_position( producer ) : 0; + mlt_position position = producer ? mlt_producer_position( producer ) : 0; mlt_properties_set_int( properties, "stats_off", 1 ); @@ -682,44 +682,24 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) if ( !silent && mlt_properties_get_int( properties, "stats_off" ) == 0 ) { - /* - if ( progress ) - { - int current_position = mlt_producer_position( producer ); - if ( current_position > last_position ) - { - fprintf( stderr, "Current Frame: %10d, percentage: %10d%c", - current_position, 100 * current_position / total_length, - progress == 2 ? '\n' : '\r' ); - last_position = current_position; - } - } - else - { - fprintf( stderr, "Current Position: %10d\r", (int)mlt_consumer_position( consumer ) ); - } - fflush( stderr ); - */ - // MOFF jit_status.has_duration = 1; jit_status.duration = llround(mlt_producer_get_length(producer) / fps_multiplier); - //jit_status.has_frame_rate = 1; - //jit_status.frame_rate = mlt_producer_get_fps(producer); jit_status.has_play_rate = 1; jit_status.play_rate = mlt_producer_get_speed(producer); jit_status.has_position = 1; jit_status.position = llround(mlt_producer_position(producer) / fps_multiplier); + if (jit_status.play_rate < 0 && jit_status.position == 0) { + mlt_producer_set_speed( producer, 0 ); + mlt_consumer_purge( consumer ); + //mlt_producer_seek( producer, 0); + jit_status.play_rate = 0; + jit_status.position = 0; + } write_status(&jit_status); last_position = jit_status.position; } - - //if ( silent || progress ) - //nanosleep( &tm, NULL ); } - - //if ( !silent ) - //fprintf( stderr, "\n" ); } } From 975745c2e4e685e691add9c4d77fb8b0e41c1fbb Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 8 Dec 2022 10:14:49 +0100 Subject: [PATCH 061/130] Fallback to r_frame_rate --- src/modules/avformat/producer_avformat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index a11561aa3..a34db4c34 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -403,7 +403,8 @@ static mlt_properties find_default_streams( producer_avformat self ) } mlt_properties_set( meta_media, key, "video" ); snprintf( key, sizeof(key), "meta.media.%u.stream.frame_rate", i ); - double ffmpeg_fps = av_q2d( context->streams[ i ]->avg_frame_rate ); + double avg_frame_rate = av_q2d( context->streams[ i ]->avg_frame_rate ); + double ffmpeg_fps = isfinite( avg_frame_rate ) ? avg_frame_rate : av_q2d( context->streams[ i ]->r_frame_rate ); mlt_properties_set_double( meta_media, key, ffmpeg_fps ); const char *projection = get_projection(context->streams[i]); From 595d7c6a58b61fdac80da52771901a856aedbf86 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 9 Dec 2022 09:50:25 +0100 Subject: [PATCH 062/130] fix framerate problem --- src/melt/melt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index d6019266d..b246674bc 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1279,6 +1279,12 @@ int main( int argc, char **argv ) media_info__init(jit_status.media_info); jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); + const int frame_rate_num = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_num"); + const int frame_rate_den = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_den"); + if (frame_rate_num > 0 && frame_rate_den > 0) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = ((double) frame_rate_num) / ((double) frame_rate_den); + } for (int i = 0; i < jit_status.media_info->n_streams; i++) { Stream *s = calloc(sizeof (Stream), 1); stream__init(s); From da00e69d220c12093f2f6cefbd5edd1e52400c9f Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 16 Dec 2022 10:17:05 +0100 Subject: [PATCH 063/130] only start paused when using status fifo --- src/melt/melt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index b246674bc..31d486301 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1271,7 +1271,7 @@ int main( int argc, char **argv ) // video is paused initially jit_status.has_playing = 1; - jit_status.playing = 0; + jit_status.playing = status_fifo ? 0 : 1; // play automatically when status fifo is disabled // media info mlt_producer av = find_producer_avformat(melt); @@ -1417,9 +1417,11 @@ int main( int argc, char **argv ) signal( SIGPIPE, stop_handler ); #endif - // start in paused state - mlt_producer_set_speed( melt, 0 ); - mlt_producer_seek( melt, 0 ); + // start in paused state? + if (!jit_status.playing) { + mlt_producer_set_speed( melt, 0 ); + mlt_producer_seek( melt, 0 ); + } // Transport functionality transport( melt, consumer ); From 6822799a89e2d5839d7c5460cfbbf5dc76a7054a Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 24 Jan 2023 16:08:55 +0100 Subject: [PATCH 064/130] add empty statement --- src/melt/melt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 31d486301..1328a4acb 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -119,7 +119,7 @@ static void transport_action( mlt_producer producer, char *value ) mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); break; - case CONTROL_TYPE__SEEK_REL: + case CONTROL_TYPE__SEEK_REL: ; const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, pos); From e4aeeb63f6023539b4ff1741f68cd039faf1be0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 27 Jan 2023 13:05:11 +0100 Subject: [PATCH 065/130] producer_avformat: Use filtergraph dimensions and pixel format where appropriate This is necessary since avfilter may change dimensions and/or pixel format. Autorotate is handled more succinctly in set_image_size(). --- src/modules/avformat/producer_avformat.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index aaaf4d728..3394cb37d 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -760,12 +760,16 @@ static int get_basic_info( producer_avformat self, mlt_profile profile, const ch mlt_properties_set_int( properties, "height", codec_params->height ); get_aspect_ratio( properties, format->streams[ self->video_index ], codec_params ); +#ifdef AVFILTER + int pix_fmt = self->vfilter_out ? av_buffersink_get_format(self->vfilter_out) : codec_params->format; +#else int pix_fmt = codec_params->format; +#endif pick_av_pixel_format( &pix_fmt ); if ( pix_fmt != AV_PIX_FMT_NONE ) { // Verify that we can convert this to one of our image formats. struct SwsContext *context = sws_getContext( codec_params->width, codec_params->height, pix_fmt, - codec_params->width, codec_params->height, pick_pix_fmt( codec_params->format ), SWS_BILINEAR, NULL, NULL, NULL); + codec_params->width, codec_params->height, pick_pix_fmt( pix_fmt ), SWS_BILINEAR, NULL, NULL, NULL); if ( context ) { sws_freeContext( context ); @@ -807,11 +811,6 @@ static int setup_video_filters( producer_avformat self ) if (result >= 0) { result = avfilter_graph_create_filter(&self->vfilter_out, avfilter_get_by_name("buffersink"), "mlt_buffersink", NULL, NULL, self->vfilter_graph); - - if (result >= 0) { - enum AVPixelFormat pix_fmts[] = { codec_params->format, AV_PIX_FMT_NONE }; - result = av_opt_set_int_list(self->vfilter_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); - } } return result; @@ -1607,6 +1606,12 @@ static int convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffe static void set_image_size( producer_avformat self, int *width, int *height ) { +#ifdef AVFILTER + if (self->vfilter_out) { + *width = av_buffersink_get_w(self->vfilter_out); + *height = av_buffersink_get_h(self->vfilter_out); + } +#else double dar = mlt_profile_dar( mlt_service_profile( MLT_PRODUCER_SERVICE(self->parent) ) ); double theta = self->autorotate? get_rotation( MLT_PRODUCER_PROPERTIES(self->parent), self->video_format->streams[self->video_index] ) : 0.0; if ( fabs(theta - 90.0) < 1.0 || fabs(theta - 270.0) < 1.0 ) @@ -1625,6 +1630,7 @@ static void set_image_size( producer_avformat self, int *width, int *height ) else *height = self->video_codec->height; } +#endif } /** Allocate the image buffer and set it on the frame. @@ -1769,7 +1775,11 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form codec_params = stream->codecpar; // Only change the requested image format for special cases +#ifdef AVFILTER + *format = pick_image_format(self->vfilter_out ? av_buffersink_get_format(self->vfilter_out) : codec_params->format, self->full_range, *format); +#else *format = pick_image_format(codec_params->format, self->full_range, *format); +#endif // Duplicate the last image if necessary if ( self->video_frame && self->video_frame->linesize[0] From 3201851e0a4c2e2ac723bab447a14d654fac1e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 24 Jan 2023 12:21:27 +0100 Subject: [PATCH 066/130] Add Code::Blocks project files --- mlt.cbp | 1427 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mlt.depend | 57 +++ mlt.layout | 80 +++ 3 files changed, 1564 insertions(+) create mode 100644 mlt.cbp create mode 100644 mlt.depend create mode 100644 mlt.layout diff --git a/mlt.cbp b/mlt.cbp new file mode 100644 index 000000000..2e321efa8 --- /dev/null +++ b/mlt.cbp @@ -0,0 +1,1427 @@ + + + + + + diff --git a/mlt.depend b/mlt.depend new file mode 100644 index 000000000..408332cb8 --- /dev/null +++ b/mlt.depend @@ -0,0 +1,57 @@ +# depslib dependency file v1.0 +1653638752 source:/home/thardin/biz/jit/mlt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c + +1653638752 source:/home/thardin/biz/jit/mlt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp + +1665151040 source:/home/thardin/biz/jit/mlt/src/framework/mlt_animation.c + "mlt_animation.h" + "mlt_tokeniser.h" + "mlt_profile.h" + "mlt_factory.h" + "mlt_properties.h" + + + + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_animation.h + "mlt_types.h" + "mlt_property.h" + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_types.h + + + + "mlt_pool.h" + + + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_pool.h + +1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_property.h + "mlt_types.h" + + + + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_tokeniser.h + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_profile.h + "mlt_types.h" + +1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_factory.h + "mlt_types.h" + "mlt_profile.h" + "mlt_repository.h" + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_repository.h + "mlt_types.h" + "mlt_profile.h" + +1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_properties.h + "mlt_types.h" + "mlt_events.h" + + +1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_events.h + "mlt_types.h" + diff --git a/mlt.layout b/mlt.layout new file mode 100644 index 000000000..501835f75 --- /dev/null +++ b/mlt.layout @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From edf234fa351c53205a5476cabd2e6a530a76b2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Thu, 16 Feb 2023 10:55:41 +0100 Subject: [PATCH 067/130] Ignore mlt.layout --- .gitignore | 1 + mlt.layout | 80 ------------------------------------------------------ 2 files changed, 1 insertion(+), 80 deletions(-) delete mode 100644 mlt.layout diff --git a/.gitignore b/.gitignore index 3436b2dd8..82fa4d4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ install_manifest.txt out/ src/modules/qt/mltqt_autogen/ src/modules/glaxnimate/mltglaxnimate_autogen/ +mlt.layout diff --git a/mlt.layout b/mlt.layout deleted file mode 100644 index 501835f75..000000000 --- a/mlt.layout +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 7ab9dc29d723c89d134970e84924d3a6604f68c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 22 Feb 2023 15:02:45 +0100 Subject: [PATCH 068/130] Change -disable-status-fifo to -enable-status-fifo --- src/melt/melt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 0ac853802..2099a5ed4 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1012,7 +1012,7 @@ int main( int argc, char **argv ) const char* repo_path = NULL; int is_consumer_explicit = 0; int is_setlocale = 0; - int status_fifo = 1; + int status_fifo = 0; // Handle abnormal exit situations. signal( SIGSEGV, abnormal_exit_handler ); @@ -1166,9 +1166,9 @@ int main( int argc, char **argv ) { is_consumer_explicit = 1; } - else if ( !strcmp( argv[ i ], "-disable-status-fifo" ) ) + else if ( !strcmp( argv[ i ], "-enable-status-fifo" ) ) { - status_fifo = 0; + status_fifo = 1; } } From c77e4a86a63991d7338673aaee76cc498a5ebc37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 22 Feb 2023 15:20:55 +0100 Subject: [PATCH 069/130] Actually, don't track mlt.cbp because that makes it harder to switch between our branch and upstream Update .gitignore though The same goes for mlt.depend This makes the difference between us and upstream smaller --- .gitignore | 2 + mlt.cbp | 1427 ---------------------------------------------------- mlt.depend | 57 --- 3 files changed, 2 insertions(+), 1484 deletions(-) delete mode 100644 mlt.cbp delete mode 100644 mlt.depend diff --git a/.gitignore b/.gitignore index 82fa4d4c4..264360789 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,5 @@ out/ src/modules/qt/mltqt_autogen/ src/modules/glaxnimate/mltglaxnimate_autogen/ mlt.layout +mlt.cbp +mlt.depend diff --git a/mlt.cbp b/mlt.cbp deleted file mode 100644 index 2e321efa8..000000000 --- a/mlt.cbp +++ /dev/null @@ -1,1427 +0,0 @@ - - - - - - diff --git a/mlt.depend b/mlt.depend deleted file mode 100644 index 408332cb8..000000000 --- a/mlt.depend +++ /dev/null @@ -1,57 +0,0 @@ -# depslib dependency file v1.0 -1653638752 source:/home/thardin/biz/jit/mlt/CMakeFiles/3.18.4/CompilerIdC/CMakeCCompilerId.c - -1653638752 source:/home/thardin/biz/jit/mlt/CMakeFiles/3.18.4/CompilerIdCXX/CMakeCXXCompilerId.cpp - -1665151040 source:/home/thardin/biz/jit/mlt/src/framework/mlt_animation.c - "mlt_animation.h" - "mlt_tokeniser.h" - "mlt_profile.h" - "mlt_factory.h" - "mlt_properties.h" - - - - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_animation.h - "mlt_types.h" - "mlt_property.h" - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_types.h - - - - "mlt_pool.h" - - - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_pool.h - -1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_property.h - "mlt_types.h" - - - - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_tokeniser.h - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_profile.h - "mlt_types.h" - -1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_factory.h - "mlt_types.h" - "mlt_profile.h" - "mlt_repository.h" - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_repository.h - "mlt_types.h" - "mlt_profile.h" - -1665151040 /home/thardin/biz/jit/mlt/src/framework/mlt_properties.h - "mlt_types.h" - "mlt_events.h" - - -1652169451 /home/thardin/biz/jit/mlt/src/framework/mlt_events.h - "mlt_types.h" - From f64f7ec717cce97aa208ba868158ff0fc2864060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 24 Feb 2023 14:49:11 +0100 Subject: [PATCH 070/130] Bring melt.c more in line with upstream --- src/melt/jit.c | 219 ++++++++++++++++++++++ src/melt/melt.c | 486 ++---------------------------------------------- 2 files changed, 239 insertions(+), 466 deletions(-) create mode 100644 src/melt/jit.c diff --git a/src/melt/jit.c b/src/melt/jit.c new file mode 100644 index 000000000..9b6c4f25c --- /dev/null +++ b/src/melt/jit.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include + +#include "jit.h" +#include "JitControl.pb-c.h" +#include "JitStatus.pb-c.h" + +static JitStatus jit_status = JIT_STATUS__INIT; +static int jit_status_fd = -1; +static double fps_multiplier; + +static void jit_action( mlt_producer producer, char *value ) +{ + mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); + mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); + mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); + mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); + + JitControl *const jit_control = (JitControl*) value; + switch (jit_control->type) { + case CONTROL_TYPE__PAUSE: + if (mlt_producer_get_speed( producer ) != 0) { + mlt_producer_set_speed( producer, 0 ); + mlt_consumer_purge( consumer ); + if (jit_status.playing) { + if (jit_control->has_seek_position) { + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); + } else { + //mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); + } + } + } + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + jit_status.playing = 0; + break; + case CONTROL_TYPE__PLAY: + if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { + mlt_producer_set_speed( producer, jit_control->play_rate ); + } + mlt_consumer_purge( consumer ); + mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); + jit_status.playing = 1; + break; + + case CONTROL_TYPE__PLAY_RATE: + mlt_producer_set_speed( producer, jit_control->play_rate ); + break; + + case CONTROL_TYPE__SEEK: + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); + fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); + break; + case CONTROL_TYPE__SEEK_REL: ; + const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, pos); + fire_jack_seek_event(jack, pos); + break; + case CONTROL_TYPE__QUIT: + mlt_properties_set_int( properties, "done", 1 ); + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + break; + default: + break; + } + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); +} + +static JitControl *read_control() { + static char *buf = NULL; + static int buf_len = 0; + + int len; + if (read(STDIN_FILENO, &len, 4) != 4) { + exit(3); + } + if (buf_len < len) { + buf = realloc(buf, len); + if (!buf) { + exit(4); + } + buf_len = len; + } + + for (int i = 0; i < len; ) { + const int r = read(STDIN_FILENO, buf + i, len - i); + if (r < 1) { + exit(5); + } + i += r; + } + return jit_control__unpack(NULL, len, buf); +} + +static void write_status(JitStatus *const jit_status) { + static char *buf = NULL; + static int buf_len = 0; + + if (jit_status_fd < 0) { + return; + } + + int len = jit_status__get_packed_size(jit_status); + if (buf_len < len) { + buf = realloc(buf, len); + if (!buf) { + perror("realloc"); + exit(1); + } + buf_len = len; + } + + jit_status__pack(jit_status, buf); + if (write(jit_status_fd, buf, len) != len) { + perror("write"); + exit(1); + } +} + +static mlt_producer find_producer_avformat(mlt_producer p) { + + mlt_tractor tractor = (mlt_tractor) p; + mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); + mlt_playlist playlist = (mlt_playlist) mlt_multitrack_track(multitrack, 0); + mlt_producer clip = mlt_playlist_get_clip(playlist, 0); + return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); +} + +static void dump_properties(mlt_properties p) { + for (int i = 0; i < mlt_properties_count(p); i++) { + char *name = mlt_properties_get_name(p, i); + printf("%s\n", name); + } +} + +static void open_status_pipe(void) { + jit_status_fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (jit_status_fd < 0) { + perror("socket"); + exit(2); + } + + struct sockaddr_un sun; + memset(&sun, 0, sizeof sun); + sun.sun_family = AF_UNIX; + sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Opening status socket: %s\n", sun.sun_path); + fflush(stdout); + + if (connect(jit_status_fd, (struct sockaddr *) &sun, sizeof sun) < 0) { + perror("connect"); + exit(2); + } + fprintf(stdout, "Status pipe opened\n"); + fflush(stdout); +} + +static void print_media_info(void) { + mlt_producer av = find_producer_avformat(melt); + jit_status.media_info = calloc(1, sizeof (MediaInfo)); + media_info__init(jit_status.media_info); + jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); + jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); + const int frame_rate_num = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_num"); + const int frame_rate_den = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_den"); + if (frame_rate_num > 0 && frame_rate_den > 0) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = ((double) frame_rate_num) / ((double) frame_rate_den); + } + for (int i = 0; i < jit_status.media_info->n_streams; i++) { + Stream *s = calloc(sizeof (Stream), 1); + stream__init(s); + jit_status.media_info->streams[i] = s; + s->has_type = 1; + s->type = STREAM_TYPE__UNKNOWN; + char key[100]; + sprintf(key, "meta.media.%d.stream.type", i); + char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (!value) { + continue; + } else if (!strcmp(value, "audio")) { + s->type = STREAM_TYPE__AUDIO; + s->audio = calloc(1, sizeof (AudioStream)); + audio_stream__init(s->audio); + sprintf(key, "meta.media.%d.codec.channels", i); + s->audio->has_channels = 1; + s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + jit_status.has_total_channels = 1; + jit_status.total_channels += s->audio->channels; + sprintf(key, "meta.attr.%d.stream.language.markup", i); + value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (value) { + s->audio->language = strdup(value); + } + } else if (!strcmp(value, "video")) { + s->type = STREAM_TYPE__VIDEO; + s->video = calloc(1, sizeof (VideoStream)); + video_stream__init(s->video); + sprintf(key, "meta.media.%d.stream.frame_rate", i); + s->video->has_frame_rate = 1; + s->video->frame_rate = mlt_properties_get_double(MLT_PRODUCER_PROPERTIES(av), key); + if (!jit_status.has_frame_rate) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = s->video->frame_rate; + } + sprintf(key, "meta.media.%d.codec.width", i); + s->video->has_width = 1; + s->video->width = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + sprintf(key, "meta.media.%d.codec.height", i); + s->video->has_height = 1; + s->video->height = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + } + } +} diff --git a/src/melt/melt.c b/src/melt/melt.c index 2099a5ed4..f3e11512a 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -20,7 +20,6 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include #include #include #include @@ -30,11 +29,6 @@ #include #include #include -#include -#include -#include -#include -#include #include @@ -43,13 +37,8 @@ #endif #include "io.h" -#include "JitControl.pb-c.h" -#include "JitStatus.pb-c.h" static mlt_producer melt = NULL; -static JitStatus jit_status = JIT_STATUS__INIT; -static int jit_status_fd = -1; -static double fps_multiplier; static void stop_handler(int signum) { @@ -74,268 +63,19 @@ static void fire_jack_seek_event(mlt_properties jack, int position) mlt_events_fire(jack, "jack-seek", mlt_event_data_from_int(position)); } +#include "jit.c" + static void transport_action( mlt_producer producer, char *value ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); - mlt_position position = producer ? mlt_producer_position( producer ) : 0; + mlt_position position = producer? mlt_producer_position( producer ) : 0; mlt_properties_set_int( properties, "stats_off", 1 ); - JitControl *const jit_control = (JitControl*) value; - switch (jit_control->type) { - case CONTROL_TYPE__PAUSE: - if (mlt_producer_get_speed( producer ) != 0) { - mlt_producer_set_speed( producer, 0 ); - mlt_consumer_purge( consumer ); - if (jit_status.playing) { - if (jit_control->has_seek_position) { - mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); - } else { - //mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); - } - } - } - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - jit_status.playing = 0; - break; - case CONTROL_TYPE__PLAY: - if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { - mlt_producer_set_speed( producer, jit_control->play_rate ); - } - mlt_consumer_purge( consumer ); - mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); - jit_status.playing = 1; - break; - - case CONTROL_TYPE__PLAY_RATE: - mlt_producer_set_speed( producer, jit_control->play_rate ); - break; - - case CONTROL_TYPE__SEEK: - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); - fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); - break; - case CONTROL_TYPE__SEEK_REL: ; - const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, pos); - fire_jack_seek_event(jack, pos); - break; - case CONTROL_TYPE__QUIT: - mlt_properties_set_int( properties, "done", 1 ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - break; - default: - break; - } - mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); - - /* - if ( strlen( value ) == 1 ) - { - switch( value[ 0 ] ) - { - case 'q': - case 'Q': - mlt_properties_set_int( properties, "done", 1 ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - break; - case '0': - position = 0; - mlt_producer_set_speed( producer, 1 ); - mlt_producer_seek( producer, position ); - mlt_consumer_purge( consumer ); - fire_jack_seek_event(jack, position); - break; - case '1': - mlt_producer_set_speed( producer, -10 ); - break; - case '2': - mlt_producer_set_speed( producer, -5 ); - break; - case '3': - mlt_producer_set_speed( producer, -2 ); - break; - case '4': - mlt_producer_set_speed( producer, -1 ); - break; - case '5': - mlt_producer_set_speed( producer, 0 ); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - break; - case '6': - case ' ': - if ( !jack || mlt_producer_get_speed( producer ) != 0 ) - mlt_producer_set_speed( producer, 1 ); - mlt_consumer_purge( consumer ); - mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); - break; - case '7': - mlt_producer_set_speed( producer, 2 ); - break; - case '8': - mlt_producer_set_speed( producer, 5 ); - break; - case '9': - mlt_producer_set_speed( producer, 10 ); - break; - case 'd': - if ( multitrack != NULL ) - { - int i = 0; - mlt_position last = -1; - fprintf( stderr, "\n" ); - for ( i = 0; 1; i ++ ) - { - position = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i ); - if ( position == last ) - break; - last = position; - fprintf( stderr, "%d: %d\n", i, (int)position ); - } - } - break; - - case 'g': - if ( multitrack != NULL ) - { - position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 ); - mlt_producer_seek( producer, position ); - mlt_consumer_purge( consumer ); - fire_jack_seek_event(jack, position); - } - break; - case 'H': - if ( producer != NULL ) - { - position -= mlt_producer_get_fps( producer ) * 60; - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - break; - case 'h': - if ( producer != NULL ) - { - position--; - mlt_producer_set_speed( producer, 0 ); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - fire_jack_seek_event(jack, position); - } - break; - case 'j': - if ( multitrack != NULL ) - { - position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 ); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - break; - case 'k': - if ( multitrack != NULL ) - { - position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 ); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - break; - case 'l': - if ( producer != NULL ) - { - position++; - mlt_consumer_purge( consumer ); - if ( mlt_producer_get_speed( producer ) != 0 ) - { - mlt_producer_set_speed( producer, 0 ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - } - else - { - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - } - break; - case 'L': - if ( producer != NULL ) - { - position += mlt_producer_get_fps( producer ) * 60; - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - break; - default: - if (producer) { - mlt_position len = mlt_producer_get_length(producer); - switch (value[0]) { - case 'z': - position = len; - break; - case 'Z': - position = 2 * len; - break; - case 'x': - position = 3 * len; - break; - case 'X': - position = 4 * len; - break; - case 'c': - position = 5 * len; - break; - case 'C': - position = 6 * len; - break; - case 'v': - position = 7 * len; - break; - case 'V': - position = 8 * len; - break; - case 'b': - position = 9 * len; - break; - case 'B': - position = 10 * len; - break; - case 'n': - position = 11 * len; - break; - case 'N': - position = 12 * len; - break; - case 'm': - position = 13 * len; - break; - case 'M': - position = 14 * len; - break; - default: - len = 0; - } - if (len) { - position /= 15; - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, position ); - fire_jack_seek_event(jack, position); - } - } - break; - } - - mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); - } */ + jit_action( producer, value ); mlt_properties_set_int( properties, "stats_off", 0 ); } @@ -419,9 +159,8 @@ static int load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc, qglsl = 1; #if SDL_MAJOR_VERSION == 2 if ( !strcmp("sdl", argv[i]) || !strcmp("sdl_audio", argv[i]) || !strcmp("sdl_preview", argv[i]) || !strcmp("sdl_still", argv[i]) ) { - /* fprintf(stderr, -"Error: This program was linked against SDL2, which is incompatible with\nSDL1 consumers. Aborting.\n");*/ +"Error: This program was linked against SDL2, which is incompatible with\nSDL1 consumers. Aborting.\n"); return EXIT_FAILURE; } #endif @@ -535,57 +274,6 @@ static void event_handling( mlt_producer producer, mlt_consumer consumer ) #endif -static JitControl *read_control() { - static char *buf = NULL; - static int buf_len = 0; - - int len; - if (read(STDIN_FILENO, &len, 4) != 4) { - exit(3); - } - if (buf_len < len) { - buf = realloc(buf, len); - if (!buf) { - exit(4); - } - buf_len = len; - } - - for (int i = 0; i < len; ) { - const int r = read(STDIN_FILENO, buf + i, len - i); - if (r < 1) { - exit(5); - } - i += r; - } - return jit_control__unpack(NULL, len, buf); -} - -static void write_status(JitStatus *const jit_status) { - static char *buf = NULL; - static int buf_len = 0; - - if (jit_status_fd < 0) { - return; - } - - int len = jit_status__get_packed_size(jit_status); - if (buf_len < len) { - buf = realloc(buf, len); - if (!buf) { - perror("realloc"); - exit(1); - } - buf_len = len; - } - - jit_status__pack(jit_status, buf); - if (write(jit_status_fd, buf, len) != len) { - perror("write"); - exit(1); - } -} - static void transport( mlt_producer producer, mlt_consumer consumer ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); @@ -595,9 +283,9 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) struct timespec tm = { 0, 40000000 }; int total_length = mlt_producer_get_playtime( producer ); int last_position = 0; - fd_set set; - struct timeval timeout; - int sel; + fd_set set; + struct timeval timeout; + int sel; if ( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { @@ -605,18 +293,6 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) { if ( !is_getc ) term_init( ); -/* - fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" ); - fprintf( stderr, "|1=-10| |2= -5| |3= -2| |4= -1| |5= 0| |6= 1| |7= 2| |8= 5| |9= 10|\n" ); - fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" ); - - fprintf( stderr, "+---------------------------------------------------------------------+\n" ); - fprintf( stderr, "| H = back 1 minute, L = forward 1 minute |\n" ); - fprintf( stderr, "| h = previous frame, l = next frame |\n" ); - fprintf( stderr, "| g = start of clip, j = next clip, k = previous clip |\n" ); - fprintf( stderr, "| 0 = restart, q = quit, space = play |\n" ); - fprintf( stderr, "+---------------------------------------------------------------------+\n" ); -*/ } // frame rate multiplier @@ -631,50 +307,17 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { - - //char string[2] = {0, 0}; - FD_ZERO(&set); - FD_SET(STDIN_FILENO, &set); - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0) { - /* - if (read(STDIN_FILENO, string, 1) != 1) { - string[0] = 'q'; - } - if (string[0] >= '!') { - transport_action( producer, string ); - } - */ + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0) { JitControl *const jit_control = read_control(); if (jit_control) { transport_action( producer, (char*) jit_control ); jit_control__free_unpacked(jit_control, NULL); } - } - - /* - char string[2] = {0, 0}; - int value = ( silent || progress || is_getc )? -1 : term_read( ); - if ( is_getc ) - { - do { - value = read(STDIN_FILENO, string, 1); - } while (value == 1 && string[0] < '!'); - if (value == 1) { - value = string[0]; - } else { - value = 'q'; - } - } - - if ( value != -1 ) - { - string[0] = value; - transport_action( producer, string ); } - */ - #if defined(SDL_MAJOR_VERSION) event_handling( producer, consumer ); @@ -688,6 +331,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) jit_status.play_rate = mlt_producer_get_speed(producer); jit_status.has_position = 1; jit_status.position = llround(mlt_producer_position(producer) / fps_multiplier); + if (jit_status.play_rate < 0 && jit_status.position == 0) { mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); @@ -696,8 +340,8 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) jit_status.position = 0; } - write_status(&jit_status); - last_position = jit_status.position; + write_status(&jit_status); + last_position = jit_status.position; } } } @@ -964,22 +608,6 @@ static void set_preview_scale(mlt_profile *profile, mlt_profile *backup_profile, } } -static mlt_producer find_producer_avformat(mlt_producer p) { - - mlt_tractor tractor = (mlt_tractor) p; - mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); - mlt_playlist playlist = (mlt_playlist) mlt_multitrack_track(multitrack, 0); - mlt_producer clip = mlt_playlist_get_clip(playlist, 0); - return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); -} - -static void dump_properties(mlt_properties p) { - for (int i = 0; i < mlt_properties_count(p); i++) { - char *name = mlt_properties_get_name(p, i); - printf("%s\n", name); - } -} - static mlt_repository setup_factory(const char* repo_path, int set_locale) { mlt_repository repo = mlt_factory_init(repo_path); @@ -1175,25 +803,7 @@ int main( int argc, char **argv ) // Open status pipe if (status_fifo) { - jit_status_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (jit_status_fd < 0) { - perror("socket"); - exit(2); - } - - struct sockaddr_un sun; - memset(&sun, 0, sizeof sun); - sun.sun_family = AF_UNIX; - sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Opening status socket: %s\n", sun.sun_path); - fflush(stdout); - - if (connect(jit_status_fd, (struct sockaddr *) &sun, sizeof sun) < 0) { - perror("connect"); - exit(2); - } - fprintf(stdout, "Status pipe opened\n"); - fflush(stdout); + open_status_pipe(); } if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress ) @@ -1271,69 +881,13 @@ int main( int argc, char **argv ) if ( store == NULL && consumer == NULL ) consumer = create_consumer( profile, NULL ); } - + // video is paused initially jit_status.has_playing = 1; jit_status.playing = status_fifo ? 0 : 1; // play automatically when status fifo is disabled // media info - mlt_producer av = find_producer_avformat(melt); - jit_status.media_info = calloc(1, sizeof (MediaInfo)); - media_info__init(jit_status.media_info); - jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); - jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); - const int frame_rate_num = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_num"); - const int frame_rate_den = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_den"); - if (frame_rate_num > 0 && frame_rate_den > 0) { - jit_status.has_frame_rate = 1; - jit_status.frame_rate = ((double) frame_rate_num) / ((double) frame_rate_den); - } - for (int i = 0; i < jit_status.media_info->n_streams; i++) { - Stream *s = calloc(sizeof (Stream), 1); - stream__init(s); - jit_status.media_info->streams[i] = s; - s->has_type = 1; - s->type = STREAM_TYPE__UNKNOWN; - char key[100]; - sprintf(key, "meta.media.%d.stream.type", i); - char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); - if (!value) { - continue; - } else if (!strcmp(value, "audio")) { - s->type = STREAM_TYPE__AUDIO; - s->audio = calloc(1, sizeof (AudioStream)); - audio_stream__init(s->audio); - sprintf(key, "meta.media.%d.codec.channels", i); - s->audio->has_channels = 1; - s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - jit_status.has_total_channels = 1; - jit_status.total_channels += s->audio->channels; - sprintf(key, "meta.attr.%d.stream.language.markup", i); - value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); - if (value) { - s->audio->language = strdup(value); - } - } else if (!strcmp(value, "video")) { - s->type = STREAM_TYPE__VIDEO; - s->video = calloc(1, sizeof (VideoStream)); - video_stream__init(s->video); - sprintf(key, "meta.media.%d.stream.frame_rate", i); - s->video->has_frame_rate = 1; - s->video->frame_rate = mlt_properties_get_double(MLT_PRODUCER_PROPERTIES(av), key); - if (!jit_status.has_frame_rate) { - jit_status.has_frame_rate = 1; - jit_status.frame_rate = s->video->frame_rate; - } - sprintf(key, "meta.media.%d.codec.width", i); - s->video->has_width = 1; - s->video->width = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - sprintf(key, "meta.media.%d.codec.height", i); - s->video->has_height = 1; - s->video->height = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - } - } - //dump_properties(av); - //exit(1); + print_media_info(); // Set transport properties on consumer and produder if ( consumer != NULL && melt != NULL ) @@ -1435,7 +989,7 @@ int main( int argc, char **argv ) } else if ( store != NULL && store != stdout && name != NULL ) { - //fprintf( stderr, "Project saved as %s.\n", name ); + fprintf( stderr, "Project saved as %s.\n", name ); fclose( store ); } } From dbc3a266a576bdef555098f746190df2b3e3816d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 24 Feb 2023 14:54:08 +0100 Subject: [PATCH 071/130] Oops --- src/melt/jit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 9b6c4f25c..36ce4773a 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -5,7 +5,6 @@ #include #include -#include "jit.h" #include "JitControl.pb-c.h" #include "JitStatus.pb-c.h" From 65fe7371ce4c289ee65c4b2b1c48a9f99b4180a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 24 Feb 2023 14:59:13 +0100 Subject: [PATCH 072/130] Generate protobuf files using CMake --- .gitignore | 4 + src/melt/CMakeLists.txt | 12 + src/melt/JitControl.pb-c.c | 154 ---------- src/melt/JitControl.pb-c.h | 86 ------ src/melt/JitStatus.pb-c.c | 597 ------------------------------------- src/melt/JitStatus.pb-c.h | 237 --------------- 6 files changed, 16 insertions(+), 1074 deletions(-) delete mode 100644 src/melt/JitControl.pb-c.c delete mode 100644 src/melt/JitControl.pb-c.h delete mode 100644 src/melt/JitStatus.pb-c.c delete mode 100644 src/melt/JitStatus.pb-c.h diff --git a/.gitignore b/.gitignore index 264360789..97717f57a 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,7 @@ src/modules/glaxnimate/mltglaxnimate_autogen/ mlt.layout mlt.cbp mlt.depend +src/melt/JitControl.pb-c.c +src/melt/JitControl.pb-c.h +src/melt/JitStatus.pb-c.c +src/melt/JitStatus.pb-c.h diff --git a/src/melt/CMakeLists.txt b/src/melt/CMakeLists.txt index c85355627..6152d3e93 100644 --- a/src/melt/CMakeLists.txt +++ b/src/melt/CMakeLists.txt @@ -1,3 +1,15 @@ +add_custom_command( + OUTPUT JitControl.pb-c.c + COMMAND protoc-c --c_out=. JitControl.proto + DEPENDS JitControl.proto +) + +add_custom_command( + OUTPUT JitStatus.pb-c.c + COMMAND protoc-c --c_out=. JitStatus.proto + DEPENDS JitStatus.proto +) + add_executable(melt melt.c io.c io.h JitControl.pb-c.c JitStatus.pb-c.c) target_compile_options(melt PRIVATE ${MLT_COMPILE_OPTIONS}) diff --git a/src/melt/JitControl.pb-c.c b/src/melt/JitControl.pb-c.c deleted file mode 100644 index accf5fba9..000000000 --- a/src/melt/JitControl.pb-c.c +++ /dev/null @@ -1,154 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: JitControl.proto */ - -/* Do not generate deprecated warnings for self */ -#ifndef PROTOBUF_C__NO_DEPRECATED -#define PROTOBUF_C__NO_DEPRECATED -#endif - -#include "JitControl.pb-c.h" -void jit_control__init - (JitControl *message) -{ - static const JitControl init_value = JIT_CONTROL__INIT; - *message = init_value; -} -size_t jit_control__get_packed_size - (const JitControl *message) -{ - assert(message->base.descriptor == &jit_control__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t jit_control__pack - (const JitControl *message, - uint8_t *out) -{ - assert(message->base.descriptor == &jit_control__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t jit_control__pack_to_buffer - (const JitControl *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &jit_control__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -JitControl * - jit_control__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (JitControl *) - protobuf_c_message_unpack (&jit_control__descriptor, - allocator, len, data); -} -void jit_control__free_unpacked - (JitControl *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &jit_control__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -static const ProtobufCFieldDescriptor jit_control__field_descriptors[3] = -{ - { - "type", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_ENUM, - offsetof(JitControl, has_type), - offsetof(JitControl, type), - &control_type__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "play_rate", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(JitControl, has_play_rate), - offsetof(JitControl, play_rate), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "seek_position", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT64, - offsetof(JitControl, has_seek_position), - offsetof(JitControl, seek_position), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned jit_control__field_indices_by_name[] = { - 1, /* field[1] = play_rate */ - 2, /* field[2] = seek_position */ - 0, /* field[0] = type */ -}; -static const ProtobufCIntRange jit_control__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor jit_control__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "JitControl", - "JitControl", - "JitControl", - "", - sizeof(JitControl), - 3, - jit_control__field_descriptors, - jit_control__field_indices_by_name, - 1, jit_control__number_ranges, - (ProtobufCMessageInit) jit_control__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCEnumValue control_type__enum_values_by_number[6] = -{ - { "PAUSE", "CONTROL_TYPE__PAUSE", 0 }, - { "PLAY", "CONTROL_TYPE__PLAY", 1 }, - { "PLAY_RATE", "CONTROL_TYPE__PLAY_RATE", 2 }, - { "QUIT", "CONTROL_TYPE__QUIT", 3 }, - { "SEEK", "CONTROL_TYPE__SEEK", 4 }, - { "SEEK_REL", "CONTROL_TYPE__SEEK_REL", 5 }, -}; -static const ProtobufCIntRange control_type__value_ranges[] = { -{0, 0},{0, 6} -}; -static const ProtobufCEnumValueIndex control_type__enum_values_by_name[6] = -{ - { "PAUSE", 0 }, - { "PLAY", 1 }, - { "PLAY_RATE", 2 }, - { "QUIT", 3 }, - { "SEEK", 4 }, - { "SEEK_REL", 5 }, -}; -const ProtobufCEnumDescriptor control_type__descriptor = -{ - PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, - "ControlType", - "ControlType", - "ControlType", - "", - 6, - control_type__enum_values_by_number, - 6, - control_type__enum_values_by_name, - 1, - control_type__value_ranges, - NULL,NULL,NULL,NULL /* reserved[1234] */ -}; diff --git a/src/melt/JitControl.pb-c.h b/src/melt/JitControl.pb-c.h deleted file mode 100644 index a47b676ea..000000000 --- a/src/melt/JitControl.pb-c.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: JitControl.proto */ - -#ifndef PROTOBUF_C_JitControl_2eproto__INCLUDED -#define PROTOBUF_C_JitControl_2eproto__INCLUDED - -#include - -PROTOBUF_C__BEGIN_DECLS - -#if PROTOBUF_C_VERSION_NUMBER < 1000000 -# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION -# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. -#endif - - -typedef struct JitControl JitControl; - - -/* --- enums --- */ - -typedef enum _ControlType { - CONTROL_TYPE__PAUSE = 0, - CONTROL_TYPE__PLAY = 1, - CONTROL_TYPE__PLAY_RATE = 2, - CONTROL_TYPE__QUIT = 3, - CONTROL_TYPE__SEEK = 4, - CONTROL_TYPE__SEEK_REL = 5 - PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(CONTROL_TYPE) -} ControlType; - -/* --- messages --- */ - -struct JitControl -{ - ProtobufCMessage base; - protobuf_c_boolean has_type; - ControlType type; - protobuf_c_boolean has_play_rate; - int32_t play_rate; - protobuf_c_boolean has_seek_position; - int64_t seek_position; -}; -#define JIT_CONTROL__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&jit_control__descriptor) \ - , 0, CONTROL_TYPE__PAUSE, 0, 0, 0, 0 } - - -/* JitControl methods */ -void jit_control__init - (JitControl *message); -size_t jit_control__get_packed_size - (const JitControl *message); -size_t jit_control__pack - (const JitControl *message, - uint8_t *out); -size_t jit_control__pack_to_buffer - (const JitControl *message, - ProtobufCBuffer *buffer); -JitControl * - jit_control__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void jit_control__free_unpacked - (JitControl *message, - ProtobufCAllocator *allocator); -/* --- per-message closures --- */ - -typedef void (*JitControl_Closure) - (const JitControl *message, - void *closure_data); - -/* --- services --- */ - - -/* --- descriptors --- */ - -extern const ProtobufCEnumDescriptor control_type__descriptor; -extern const ProtobufCMessageDescriptor jit_control__descriptor; - -PROTOBUF_C__END_DECLS - - -#endif /* PROTOBUF_C_JitControl_2eproto__INCLUDED */ diff --git a/src/melt/JitStatus.pb-c.c b/src/melt/JitStatus.pb-c.c deleted file mode 100644 index 8b546a9db..000000000 --- a/src/melt/JitStatus.pb-c.c +++ /dev/null @@ -1,597 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: JitStatus.proto */ - -/* Do not generate deprecated warnings for self */ -#ifndef PROTOBUF_C__NO_DEPRECATED -#define PROTOBUF_C__NO_DEPRECATED -#endif - -#include "JitStatus.pb-c.h" -void jit_status__init - (JitStatus *message) -{ - static const JitStatus init_value = JIT_STATUS__INIT; - *message = init_value; -} -size_t jit_status__get_packed_size - (const JitStatus *message) -{ - assert(message->base.descriptor == &jit_status__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t jit_status__pack - (const JitStatus *message, - uint8_t *out) -{ - assert(message->base.descriptor == &jit_status__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t jit_status__pack_to_buffer - (const JitStatus *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &jit_status__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -JitStatus * - jit_status__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (JitStatus *) - protobuf_c_message_unpack (&jit_status__descriptor, - allocator, len, data); -} -void jit_status__free_unpacked - (JitStatus *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &jit_status__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void media_info__init - (MediaInfo *message) -{ - static const MediaInfo init_value = MEDIA_INFO__INIT; - *message = init_value; -} -size_t media_info__get_packed_size - (const MediaInfo *message) -{ - assert(message->base.descriptor == &media_info__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t media_info__pack - (const MediaInfo *message, - uint8_t *out) -{ - assert(message->base.descriptor == &media_info__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t media_info__pack_to_buffer - (const MediaInfo *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &media_info__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -MediaInfo * - media_info__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (MediaInfo *) - protobuf_c_message_unpack (&media_info__descriptor, - allocator, len, data); -} -void media_info__free_unpacked - (MediaInfo *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &media_info__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void stream__init - (Stream *message) -{ - static const Stream init_value = STREAM__INIT; - *message = init_value; -} -size_t stream__get_packed_size - (const Stream *message) -{ - assert(message->base.descriptor == &stream__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t stream__pack - (const Stream *message, - uint8_t *out) -{ - assert(message->base.descriptor == &stream__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t stream__pack_to_buffer - (const Stream *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &stream__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -Stream * - stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (Stream *) - protobuf_c_message_unpack (&stream__descriptor, - allocator, len, data); -} -void stream__free_unpacked - (Stream *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &stream__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void audio_stream__init - (AudioStream *message) -{ - static const AudioStream init_value = AUDIO_STREAM__INIT; - *message = init_value; -} -size_t audio_stream__get_packed_size - (const AudioStream *message) -{ - assert(message->base.descriptor == &audio_stream__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t audio_stream__pack - (const AudioStream *message, - uint8_t *out) -{ - assert(message->base.descriptor == &audio_stream__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t audio_stream__pack_to_buffer - (const AudioStream *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &audio_stream__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -AudioStream * - audio_stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (AudioStream *) - protobuf_c_message_unpack (&audio_stream__descriptor, - allocator, len, data); -} -void audio_stream__free_unpacked - (AudioStream *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &audio_stream__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void video_stream__init - (VideoStream *message) -{ - static const VideoStream init_value = VIDEO_STREAM__INIT; - *message = init_value; -} -size_t video_stream__get_packed_size - (const VideoStream *message) -{ - assert(message->base.descriptor == &video_stream__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t video_stream__pack - (const VideoStream *message, - uint8_t *out) -{ - assert(message->base.descriptor == &video_stream__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t video_stream__pack_to_buffer - (const VideoStream *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &video_stream__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -VideoStream * - video_stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (VideoStream *) - protobuf_c_message_unpack (&video_stream__descriptor, - allocator, len, data); -} -void video_stream__free_unpacked - (VideoStream *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &video_stream__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -static const ProtobufCFieldDescriptor jit_status__field_descriptors[7] = -{ - { - "duration", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT64, - offsetof(JitStatus, has_duration), - offsetof(JitStatus, duration), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "frame_rate", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_DOUBLE, - offsetof(JitStatus, has_frame_rate), - offsetof(JitStatus, frame_rate), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "playing", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_BOOL, - offsetof(JitStatus, has_playing), - offsetof(JitStatus, playing), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "play_rate", - 4, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(JitStatus, has_play_rate), - offsetof(JitStatus, play_rate), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "position", - 5, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT64, - offsetof(JitStatus, has_position), - offsetof(JitStatus, position), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "total_channels", - 6, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(JitStatus, has_total_channels), - offsetof(JitStatus, total_channels), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "media_info", - 7, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(JitStatus, media_info), - &media_info__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned jit_status__field_indices_by_name[] = { - 0, /* field[0] = duration */ - 1, /* field[1] = frame_rate */ - 6, /* field[6] = media_info */ - 3, /* field[3] = play_rate */ - 2, /* field[2] = playing */ - 4, /* field[4] = position */ - 5, /* field[5] = total_channels */ -}; -static const ProtobufCIntRange jit_status__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 7 } -}; -const ProtobufCMessageDescriptor jit_status__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "JitStatus", - "JitStatus", - "JitStatus", - "", - sizeof(JitStatus), - 7, - jit_status__field_descriptors, - jit_status__field_indices_by_name, - 1, jit_status__number_ranges, - (ProtobufCMessageInit) jit_status__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor media_info__field_descriptors[1] = -{ - { - "streams", - 1, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(MediaInfo, n_streams), - offsetof(MediaInfo, streams), - &stream__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned media_info__field_indices_by_name[] = { - 0, /* field[0] = streams */ -}; -static const ProtobufCIntRange media_info__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor media_info__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "MediaInfo", - "MediaInfo", - "MediaInfo", - "", - sizeof(MediaInfo), - 1, - media_info__field_descriptors, - media_info__field_indices_by_name, - 1, media_info__number_ranges, - (ProtobufCMessageInit) media_info__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor stream__field_descriptors[3] = -{ - { - "type", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_ENUM, - offsetof(Stream, has_type), - offsetof(Stream, type), - &stream_type__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "audio", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(Stream, audio), - &audio_stream__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "video", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(Stream, video), - &video_stream__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned stream__field_indices_by_name[] = { - 1, /* field[1] = audio */ - 0, /* field[0] = type */ - 2, /* field[2] = video */ -}; -static const ProtobufCIntRange stream__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor stream__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "Stream", - "Stream", - "Stream", - "", - sizeof(Stream), - 3, - stream__field_descriptors, - stream__field_indices_by_name, - 1, stream__number_ranges, - (ProtobufCMessageInit) stream__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor audio_stream__field_descriptors[2] = -{ - { - "channels", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(AudioStream, has_channels), - offsetof(AudioStream, channels), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "language", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(AudioStream, language), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned audio_stream__field_indices_by_name[] = { - 0, /* field[0] = channels */ - 1, /* field[1] = language */ -}; -static const ProtobufCIntRange audio_stream__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor audio_stream__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "AudioStream", - "AudioStream", - "AudioStream", - "", - sizeof(AudioStream), - 2, - audio_stream__field_descriptors, - audio_stream__field_indices_by_name, - 1, audio_stream__number_ranges, - (ProtobufCMessageInit) audio_stream__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor video_stream__field_descriptors[3] = -{ - { - "frame_rate", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_DOUBLE, - offsetof(VideoStream, has_frame_rate), - offsetof(VideoStream, frame_rate), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "width", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(VideoStream, has_width), - offsetof(VideoStream, width), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "height", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_INT32, - offsetof(VideoStream, has_height), - offsetof(VideoStream, height), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned video_stream__field_indices_by_name[] = { - 0, /* field[0] = frame_rate */ - 2, /* field[2] = height */ - 1, /* field[1] = width */ -}; -static const ProtobufCIntRange video_stream__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor video_stream__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "VideoStream", - "VideoStream", - "VideoStream", - "", - sizeof(VideoStream), - 3, - video_stream__field_descriptors, - video_stream__field_indices_by_name, - 1, video_stream__number_ranges, - (ProtobufCMessageInit) video_stream__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCEnumValue stream_type__enum_values_by_number[3] = -{ - { "UNKNOWN", "STREAM_TYPE__UNKNOWN", 0 }, - { "AUDIO", "STREAM_TYPE__AUDIO", 1 }, - { "VIDEO", "STREAM_TYPE__VIDEO", 2 }, -}; -static const ProtobufCIntRange stream_type__value_ranges[] = { -{0, 0},{0, 3} -}; -static const ProtobufCEnumValueIndex stream_type__enum_values_by_name[3] = -{ - { "AUDIO", 1 }, - { "UNKNOWN", 0 }, - { "VIDEO", 2 }, -}; -const ProtobufCEnumDescriptor stream_type__descriptor = -{ - PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, - "StreamType", - "StreamType", - "StreamType", - "", - 3, - stream_type__enum_values_by_number, - 3, - stream_type__enum_values_by_name, - 1, - stream_type__value_ranges, - NULL,NULL,NULL,NULL /* reserved[1234] */ -}; diff --git a/src/melt/JitStatus.pb-c.h b/src/melt/JitStatus.pb-c.h deleted file mode 100644 index a6c3ade58..000000000 --- a/src/melt/JitStatus.pb-c.h +++ /dev/null @@ -1,237 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: JitStatus.proto */ - -#ifndef PROTOBUF_C_JitStatus_2eproto__INCLUDED -#define PROTOBUF_C_JitStatus_2eproto__INCLUDED - -#include - -PROTOBUF_C__BEGIN_DECLS - -#if PROTOBUF_C_VERSION_NUMBER < 1000000 -# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION -# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. -#endif - - -typedef struct JitStatus JitStatus; -typedef struct MediaInfo MediaInfo; -typedef struct Stream Stream; -typedef struct AudioStream AudioStream; -typedef struct VideoStream VideoStream; - - -/* --- enums --- */ - -typedef enum _StreamType { - STREAM_TYPE__UNKNOWN = 0, - STREAM_TYPE__AUDIO = 1, - STREAM_TYPE__VIDEO = 2 - PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(STREAM_TYPE) -} StreamType; - -/* --- messages --- */ - -struct JitStatus -{ - ProtobufCMessage base; - protobuf_c_boolean has_duration; - int64_t duration; - protobuf_c_boolean has_frame_rate; - double frame_rate; - protobuf_c_boolean has_playing; - protobuf_c_boolean playing; - protobuf_c_boolean has_play_rate; - int32_t play_rate; - protobuf_c_boolean has_position; - int64_t position; - protobuf_c_boolean has_total_channels; - int32_t total_channels; - MediaInfo *media_info; -}; -#define JIT_STATUS__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&jit_status__descriptor) \ - , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } - - -struct MediaInfo -{ - ProtobufCMessage base; - size_t n_streams; - Stream **streams; -}; -#define MEDIA_INFO__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&media_info__descriptor) \ - , 0,NULL } - - -struct Stream -{ - ProtobufCMessage base; - protobuf_c_boolean has_type; - StreamType type; - AudioStream *audio; - VideoStream *video; -}; -#define STREAM__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&stream__descriptor) \ - , 0, STREAM_TYPE__UNKNOWN, NULL, NULL } - - -struct AudioStream -{ - ProtobufCMessage base; - protobuf_c_boolean has_channels; - int32_t channels; - char *language; -}; -#define AUDIO_STREAM__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&audio_stream__descriptor) \ - , 0, 0, NULL } - - -struct VideoStream -{ - ProtobufCMessage base; - protobuf_c_boolean has_frame_rate; - double frame_rate; - protobuf_c_boolean has_width; - int32_t width; - protobuf_c_boolean has_height; - int32_t height; -}; -#define VIDEO_STREAM__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&video_stream__descriptor) \ - , 0, 0, 0, 0, 0, 0 } - - -/* JitStatus methods */ -void jit_status__init - (JitStatus *message); -size_t jit_status__get_packed_size - (const JitStatus *message); -size_t jit_status__pack - (const JitStatus *message, - uint8_t *out); -size_t jit_status__pack_to_buffer - (const JitStatus *message, - ProtobufCBuffer *buffer); -JitStatus * - jit_status__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void jit_status__free_unpacked - (JitStatus *message, - ProtobufCAllocator *allocator); -/* MediaInfo methods */ -void media_info__init - (MediaInfo *message); -size_t media_info__get_packed_size - (const MediaInfo *message); -size_t media_info__pack - (const MediaInfo *message, - uint8_t *out); -size_t media_info__pack_to_buffer - (const MediaInfo *message, - ProtobufCBuffer *buffer); -MediaInfo * - media_info__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void media_info__free_unpacked - (MediaInfo *message, - ProtobufCAllocator *allocator); -/* Stream methods */ -void stream__init - (Stream *message); -size_t stream__get_packed_size - (const Stream *message); -size_t stream__pack - (const Stream *message, - uint8_t *out); -size_t stream__pack_to_buffer - (const Stream *message, - ProtobufCBuffer *buffer); -Stream * - stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void stream__free_unpacked - (Stream *message, - ProtobufCAllocator *allocator); -/* AudioStream methods */ -void audio_stream__init - (AudioStream *message); -size_t audio_stream__get_packed_size - (const AudioStream *message); -size_t audio_stream__pack - (const AudioStream *message, - uint8_t *out); -size_t audio_stream__pack_to_buffer - (const AudioStream *message, - ProtobufCBuffer *buffer); -AudioStream * - audio_stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void audio_stream__free_unpacked - (AudioStream *message, - ProtobufCAllocator *allocator); -/* VideoStream methods */ -void video_stream__init - (VideoStream *message); -size_t video_stream__get_packed_size - (const VideoStream *message); -size_t video_stream__pack - (const VideoStream *message, - uint8_t *out); -size_t video_stream__pack_to_buffer - (const VideoStream *message, - ProtobufCBuffer *buffer); -VideoStream * - video_stream__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void video_stream__free_unpacked - (VideoStream *message, - ProtobufCAllocator *allocator); -/* --- per-message closures --- */ - -typedef void (*JitStatus_Closure) - (const JitStatus *message, - void *closure_data); -typedef void (*MediaInfo_Closure) - (const MediaInfo *message, - void *closure_data); -typedef void (*Stream_Closure) - (const Stream *message, - void *closure_data); -typedef void (*AudioStream_Closure) - (const AudioStream *message, - void *closure_data); -typedef void (*VideoStream_Closure) - (const VideoStream *message, - void *closure_data); - -/* --- services --- */ - - -/* --- descriptors --- */ - -extern const ProtobufCEnumDescriptor stream_type__descriptor; -extern const ProtobufCMessageDescriptor jit_status__descriptor; -extern const ProtobufCMessageDescriptor media_info__descriptor; -extern const ProtobufCMessageDescriptor stream__descriptor; -extern const ProtobufCMessageDescriptor audio_stream__descriptor; -extern const ProtobufCMessageDescriptor video_stream__descriptor; - -PROTOBUF_C__END_DECLS - - -#endif /* PROTOBUF_C_JitStatus_2eproto__INCLUDED */ From 2068e0dd710f72b81513cbf2f53e5ea75cb8d7c1 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 13:51:37 +0200 Subject: [PATCH 073/130] generate protobuf headers --- src/melt/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/melt/CMakeLists.txt b/src/melt/CMakeLists.txt index 6152d3e93..8fcade1b7 100644 --- a/src/melt/CMakeLists.txt +++ b/src/melt/CMakeLists.txt @@ -1,11 +1,11 @@ add_custom_command( - OUTPUT JitControl.pb-c.c + OUTPUT JitControl.pb-c.c JitControl.pb-c.h COMMAND protoc-c --c_out=. JitControl.proto DEPENDS JitControl.proto ) add_custom_command( - OUTPUT JitStatus.pb-c.c + OUTPUT JitStatus.pb-c.c JitStatus.pb-c.h COMMAND protoc-c --c_out=. JitStatus.proto DEPENDS JitStatus.proto ) From 9d9e90097c6681c4931fe4f3244a7345dd7bdb3c Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 14:13:54 +0200 Subject: [PATCH 074/130] refactor data transport --- src/melt/jit.c | 38 +++++++++++++++++--------------------- src/melt/melt.c | 16 ++++------------ 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 36ce4773a..8ebf2ee0f 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -71,29 +71,25 @@ static void jit_action( mlt_producer producer, char *value ) } static JitControl *read_control() { - static char *buf = NULL; - static int buf_len = 0; - - int len; - if (read(STDIN_FILENO, &len, 4) != 4) { - exit(3); - } - if (buf_len < len) { - buf = realloc(buf, len); - if (!buf) { - exit(4); - } - buf_len = len; + static char buf[1 * 1024 * 1024]; // 1 MB + fd_set set; + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) <= 0) { + return NULL; } - - for (int i = 0; i < len; ) { - const int r = read(STDIN_FILENO, buf + i, len - i); - if (r < 1) { - exit(5); - } - i += r; + const ssize_t r = read(jit_status_fd, buf, sizeof buf); + if (r < 1) { + perror("read"); + exit(1); + } else if (r == sizeof buf) { + fprintf(stderr, "read buffer overflow\n"); + exit(1); } - return jit_control__unpack(NULL, len, buf); + return jit_control__unpack(NULL, sizeof buf, buf); } static void write_status(JitStatus *const jit_status) { diff --git a/src/melt/melt.c b/src/melt/melt.c index f3e11512a..8acb5df8e 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -283,8 +283,6 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) struct timespec tm = { 0, 40000000 }; int total_length = mlt_producer_get_playtime( producer ); int last_position = 0; - fd_set set; - struct timeval timeout; int sel; if ( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) @@ -307,16 +305,10 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) ) { - FD_ZERO(&set); - FD_SET(STDIN_FILENO, &set); - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0) { - JitControl *const jit_control = read_control(); - if (jit_control) { - transport_action( producer, (char*) jit_control ); - jit_control__free_unpacked(jit_control, NULL); - } + JitControl *const jit_control = read_control(); + if (jit_control) { + transport_action( producer, (char*) jit_control ); + jit_control__free_unpacked(jit_control, NULL); } #if defined(SDL_MAJOR_VERSION) From 71a15836ab0446dab59336e2fc84f6f85571fbbf Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 15:45:02 +0200 Subject: [PATCH 075/130] idebug --- src/melt/jit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 8ebf2ee0f..970e9a92e 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -78,9 +78,12 @@ static JitControl *read_control() { struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; + fprintf(stderr, "will read yo\n"); if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) <= 0) { + fprintf(stderr, "no deal\n"); return NULL; } + fprintf(stderr, "yaaay!\n"); const ssize_t r = read(jit_status_fd, buf, sizeof buf); if (r < 1) { perror("read"); @@ -151,7 +154,7 @@ static void open_status_pipe(void) { perror("connect"); exit(2); } - fprintf(stdout, "Status pipe opened\n"); + fprintf(stdout, "Status socket opened\n"); fflush(stdout); } From 944940add3a6e5a4614e11fd71715753f1878ed3 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:02:50 +0200 Subject: [PATCH 076/130] trial --- src/melt/jit.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 970e9a92e..b31d5f155 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -72,22 +72,26 @@ static void jit_action( mlt_producer producer, char *value ) static JitControl *read_control() { static char buf[1 * 1024 * 1024]; // 1 MB - fd_set set; - FD_ZERO(&set); - FD_SET(STDIN_FILENO, &set); + + struct sockaddr_un sun; + memset(&sun, 0, sizeof sun); + sun.sun_family = AF_UNIX; + sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); + socklen_t len = sizeof sun; + struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; + fprintf(stderr, "will read yo\n"); - if (select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) <= 0) { - fprintf(stderr, "no deal\n"); - return NULL; - } - fprintf(stderr, "yaaay!\n"); - const ssize_t r = read(jit_status_fd, buf, sizeof buf); + setsockopt(jit_status_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout); + const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &sun, &len); if (r < 1) { - perror("read"); - exit(1); + if (r < 1) { + perror("recvfrom"); + exit(1); + } + return NULL; } else if (r == sizeof buf) { fprintf(stderr, "read buffer overflow\n"); exit(1); From 7ab039f00a7e917fca2e2c192154193a4fd6a797 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:08:25 +0200 Subject: [PATCH 077/130] test --- src/melt/jit.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index b31d5f155..28bc830be 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -87,10 +87,7 @@ static JitControl *read_control() { setsockopt(jit_status_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout); const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &sun, &len); if (r < 1) { - if (r < 1) { - perror("recvfrom"); - exit(1); - } + perror("recvfrom"); return NULL; } else if (r == sizeof buf) { fprintf(stderr, "read buffer overflow\n"); From a5646a0ea36111496284400a4fe8cf04209db773 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:16:00 +0200 Subject: [PATCH 078/130] mofy --- src/melt/jit.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 28bc830be..fe44c5784 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -72,23 +72,22 @@ static void jit_action( mlt_producer producer, char *value ) static JitControl *read_control() { static char buf[1 * 1024 * 1024]; // 1 MB - - struct sockaddr_un sun; - memset(&sun, 0, sizeof sun); - sun.sun_family = AF_UNIX; - sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); - socklen_t len = sizeof sun; - + fd_set set; + FD_ZERO(&set); + FD_SET(jit_status_fd, &set); struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; - fprintf(stderr, "will read yo\n"); - setsockopt(jit_status_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout); - const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &sun, &len); - if (r < 1) { - perror("recvfrom"); + if (select(jit_status_fd + 1, &set, NULL, NULL, &timeout) <= 0) { + fprintf(stderr, "no deal\n"); return NULL; + } + fprintf(stderr, "yaaay!\n"); + const ssize_t r = read(jit_status_fd, buf, sizeof buf); + if (r < 1) { + perror("read"); + exit(1); } else if (r == sizeof buf) { fprintf(stderr, "read buffer overflow\n"); exit(1); From 5836c7228d50220831c79e33bd6dc3184759725e Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:27:45 +0200 Subject: [PATCH 079/130] new attempt --- src/melt/jit.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index fe44c5784..da766c767 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -12,6 +12,10 @@ static JitStatus jit_status = JIT_STATUS__INIT; static int jit_status_fd = -1; static double fps_multiplier; +static struct sockaddr_un client_sun; +static socklen_t client_sun_len = 0; + + static void jit_action( mlt_producer producer, char *value ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); @@ -84,7 +88,9 @@ static JitControl *read_control() { return NULL; } fprintf(stderr, "yaaay!\n"); - const ssize_t r = read(jit_status_fd, buf, sizeof buf); + + client_sun_len = sizeof client_sun; + const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &client_sun, &client_sun_len); if (r < 1) { perror("read"); exit(1); @@ -92,6 +98,7 @@ static JitControl *read_control() { fprintf(stderr, "read buffer overflow\n"); exit(1); } + fprintf(stderr, "time to unpack!\n"); return jit_control__unpack(NULL, sizeof buf, buf); } @@ -114,10 +121,12 @@ static void write_status(JitStatus *const jit_status) { } jit_status__pack(jit_status, buf); - if (write(jit_status_fd, buf, len) != len) { - perror("write"); - exit(1); - } + if (client_sun_len > 0) { + if (sendto(jit_status_fd, buf, len, 0, (struct sockaddr*) &client_sun, client_sun_len) != len) { + perror("sendto"); + exit(1); + } + } } static mlt_producer find_producer_avformat(mlt_producer p) { @@ -146,15 +155,15 @@ static void open_status_pipe(void) { struct sockaddr_un sun; memset(&sun, 0, sizeof sun); sun.sun_family = AF_UNIX; - sprintf(sun.sun_path, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Opening status socket: %s\n", sun.sun_path); + snprintf(sun.sun_path, sizeof sun, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Creating status socket: %s\n", sun.sun_path); fflush(stdout); - if (connect(jit_status_fd, (struct sockaddr *) &sun, sizeof sun) < 0) { - perror("connect"); - exit(2); - } - fprintf(stdout, "Status socket opened\n"); + if (bind(jit_status_fd, (struct sockaddr*) &sun, sizeof sun) < 0) { + perror("bind"); + exit(2); + } + fprintf(stdout, "Status socket created\n"); fflush(stdout); } From b85384e37c9821e4615240876980cc262a908365 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:45:55 +0200 Subject: [PATCH 080/130] this time! --- src/melt/jit.c | 4 ++-- src/melt/melt.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index da766c767..1bdb23645 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -99,7 +99,7 @@ static JitControl *read_control() { exit(1); } fprintf(stderr, "time to unpack!\n"); - return jit_control__unpack(NULL, sizeof buf, buf); + return jit_control__unpack(NULL, r, buf); } static void write_status(JitStatus *const jit_status) { @@ -120,8 +120,8 @@ static void write_status(JitStatus *const jit_status) { buf_len = len; } - jit_status__pack(jit_status, buf); if (client_sun_len > 0) { + jit_status__pack(jit_status, buf); if (sendto(jit_status_fd, buf, len, 0, (struct sockaddr*) &client_sun, client_sun_len) != len) { perror("sendto"); exit(1); diff --git a/src/melt/melt.c b/src/melt/melt.c index 8acb5df8e..3c76c3092 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -307,6 +307,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) { JitControl *const jit_control = read_control(); if (jit_control) { + fprintf(stderr, "korv!\n"); transport_action( producer, (char*) jit_control ); jit_control__free_unpacked(jit_control, NULL); } From 0917bc32ad7a682fb2bb0d3afa25a0c9c8ec7d6e Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:52:51 +0200 Subject: [PATCH 081/130] remove debug print --- src/melt/jit.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 1bdb23645..04722857b 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -12,8 +12,8 @@ static JitStatus jit_status = JIT_STATUS__INIT; static int jit_status_fd = -1; static double fps_multiplier; -static struct sockaddr_un client_sun; -static socklen_t client_sun_len = 0; +static struct sockaddr_un client_addr; +static socklen_t client_addr_len = 0; static void jit_action( mlt_producer producer, char *value ) @@ -82,15 +82,12 @@ static JitControl *read_control() { struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; - fprintf(stderr, "will read yo\n"); if (select(jit_status_fd + 1, &set, NULL, NULL, &timeout) <= 0) { - fprintf(stderr, "no deal\n"); return NULL; } - fprintf(stderr, "yaaay!\n"); - client_sun_len = sizeof client_sun; - const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &client_sun, &client_sun_len); + client_addr_len = sizeof client_addr; + const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &client_addr, &client_addr_len); if (r < 1) { perror("read"); exit(1); @@ -98,7 +95,6 @@ static JitControl *read_control() { fprintf(stderr, "read buffer overflow\n"); exit(1); } - fprintf(stderr, "time to unpack!\n"); return jit_control__unpack(NULL, r, buf); } @@ -120,9 +116,9 @@ static void write_status(JitStatus *const jit_status) { buf_len = len; } - if (client_sun_len > 0) { + if (client_addr_len > 0) { jit_status__pack(jit_status, buf); - if (sendto(jit_status_fd, buf, len, 0, (struct sockaddr*) &client_sun, client_sun_len) != len) { + if (sendto(jit_status_fd, buf, len, 0, (struct sockaddr*) &client_addr, client_addr_len) != len) { perror("sendto"); exit(1); } @@ -152,14 +148,13 @@ static void open_status_pipe(void) { exit(2); } - struct sockaddr_un sun; - memset(&sun, 0, sizeof sun); - sun.sun_family = AF_UNIX; - snprintf(sun.sun_path, sizeof sun, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Creating status socket: %s\n", sun.sun_path); + memset(&client_addr, 0, sizeof client_addr); + client_addr.sun_family = AF_UNIX; + snprintf(client_addr.sun_path, sizeof client_addr, "/tmp/jit-status-%lld", (long long) getppid()); + fprintf(stdout, "Creating status socket: %s\n", client_addr.sun_path); fflush(stdout); - if (bind(jit_status_fd, (struct sockaddr*) &sun, sizeof sun) < 0) { + if (bind(jit_status_fd, (struct sockaddr*) &client_addr, sizeof client_addr) < 0) { perror("bind"); exit(2); } From fdfbe5013e7c93a8148ea5da1d1f2c87ed9fed3b Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Thu, 11 May 2023 16:59:36 +0200 Subject: [PATCH 082/130] remove debug print --- src/melt/melt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/melt/melt.c b/src/melt/melt.c index 3c76c3092..8acb5df8e 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -307,7 +307,6 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) { JitControl *const jit_control = read_control(); if (jit_control) { - fprintf(stderr, "korv!\n"); transport_action( producer, (char*) jit_control ); jit_control__free_unpacked(jit_control, NULL); } From 40eeb8ed09b67c717c7f3c626a7910b9f80b498e Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Fri, 12 May 2023 10:10:11 +0200 Subject: [PATCH 083/130] refactor --- src/melt/jit.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 04722857b..507342623 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -9,11 +9,11 @@ #include "JitStatus.pb-c.h" static JitStatus jit_status = JIT_STATUS__INIT; -static int jit_status_fd = -1; static double fps_multiplier; -static struct sockaddr_un client_addr; -static socklen_t client_addr_len = 0; +static int melt_sock_fd = -1; // UNIX domain socket for melt/jit messaging +static struct sockaddr_un jit_sock_addr; // last known socket address of jit +static socklen_t jit_sock_addr_len = 0; static void jit_action( mlt_producer producer, char *value ) @@ -78,16 +78,16 @@ static JitControl *read_control() { static char buf[1 * 1024 * 1024]; // 1 MB fd_set set; FD_ZERO(&set); - FD_SET(jit_status_fd, &set); + FD_SET(melt_sock_fd, &set); struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; - if (select(jit_status_fd + 1, &set, NULL, NULL, &timeout) <= 0) { + if (select(melt_sock_fd + 1, &set, NULL, NULL, &timeout) <= 0) { return NULL; } - client_addr_len = sizeof client_addr; - const ssize_t r = recvfrom(jit_status_fd, buf, sizeof buf, 0, (struct sockaddr*) &client_addr, &client_addr_len); + jit_sock_addr_len = sizeof jit_sock_addr; + const ssize_t r = recvfrom(melt_sock_fd, buf, sizeof buf, 0, (struct sockaddr*) &jit_sock_addr, &jit_sock_addr_len); if (r < 1) { perror("read"); exit(1); @@ -102,7 +102,7 @@ static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; - if (jit_status_fd < 0) { + if (melt_sock_fd < 0) { return; } @@ -116,9 +116,9 @@ static void write_status(JitStatus *const jit_status) { buf_len = len; } - if (client_addr_len > 0) { + if (jit_sock_addr_len > 0) { jit_status__pack(jit_status, buf); - if (sendto(jit_status_fd, buf, len, 0, (struct sockaddr*) &client_addr, client_addr_len) != len) { + if (sendto(melt_sock_fd, buf, len, 0, (struct sockaddr*) &jit_sock_addr, jit_sock_addr_len) != len) { perror("sendto"); exit(1); } @@ -142,19 +142,19 @@ static void dump_properties(mlt_properties p) { } static void open_status_pipe(void) { - jit_status_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (jit_status_fd < 0) { + melt_sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (melt_sock_fd < 0) { perror("socket"); exit(2); } - memset(&client_addr, 0, sizeof client_addr); - client_addr.sun_family = AF_UNIX; - snprintf(client_addr.sun_path, sizeof client_addr, "/tmp/jit-status-%lld", (long long) getppid()); - fprintf(stdout, "Creating status socket: %s\n", client_addr.sun_path); + memset(&jit_sock_addr, 0, sizeof jit_sock_addr); + jit_sock_addr.sun_family = AF_UNIX; + snprintf(jit_sock_addr.sun_path, sizeof jit_sock_addr, "/tmp/melt-sock-%lld", (long long) getppid()); + fprintf(stdout, "Creating status socket: %s\n", jit_sock_addr.sun_path); fflush(stdout); - if (bind(jit_status_fd, (struct sockaddr*) &client_addr, sizeof client_addr) < 0) { + if (bind(melt_sock_fd, (struct sockaddr*) &jit_sock_addr, sizeof jit_sock_addr) < 0) { perror("bind"); exit(2); } From f7688b52b2d344f1c3e47bb9c6a06b1ae99c51f8 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 12 Feb 2024 14:52:41 +0100 Subject: [PATCH 084/130] null check --- src/melt/melt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/melt/melt.c b/src/melt/melt.c index 8acb5df8e..2ad918f20 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -67,6 +67,10 @@ static void fire_jack_seek_event(mlt_properties jack, int position) static void transport_action( mlt_producer producer, char *value ) { + if (!(producer && value)) { + return; + } + mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); From fd8e5ba2871cf4d3716fab5544f5d1a38ebab4ec Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Mon, 12 Feb 2024 15:44:06 +0100 Subject: [PATCH 085/130] more error checking --- src/melt/jit.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index 507342623..f7a8f386d 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -82,7 +82,7 @@ static JitControl *read_control() { struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; - if (select(melt_sock_fd + 1, &set, NULL, NULL, &timeout) <= 0) { + if (melt_sock_fd < 0 || select(melt_sock_fd + 1, &set, NULL, NULL, &timeout) <= 0) { return NULL; } @@ -102,7 +102,7 @@ static void write_status(JitStatus *const jit_status) { static char *buf = NULL; static int buf_len = 0; - if (melt_sock_fd < 0) { + if (melt_sock_fd < 0 || jit_sock_addr_len <= 0) { return; } @@ -116,12 +116,10 @@ static void write_status(JitStatus *const jit_status) { buf_len = len; } - if (jit_sock_addr_len > 0) { - jit_status__pack(jit_status, buf); - if (sendto(melt_sock_fd, buf, len, 0, (struct sockaddr*) &jit_sock_addr, jit_sock_addr_len) != len) { - perror("sendto"); - exit(1); - } + jit_status__pack(jit_status, buf); + if (sendto(melt_sock_fd, buf, len, 0, (struct sockaddr*) &jit_sock_addr, jit_sock_addr_len) != len) { + perror("sendto"); + exit(1); } } From 025afafa8e7bbafebd32651b6895ee68ec1c825b Mon Sep 17 00:00:00 2001 From: j-b-m Date: Tue, 27 Feb 2024 20:44:47 +0100 Subject: [PATCH 086/130] Also check for Wayland's WAYLAND_DISPLAY to detect a graphical session (#972) * Also check for Wayland's WAYLAND_DISPLAY to detect a graphical session * Correct error message on missing graphical session --- src/modules/glaxnimate/producer_glaxnimate.cpp | 6 +++--- src/modules/qt/common.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/glaxnimate/producer_glaxnimate.cpp b/src/modules/glaxnimate/producer_glaxnimate.cpp index dbf406a0e..12fe403ca 100644 --- a/src/modules/glaxnimate/producer_glaxnimate.cpp +++ b/src/modules/glaxnimate/producer_glaxnimate.cpp @@ -140,11 +140,11 @@ static bool createQApplicationIfNeeded(mlt_service service) + QStringLiteral("/plugins")); #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - if (getenv("DISPLAY") == 0) { + if (getenv("DISPLAY") == 0 && getenv("WAYLAND_DISPLAY") == 0) { mlt_log_error( service, - "The MLT Qt module requires a X11 environment.\n" - "Please either run melt from an X session or use a fake X server like xvfb:\n" + "The MLT Glaxnimate module requires a X11 or Wayland environment.\n" + "Please either run melt from a session with a display server or use a fake X server like xvfb:\n" "xvfb-run -a melt (...)\n"); return false; } diff --git a/src/modules/qt/common.cpp b/src/modules/qt/common.cpp index 60ffea067..02d45f51f 100644 --- a/src/modules/qt/common.cpp +++ b/src/modules/qt/common.cpp @@ -36,11 +36,11 @@ bool createQApplicationIfNeeded(mlt_service service) + QStringLiteral("/plugins")); #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) - if (getenv("DISPLAY") == 0) { + if (getenv("DISPLAY") == 0 && getenv("WAYLAND_DISPLAY") == 0) { mlt_log_error( service, - "The MLT Qt module requires a X11 environment.\n" - "Please either run melt from an X session or use a fake X server like xvfb:\n" + "The MLT Qt module requires a X11 or Wayland environment.\n" + "Please either run melt from a session with a display server or use a fake X server like xvfb:\n" "xvfb-run -a melt (...)\n"); return false; } From 0f8841c13d4a76077ebc985e0307d827569a6884 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 28 Feb 2024 20:29:34 -0800 Subject: [PATCH 087/130] fix wave filter distorts on wave=1 with preview scaling --- src/modules/kdenlive/filter_wave.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/kdenlive/filter_wave.c b/src/modules/kdenlive/filter_wave.c index fea0b16a1..af0bcb2ab 100644 --- a/src/modules/kdenlive/filter_wave.c +++ b/src/modules/kdenlive/filter_wave.c @@ -2,7 +2,7 @@ * wave.c -- wave filter * Copyright (C) ?-2007 Leny Grisel * Copyright (C) 2007 Jean-Baptiste Mardelle - * Copyright (c) 2022 Meltytech, LLC + * Copyright (c) 2022-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -139,7 +139,7 @@ static int filter_get_image(mlt_frame frame, desc.dst = dst; desc.position = position; desc.speed = speed; - desc.factor = factor; + desc.factor = MAX(factor, 1); desc.deformX = deformX; desc.deformY = deformY; mlt_slices_run_normal(0, do_wave_slice_proc, &desc); From 30115615b3a4487724c6878ee70c3ec0fd890426 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 28 Feb 2024 20:29:47 -0800 Subject: [PATCH 088/130] clang-format --- src/modules/glaxnimate/producer_glaxnimate.cpp | 10 +++++----- src/modules/qt/common.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/glaxnimate/producer_glaxnimate.cpp b/src/modules/glaxnimate/producer_glaxnimate.cpp index 12fe403ca..556918e49 100644 --- a/src/modules/glaxnimate/producer_glaxnimate.cpp +++ b/src/modules/glaxnimate/producer_glaxnimate.cpp @@ -141,11 +141,11 @@ static bool createQApplicationIfNeeded(mlt_service service) #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) if (getenv("DISPLAY") == 0 && getenv("WAYLAND_DISPLAY") == 0) { - mlt_log_error( - service, - "The MLT Glaxnimate module requires a X11 or Wayland environment.\n" - "Please either run melt from a session with a display server or use a fake X server like xvfb:\n" - "xvfb-run -a melt (...)\n"); + mlt_log_error(service, + "The MLT Glaxnimate module requires a X11 or Wayland environment.\n" + "Please either run melt from a session with a display server or use a " + "fake X server like xvfb:\n" + "xvfb-run -a melt (...)\n"); return false; } #endif diff --git a/src/modules/qt/common.cpp b/src/modules/qt/common.cpp index 02d45f51f..a8aad0076 100644 --- a/src/modules/qt/common.cpp +++ b/src/modules/qt/common.cpp @@ -37,11 +37,11 @@ bool createQApplicationIfNeeded(mlt_service service) #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) if (getenv("DISPLAY") == 0 && getenv("WAYLAND_DISPLAY") == 0) { - mlt_log_error( - service, - "The MLT Qt module requires a X11 or Wayland environment.\n" - "Please either run melt from a session with a display server or use a fake X server like xvfb:\n" - "xvfb-run -a melt (...)\n"); + mlt_log_error(service, + "The MLT Qt module requires a X11 or Wayland environment.\n" + "Please either run melt from a session with a display server or use a " + "fake X server like xvfb:\n" + "xvfb-run -a melt (...)\n"); return false; } #endif From 11a89df3f9180be4115e1b6e8f82b4e813d340f0 Mon Sep 17 00:00:00 2001 From: Brian Matherly Date: Fri, 8 Mar 2024 22:20:08 -0600 Subject: [PATCH 089/130] Report the channel layout so the application can use it --- src/modules/avformat/producer_avformat.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 09007d93f..9573aeed8 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -519,6 +519,15 @@ static mlt_properties find_default_streams(producer_avformat self) mlt_properties_set_int(meta_media, key, codec_params->sample_rate); snprintf(key, sizeof(key), "meta.media.%u.codec.channels", i); mlt_properties_set_int(meta_media, key, codec_params->channels); + snprintf(key, sizeof(key), "meta.media.%u.codec.layout", i); + mlt_channel_layout mlt_layout = mlt_channel_independent; + if (codec_params->channel_layout == 0) + mlt_layout = av_channel_layout_to_mlt( + av_get_default_channel_layout(codec_params->channels)); + else + mlt_layout = av_channel_layout_to_mlt(codec_params->channel_layout); + char *layout = mlt_audio_channel_layout_name(mlt_layout); + mlt_properties_set(meta_media, key, layout); break; default: break; From 7930382303eb2c1c044bd68e8b40dcf99e5a9b63 Mon Sep 17 00:00:00 2001 From: Brian Matherly Date: Fri, 8 Mar 2024 22:20:36 -0600 Subject: [PATCH 090/130] Set the channel layout for some audio producers This will avoid an unnecessary downmix step if the requested channel layout is not the default for the channel count --- src/modules/core/producer_noise.c | 5 +++++ src/modules/core/producer_tone.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/modules/core/producer_noise.c b/src/modules/core/producer_noise.c index 046f661e1..4b4389b8d 100644 --- a/src/modules/core/producer_noise.c +++ b/src/modules/core/producer_noise.c @@ -160,6 +160,11 @@ static int producer_get_audio(mlt_frame frame, // Set the buffer for destruction mlt_frame_set_audio(frame, *buffer, *format, size, mlt_pool_release); + mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame); + mlt_properties_set(frame_properties, + "channel_layout", + mlt_properties_get(frame_properties, "consumer.channel_layout")); + return 0; } diff --git a/src/modules/core/producer_tone.c b/src/modules/core/producer_tone.c index 7ddae53e6..364c9f0f0 100644 --- a/src/modules/core/producer_tone.c +++ b/src/modules/core/producer_tone.c @@ -72,6 +72,11 @@ static int producer_get_audio(mlt_frame frame, // Set the buffer for destruction mlt_frame_set_audio(frame, *buffer, *format, size, mlt_pool_release); + mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame); + mlt_properties_set(frame_properties, + "channel_layout", + mlt_properties_get(frame_properties, "consumer.channel_layout")); + return 0; } From ab761ae05bee3f58ade05d54353e56f8208db4fa Mon Sep 17 00:00:00 2001 From: Hernan Martinez Date: Sat, 9 Mar 2024 20:08:51 -0700 Subject: [PATCH 091/130] Avoid FAST_FAIL_RANGE_CHECK_FAILURE at preset enumeration (#974) --- src/framework/mlt_repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/mlt_repository.c b/src/framework/mlt_repository.c index e1efcf56b..aaae7ea4b 100644 --- a/src/framework/mlt_repository.c +++ b/src/framework/mlt_repository.c @@ -581,7 +581,7 @@ static void list_presets(mlt_properties properties, const char *path, const char // load the preset mlt_properties preset = mlt_properties_load(fullname); if (preset && mlt_properties_count(preset)) { - snprintf(fullname, 1024, "%s/%s", path, de->d_name); + snprintf(fullname, sizeof(fullname), "%s/%s", path, de->d_name); mlt_properties_set_data(properties, fullname, preset, From 6a06b3218fcbeae44ab20145a0308360059012b6 Mon Sep 17 00:00:00 2001 From: Brian Matherly Date: Wed, 13 Mar 2024 21:10:51 -0500 Subject: [PATCH 092/130] Fix crash when using chains from melt Regression caused by 2df4fc8 --- src/modules/core/producer_melt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/core/producer_melt.c b/src/modules/core/producer_melt.c index 8057b5c0a..1a0e634b0 100644 --- a/src/modules/core/producer_melt.c +++ b/src/modules/core/producer_melt.c @@ -439,7 +439,6 @@ mlt_producer producer_melt_init(mlt_profile profile, } if (producer != NULL && chain != NULL) { mlt_chain_set_source(chain, producer); - mlt_producer_close(producer); mlt_chain_attach_normalizers(chain); producer = MLT_CHAIN_PRODUCER(chain); } else if (producer != NULL) { From 0ceb9b6970c25dcadfb02cce53e01997fcd34e29 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sun, 17 Mar 2024 22:28:20 -0700 Subject: [PATCH 093/130] fix #976 outline maximum for text & dynamictext filters These filters do not inherently have a maximum outline size. Only the pango producer has a maximum . --- src/modules/plus/filter_dynamictext.yml | 1 - src/modules/plus/filter_text.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/src/modules/plus/filter_dynamictext.yml b/src/modules/plus/filter_dynamictext.yml index 4175451b8..3327d35f2 100644 --- a/src/modules/plus/filter_dynamictext.yml +++ b/src/modules/plus/filter_dynamictext.yml @@ -136,7 +136,6 @@ parameters: readonly: no default: 0 minimum: 0 - maximum: 3 mutable: yes widget: spinner diff --git a/src/modules/plus/filter_text.yml b/src/modules/plus/filter_text.yml index e00a338f0..ddbbf14ba 100644 --- a/src/modules/plus/filter_text.yml +++ b/src/modules/plus/filter_text.yml @@ -117,7 +117,6 @@ parameters: readonly: no default: 0 minimum: 0 - maximum: 3 mutable: yes widget: spinner From 92840ba8fb3e1a6375a90d91b78ac8c83395ac33 Mon Sep 17 00:00:00 2001 From: Johan Westerlund Date: Tue, 19 Mar 2024 18:40:53 +0100 Subject: [PATCH 094/130] Add missing KEEP_ALIVE cmd --- src/melt/JitControl.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/src/melt/JitControl.proto b/src/melt/JitControl.proto index b8638bb85..f82049a78 100644 --- a/src/melt/JitControl.proto +++ b/src/melt/JitControl.proto @@ -13,4 +13,5 @@ enum ControlType { QUIT = 3; SEEK = 4; SEEK_REL = 5; + KEEP_ALIVE = 6; } From e896a41da0859bf297b76bfa26a6cc4cd2db3740 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Tue, 19 Mar 2024 17:39:06 -0700 Subject: [PATCH 095/130] add ambisonic-encoder filter to spatialaudio module --- src/modules/spatialaudio/CMakeLists.txt | 12 +- src/modules/spatialaudio/factory.c | 98 ++-- .../spatialaudio/filter_ambisonic-decoder.cpp | 508 +++++++++--------- .../spatialaudio/filter_ambisonic-encoder.cpp | 179 ++++++ .../spatialaudio/filter_ambisonic-encoder.yml | 40 ++ 5 files changed, 535 insertions(+), 302 deletions(-) create mode 100644 src/modules/spatialaudio/filter_ambisonic-encoder.cpp create mode 100644 src/modules/spatialaudio/filter_ambisonic-encoder.yml diff --git a/src/modules/spatialaudio/CMakeLists.txt b/src/modules/spatialaudio/CMakeLists.txt index 58c80aada..5919c9499 100644 --- a/src/modules/spatialaudio/CMakeLists.txt +++ b/src/modules/spatialaudio/CMakeLists.txt @@ -1,4 +1,8 @@ -add_library(mltspatialaudio MODULE factory.c filter_ambisonic-decoder.cpp) +add_library(mltspatialaudio MODULE + factory.c + filter_ambisonic-decoder.cpp + filter_ambisonic-encoder.cpp +) file(GLOB YML "*.yml") add_custom_target(Other_spatialaudio_Files SOURCES @@ -13,4 +17,8 @@ set_target_properties(mltspatialaudio PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${MLT install(TARGETS mltspatialaudio LIBRARY DESTINATION ${MLT_INSTALL_MODULE_DIR}) -install(FILES filter_ambisonic-decoder.yml DESTINATION ${MLT_INSTALL_DATA_DIR}/spatialaudio) +install(FILES + filter_ambisonic-decoder.yml + filter_ambisonic-encoder.yml + DESTINATION ${MLT_INSTALL_DATA_DIR}/spatialaudio +) diff --git a/src/modules/spatialaudio/factory.c b/src/modules/spatialaudio/factory.c index 29729dd77..a282d8bc5 100644 --- a/src/modules/spatialaudio/factory.c +++ b/src/modules/spatialaudio/factory.c @@ -1,46 +1,52 @@ -/* - * factory.c -- the factory method interfaces - * Copyright (C) 2024 Meltytech, LLC - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -extern mlt_filter filter_ambisonic_decoder_init(mlt_profile profile, - mlt_service_type type, - const char *id, - char *arg); - -static mlt_properties metadata(mlt_service_type type, const char *id, void *data) -{ - char file[PATH_MAX]; - mlt_properties result = NULL; - - // Load the yaml file - snprintf(file, PATH_MAX, "%s/spatialaudio/filter_%s.yml", mlt_environment("MLT_DATA"), id); - result = mlt_properties_parse_yaml(file); - - return result; -} - -MLT_REPOSITORY -{ - MLT_REGISTER(mlt_service_filter_type, "ambisonic-decoder", filter_ambisonic_decoder_init); - MLT_REGISTER_METADATA(mlt_service_filter_type, "ambisonic-decoder", metadata, NULL); -} +/* + * factory.c -- the factory method interfaces + * Copyright (C) 2024 Meltytech, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +extern mlt_filter filter_ambisonic_decoder_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg); +extern mlt_filter filter_ambisonic_encoder_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg); + +static mlt_properties metadata(mlt_service_type type, const char *id, void *data) +{ + char file[PATH_MAX]; + mlt_properties result = NULL; + + // Load the yaml file + snprintf(file, PATH_MAX, "%s/spatialaudio/filter_%s.yml", mlt_environment("MLT_DATA"), id); + result = mlt_properties_parse_yaml(file); + + return result; +} + +MLT_REPOSITORY +{ + MLT_REGISTER(mlt_service_filter_type, "ambisonic-decoder", filter_ambisonic_decoder_init); + MLT_REGISTER_METADATA(mlt_service_filter_type, "ambisonic-decoder", metadata, NULL); + MLT_REGISTER(mlt_service_filter_type, "ambisonic-encoder", filter_ambisonic_encoder_init); + MLT_REGISTER_METADATA(mlt_service_filter_type, "ambisonic-encoder", metadata, NULL); +} diff --git a/src/modules/spatialaudio/filter_ambisonic-decoder.cpp b/src/modules/spatialaudio/filter_ambisonic-decoder.cpp index 9b93d0a32..e7d3f925a 100644 --- a/src/modules/spatialaudio/filter_ambisonic-decoder.cpp +++ b/src/modules/spatialaudio/filter_ambisonic-decoder.cpp @@ -1,254 +1,254 @@ -/* - * filter_ambisonic-decoder.cpp -- decode ambisonic audio to speaker channels - * Copyright (C) 2024 Meltytech, LLC - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -static const auto MAX_CHANNELS = 6; -static const auto AMBISONICS_BLOCK_SIZE = 1024; -static const auto AMBISONICS_ORDER = 1; -static const auto AMBISONICS_1_CHANNELS = 4; - -extern "C" { -static mlt_frame process(mlt_filter filter, mlt_frame frame); -static void close_filter(mlt_filter filter); -} - -class SpatialAudio -{ -private: - mlt_filter m_filter; - CAmbisonicBinauralizer binauralizer; - unsigned tailLength; - CAmbisonicDecoder decoder; - CAmbisonicProcessor processor; - CAmbisonicZoomer zoomer; - float *speakers[MAX_CHANNELS]; - -public: - SpatialAudio() - { - m_filter = mlt_filter_new(); - if (m_filter) { - m_filter->child = this; - m_filter->close = close_filter; - m_filter->process = process; - } - } - - ~SpatialAudio() - { - m_filter->child = nullptr; - m_filter->close = nullptr; - m_filter->parent.close = nullptr; - mlt_service_close(MLT_FILTER_SERVICE(m_filter)); - m_filter = nullptr; - } - - mlt_filter filter() { return m_filter; } - mlt_properties properties() { return MLT_FILTER_PROPERTIES(filter()); } - double getDouble(const char *name, int position, int length) - { - return mlt_properties_anim_get_double(properties(), name, position, length); - } - - bool getAudio(mlt_frame frame, float *buffer, int samples, int channels) - { - bool error = false; - bool binaural = channels >= 2 && mlt_properties_get_int(properties(), "binaural"); - - // First time setup - if (binaural && !binauralizer.GetChannelCount()) { - mlt_log_verbose(MLT_FILTER_SERVICE(filter()), - "configuring spatial audio binauralizer\n"); - error = !binauralizer.Configure(AMBISONICS_ORDER, - true, - mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame), - "audio_frequency"), - samples, - tailLength); - if (!error) { - binauralizer.Reset(); - } else { - mlt_log_error(MLT_FILTER_SERVICE(filter()), - "failed to configure spatial audio binauralizer\n"); - } - } else if (!binaural && !decoder.GetChannelCount()) { - mlt_log_verbose(MLT_FILTER_SERVICE(filter()), - "configuring spatial audio decoder for %d channels\n", - channels); - error = !decoder.Configure(AMBISONICS_ORDER, - true, - AMBISONICS_BLOCK_SIZE, - channels == 6 ? kAmblib_51 - : channels == 2 ? kAmblib_Stereo - : channels == 4 ? kAmblib_Quad - : kAmblib_CustomSpeakerSetUp, - channels); - if (!error) { - mlt_log_verbose(MLT_FILTER_SERVICE(filter()), - "configuring spatial audio processor\n"); - error = !processor.Configure(AMBISONICS_ORDER, true, AMBISONICS_BLOCK_SIZE, 0); - if (!error) { - mlt_log_verbose(MLT_FILTER_SERVICE(filter()), - "configuring spatial audio zoomer\n"); - error = !zoomer.Configure(AMBISONICS_ORDER, true, AMBISONICS_BLOCK_SIZE, 0); - if (error) { - mlt_log_error(MLT_FILTER_SERVICE(filter()), - "failed to configure spatial audio zoomer\n"); - } - } else { - mlt_log_error(MLT_FILTER_SERVICE(filter()), - "failed to configure spatial audio processor\n"); - } - } else { - mlt_log_error(MLT_FILTER_SERVICE(filter()), - "failed to configure spatial audio decoder\n"); - } - } - - // Processing - if (!error) { - CBFormat bformat; - bformat.Configure(AMBISONICS_ORDER, true, samples); - for (unsigned i = 0; i < AMBISONICS_1_CHANNELS; ++i) - bformat.InsertStream(&buffer[samples * i], i, samples); - - if (!binaural) { - mlt_position position = mlt_filter_get_position(filter(), frame); - mlt_position length = mlt_filter_get_length2(filter(), frame); - processor.SetOrientation({-DegreesToRadians(getDouble("yaw", position, length)), - DegreesToRadians(getDouble("pitch", position, length)), - DegreesToRadians(getDouble("roll", position, length))}); - processor.Refresh(); - processor.Process(&bformat, samples); - zoomer.SetZoom(getDouble("zoom", position, length)); - zoomer.Refresh(); - zoomer.Process(&bformat, samples); - } - - if (channels == 6) { - // libspatialaudio has a different channel order for 5.1 - speakers[0] = &buffer[samples * 0]; // left - speakers[1] = &buffer[samples * 1]; // right - speakers[2] = &buffer[samples * 4]; // center - speakers[3] = &buffer[samples * 5]; // LFE (subwoofer) - speakers[4] = &buffer[samples * 2]; // left surround - speakers[5] = &buffer[samples * 3]; // right surround - decoder.Process(&bformat, samples, speakers); - } else if (channels == 4 && mlt_properties_get_int(properties(), "ambisonic")) { - for (int i = 0; i < channels; ++i) - bformat.ExtractStream(&buffer[samples * i], i, samples); - } else { - for (int i = 0; i < channels; ++i) - speakers[i] = &buffer[samples * i]; - if (binaural) { - binauralizer.Process(&bformat, speakers, samples); - if (channels > 2) { - for (int i = 2; i < channels; ++i) - ::memset(speakers[i], 0, samples * sizeof(float)); - } - } else { - decoder.Process(&bformat, samples, speakers); - } - } - } - return error; - } -}; - -extern "C" { - -static int get_audio(mlt_frame frame, - void **buffer, - mlt_audio_format *format, - int *frequency, - int *channels, - int *samples) -{ - auto error = 0; - // Get the filter service - mlt_filter filter = (mlt_filter) mlt_frame_pop_audio(frame); - - mlt_service_lock(MLT_FILTER_SERVICE(filter)); - - // Get the producer's audio - if (*channels > 1) { - *format = mlt_audio_float; - int requestChannels = MAX(AMBISONICS_1_CHANNELS, *channels); - auto properties = MLT_FRAME_PROPERTIES(frame); - auto channel_layout = mlt_audio_channel_layout_id( - mlt_properties_get(properties, "consumer.channel_layout")); - mlt_properties_set(MLT_FRAME_PROPERTIES(frame), - "consumer.channel_layout", - mlt_audio_channel_layout_name(mlt_channel_independent)); - - error = mlt_frame_get_audio(frame, buffer, format, frequency, &requestChannels, samples); - - // Restore the saved channel layout - mlt_properties_set(properties, - "consumer.channel_layout", - mlt_audio_channel_layout_name(channel_layout)); - - if (!error && requestChannels >= AMBISONICS_1_CHANNELS) { - auto spatial = static_cast(filter->child); - error = spatial->getAudio(frame, static_cast(*buffer), *samples, *channels); - } - } else { - // pass through mono - error = mlt_frame_get_audio(frame, buffer, format, frequency, channels, samples); - } - - mlt_service_unlock(MLT_FILTER_SERVICE(filter)); - - return error; -} - -static mlt_frame process(mlt_filter filter, mlt_frame frame) -{ - if (mlt_frame_is_test_audio(frame) == 0) { - // Add the filter to the frame - mlt_frame_push_audio(frame, filter); - mlt_frame_push_audio(frame, (void *) get_audio); - } - return frame; -} - -static void close_filter(mlt_filter filter) -{ - delete reinterpret_cast(filter->child); -} - -mlt_filter filter_ambisonic_decoder_init(mlt_profile profile, - mlt_service_type type, - const char *id, - char *arg) -{ - mlt_filter filter = nullptr; - auto *spatial = new SpatialAudio; - - if (spatial) { - filter = spatial->filter(); - if (!filter) - delete spatial; - } - return filter; -} - -} // extern +/* + * filter_ambisonic-decoder.cpp -- decode ambisonic audio to speaker channels + * Copyright (C) 2024 Meltytech, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +static const auto MAX_CHANNELS = 6; +static const auto AMBISONICS_BLOCK_SIZE = 1024; +static const auto AMBISONICS_ORDER = 1; +static const auto AMBISONICS_1_CHANNELS = 4; + +extern "C" { +static mlt_frame process(mlt_filter filter, mlt_frame frame); +static void close_filter(mlt_filter filter); +} + +class SpatialAudio +{ +private: + mlt_filter m_filter; + CAmbisonicBinauralizer binauralizer; + unsigned tailLength; + CAmbisonicDecoder decoder; + CAmbisonicProcessor processor; + CAmbisonicZoomer zoomer; + float *speakers[MAX_CHANNELS]; + +public: + SpatialAudio() + { + m_filter = mlt_filter_new(); + if (m_filter) { + m_filter->child = this; + m_filter->close = close_filter; + m_filter->process = process; + } + } + + ~SpatialAudio() + { + m_filter->child = nullptr; + m_filter->close = nullptr; + m_filter->parent.close = nullptr; + mlt_service_close(MLT_FILTER_SERVICE(m_filter)); + m_filter = nullptr; + } + + mlt_filter filter() { return m_filter; } + mlt_properties properties() { return MLT_FILTER_PROPERTIES(filter()); } + double getDouble(const char *name, int position, int length) + { + return mlt_properties_anim_get_double(properties(), name, position, length); + } + + bool getAudio(mlt_frame frame, float *buffer, int samples, int channels) + { + bool error = false; + bool binaural = channels >= 2 && mlt_properties_get_int(properties(), "binaural"); + + // First time setup + if (binaural && !binauralizer.GetChannelCount()) { + mlt_log_verbose(MLT_FILTER_SERVICE(filter()), + "configuring spatial audio binauralizer\n"); + error = !binauralizer.Configure(AMBISONICS_ORDER, + true, + mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame), + "audio_frequency"), + samples, + tailLength); + if (!error) { + binauralizer.Reset(); + } else { + mlt_log_error(MLT_FILTER_SERVICE(filter()), + "failed to configure spatial audio binauralizer\n"); + } + } else if (!binaural && !decoder.GetChannelCount()) { + mlt_log_verbose(MLT_FILTER_SERVICE(filter()), + "configuring spatial audio decoder for %d channels\n", + channels); + error = !decoder.Configure(AMBISONICS_ORDER, + true, + AMBISONICS_BLOCK_SIZE, + channels == 6 ? kAmblib_51 + : channels == 2 ? kAmblib_Stereo + : channels == 4 ? kAmblib_Quad + : kAmblib_CustomSpeakerSetUp, + channels); + if (!error) { + mlt_log_verbose(MLT_FILTER_SERVICE(filter()), + "configuring spatial audio processor\n"); + error = !processor.Configure(AMBISONICS_ORDER, true, AMBISONICS_BLOCK_SIZE, 0); + if (!error) { + mlt_log_verbose(MLT_FILTER_SERVICE(filter()), + "configuring spatial audio zoomer\n"); + error = !zoomer.Configure(AMBISONICS_ORDER, true, AMBISONICS_BLOCK_SIZE, 0); + if (error) { + mlt_log_error(MLT_FILTER_SERVICE(filter()), + "failed to configure spatial audio zoomer\n"); + } + } else { + mlt_log_error(MLT_FILTER_SERVICE(filter()), + "failed to configure spatial audio processor\n"); + } + } else { + mlt_log_error(MLT_FILTER_SERVICE(filter()), + "failed to configure spatial audio decoder\n"); + } + } + + // Processing + if (!error) { + CBFormat bformat; + bformat.Configure(AMBISONICS_ORDER, true, samples); + for (unsigned i = 0; i < AMBISONICS_1_CHANNELS; ++i) + bformat.InsertStream(&buffer[samples * i], i, samples); + + if (!binaural) { + mlt_position position = mlt_filter_get_position(filter(), frame); + mlt_position length = mlt_filter_get_length2(filter(), frame); + processor.SetOrientation({-DegreesToRadians(getDouble("yaw", position, length)), + DegreesToRadians(getDouble("pitch", position, length)), + DegreesToRadians(getDouble("roll", position, length))}); + processor.Refresh(); + processor.Process(&bformat, samples); + zoomer.SetZoom(getDouble("zoom", position, length)); + zoomer.Refresh(); + zoomer.Process(&bformat, samples); + } + + if (channels == 6) { + // libspatialaudio has a different channel order for 5.1 + speakers[0] = &buffer[samples * 0]; // left + speakers[1] = &buffer[samples * 1]; // right + speakers[2] = &buffer[samples * 4]; // center + speakers[3] = &buffer[samples * 5]; // LFE (subwoofer) + speakers[4] = &buffer[samples * 2]; // left surround + speakers[5] = &buffer[samples * 3]; // right surround + decoder.Process(&bformat, samples, speakers); + } else if (channels == 4 && mlt_properties_get_int(properties(), "ambisonic")) { + for (int i = 0; i < channels; ++i) + bformat.ExtractStream(&buffer[samples * i], i, samples); + } else { + for (int i = 0; i < channels; ++i) + speakers[i] = &buffer[samples * i]; + if (binaural) { + binauralizer.Process(&bformat, speakers, samples); + if (channels > 2) { + for (int i = 2; i < channels; ++i) + ::memset(speakers[i], 0, samples * sizeof(float)); + } + } else { + decoder.Process(&bformat, samples, speakers); + } + } + } + return error; + } +}; + +extern "C" { + +static int get_audio(mlt_frame frame, + void **buffer, + mlt_audio_format *format, + int *frequency, + int *channels, + int *samples) +{ + auto error = 0; + // Get the filter service + mlt_filter filter = (mlt_filter) mlt_frame_pop_audio(frame); + + mlt_service_lock(MLT_FILTER_SERVICE(filter)); + + // Get the producer's audio + if (*channels > 1) { + *format = mlt_audio_float; + int requestChannels = MAX(AMBISONICS_1_CHANNELS, *channels); + auto properties = MLT_FRAME_PROPERTIES(frame); + auto channel_layout = mlt_audio_channel_layout_id( + mlt_properties_get(properties, "consumer.channel_layout")); + mlt_properties_set(MLT_FRAME_PROPERTIES(frame), + "consumer.channel_layout", + mlt_audio_channel_layout_name(mlt_channel_independent)); + + error = mlt_frame_get_audio(frame, buffer, format, frequency, &requestChannels, samples); + + // Restore the saved channel layout + mlt_properties_set(properties, + "consumer.channel_layout", + mlt_audio_channel_layout_name(channel_layout)); + + if (!error && requestChannels >= AMBISONICS_1_CHANNELS) { + auto spatial = static_cast(filter->child); + error = spatial->getAudio(frame, static_cast(*buffer), *samples, *channels); + } + } else { + // pass through mono + error = mlt_frame_get_audio(frame, buffer, format, frequency, channels, samples); + } + + mlt_service_unlock(MLT_FILTER_SERVICE(filter)); + + return error; +} + +static mlt_frame process(mlt_filter filter, mlt_frame frame) +{ + if (mlt_frame_is_test_audio(frame) == 0) { + // Add the filter to the frame + mlt_frame_push_audio(frame, filter); + mlt_frame_push_audio(frame, (void *) get_audio); + } + return frame; +} + +static void close_filter(mlt_filter filter) +{ + delete reinterpret_cast(filter->child); +} + +mlt_filter filter_ambisonic_decoder_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg) +{ + mlt_filter filter = nullptr; + auto *spatial = new SpatialAudio; + + if (spatial) { + filter = spatial->filter(); + if (!filter) + delete spatial; + } + return filter; +} + +} // extern diff --git a/src/modules/spatialaudio/filter_ambisonic-encoder.cpp b/src/modules/spatialaudio/filter_ambisonic-encoder.cpp new file mode 100644 index 000000000..a89c7f0d4 --- /dev/null +++ b/src/modules/spatialaudio/filter_ambisonic-encoder.cpp @@ -0,0 +1,179 @@ +/* + * filter_ambisonic-encoder.cpp -- position mono and stero sound in ambisonic space + * Copyright (C) 2024 Meltytech, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +// static const auto MAX_CHANNELS = 6; +static const auto AMBISONICS_ORDER = 1; +static const auto AMBISONICS_1_CHANNELS = 4; + +extern "C" { +static mlt_frame process(mlt_filter filter, mlt_frame frame); +static void close_filter(mlt_filter filter); +} + +class SpatialAudioEncoder +{ +private: + mlt_filter m_filter; + CAmbisonicEncoder encoder; + +public: + SpatialAudioEncoder() + { + m_filter = mlt_filter_new(); + if (m_filter) { + m_filter->child = this; + m_filter->close = close_filter; + m_filter->process = process; + } + } + + ~SpatialAudioEncoder() + { + m_filter->child = nullptr; + m_filter->close = nullptr; + m_filter->parent.close = nullptr; + mlt_service_close(MLT_FILTER_SERVICE(m_filter)); + m_filter = nullptr; + } + + mlt_filter filter() { return m_filter; } + mlt_properties properties() { return MLT_FILTER_PROPERTIES(filter()); } + double getDouble(const char *name, int position, int length) + { + return mlt_properties_anim_get_double(properties(), name, position, length); + } + + bool getAudio(mlt_frame frame, float *buffer, int samples, int channels) + { + bool error = false; + + // First time setup + if (!encoder.GetOrder()) { + mlt_log_verbose(MLT_FILTER_SERVICE(filter()), "configuring spatial audio encoder\n"); + error = !encoder.Configure(AMBISONICS_ORDER, true, 0); + if (error) { + mlt_log_error(MLT_FILTER_SERVICE(filter()), + "failed to configure spatial audio encoder\n"); + } + } + + // Processing + if (!error) { + CBFormat bformat; + PolarPoint polar; + mlt_position position = mlt_filter_get_position(filter(), frame); + mlt_position length = mlt_filter_get_length2(filter(), frame); + + bformat.Configure(AMBISONICS_ORDER, true, samples); + polar.fAzimuth = -DegreesToRadians(getDouble("azimuth", position, length)); + polar.fElevation = DegreesToRadians(getDouble("elevation", position, length)); + polar.fDistance = getDouble("distance", position, length); + encoder.SetPosition(polar, 1.f); + encoder.Refresh(); + encoder.Process(buffer, samples, &bformat); + for (int i = 0; i < AMBISONICS_1_CHANNELS; ++i) + bformat.ExtractStream(&buffer[samples * i], i, samples); + for (int i = AMBISONICS_1_CHANNELS; i < channels; ++i) + ::memset(&buffer[samples * i], 0, samples * sizeof(float)); + } + return error; + } +}; + +extern "C" { + +static int get_audio(mlt_frame frame, + void **buffer, + mlt_audio_format *format, + int *frequency, + int *channels, + int *samples) +{ + auto error = 0; + // Get the filter service + mlt_filter filter = (mlt_filter) mlt_frame_pop_audio(frame); + + mlt_service_lock(MLT_FILTER_SERVICE(filter)); + + // Get the producer's audio + if (*channels >= AMBISONICS_1_CHANNELS) { + *format = mlt_audio_float; + auto properties = MLT_FRAME_PROPERTIES(frame); + auto channel_layout = mlt_audio_channel_layout_id( + mlt_properties_get(properties, "consumer.channel_layout")); + mlt_properties_set(MLT_FRAME_PROPERTIES(frame), + "consumer.channel_layout", + mlt_audio_channel_layout_name(mlt_channel_independent)); + + error = mlt_frame_get_audio(frame, buffer, format, frequency, channels, samples); + + // Restore the saved channel layout + mlt_properties_set(properties, + "consumer.channel_layout", + mlt_audio_channel_layout_name(channel_layout)); + + if (!error && *channels >= AMBISONICS_1_CHANNELS) { + auto spatial = static_cast(filter->child); + error = spatial->getAudio(frame, static_cast(*buffer), *samples, *channels); + } + } else { + // pass through mono and stereo + error = mlt_frame_get_audio(frame, buffer, format, frequency, channels, samples); + } + + mlt_service_unlock(MLT_FILTER_SERVICE(filter)); + + return error; +} + +static mlt_frame process(mlt_filter filter, mlt_frame frame) +{ + if (mlt_frame_is_test_audio(frame) == 0) { + // Add the filter to the frame + mlt_frame_push_audio(frame, filter); + mlt_frame_push_audio(frame, (void *) get_audio); + } + return frame; +} + +static void close_filter(mlt_filter filter) +{ + delete reinterpret_cast(filter->child); +} + +mlt_filter filter_ambisonic_encoder_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg) +{ + mlt_filter filter = nullptr; + auto *spatial = new SpatialAudioEncoder; + + if (spatial) { + filter = spatial->filter(); + if (!filter) + delete spatial; + } + return filter; +} + +} // extern diff --git a/src/modules/spatialaudio/filter_ambisonic-encoder.yml b/src/modules/spatialaudio/filter_ambisonic-encoder.yml new file mode 100644 index 000000000..3618654ec --- /dev/null +++ b/src/modules/spatialaudio/filter_ambisonic-encoder.yml @@ -0,0 +1,40 @@ +schema_version: 7.0 +type: filter +identifier: ambisonic-encoder +title: Ambisonic Encoder +version: 1 +copyright: Meltytech, LLC +license: LGPL +language: en +url: https://github.com/videolabs/libspatialaudio +tags: + - Audio +description: Position a mono sound in Ambisonic space. +notes: > + This only supports first order for now. The consumer should be configured + for 4 or more channels. If the source has more than one channel, only the + first channel is used. + +parameters: + - identifier: azimuth + title: Azimuth + type: float + default: 0 + unit: degrees + mutable: yes + animation: yes + + - identifier: elevation + title: Elevation + type: float + default: 0 + unit: degrees + mutable: yes + animation: yes + + - identifier: distance + title: Distance + type: float + default: 0 + mutable: yes + animation: yes From b2a82de18e58e50aaba0366702087bab6052fccf Mon Sep 17 00:00:00 2001 From: j-b-m Date: Fri, 12 Apr 2024 17:30:12 +0200 Subject: [PATCH 096/130] Don't allow connecting a null producer to a service (#979) --- src/framework/mlt_service.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/framework/mlt_service.c b/src/framework/mlt_service.c index 4ee83fa5a..f9d65a27d 100644 --- a/src/framework/mlt_service.c +++ b/src/framework/mlt_service.c @@ -207,13 +207,12 @@ int mlt_service_connect_producer(mlt_service self, mlt_service producer, int ind } // If we have space, assign the input - if (base->in != NULL && index >= 0 && index < base->size) { + if (producer != NULL && base->in != NULL && index >= 0 && index < base->size) { // Get the current service mlt_service current = (index < base->count) ? base->in[index] : NULL; // Increment the reference count on this producer - if (producer != NULL) - mlt_properties_inc_ref(MLT_SERVICE_PROPERTIES(producer)); + mlt_properties_inc_ref(MLT_SERVICE_PROPERTIES(producer)); // Now we disconnect the producer service from its consumer mlt_service_disconnect(producer); From a089fcc3d5af11fd6d1c8c20341853ef67a2323e Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sat, 13 Apr 2024 09:34:48 -0700 Subject: [PATCH 097/130] fix #873 remove some unnecessary null pointer checks --- src/modules/qt/kdenlivetitle_wrapper.cpp | 3 +-- src/modules/rubberband/filter_rbpitch.cpp | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/modules/qt/kdenlivetitle_wrapper.cpp b/src/modules/qt/kdenlivetitle_wrapper.cpp index 50e3f4f6f..c253edadd 100644 --- a/src/modules/qt/kdenlivetitle_wrapper.cpp +++ b/src/modules/qt/kdenlivetitle_wrapper.cpp @@ -300,8 +300,7 @@ QTransform stringToTransform(const QString &s) static void qscene_delete(void *data) { QGraphicsScene *scene = (QGraphicsScene *) data; - if (scene) - delete scene; + delete scene; scene = NULL; } diff --git a/src/modules/rubberband/filter_rbpitch.cpp b/src/modules/rubberband/filter_rbpitch.cpp index e9cefe427..03ef7e620 100644 --- a/src/modules/rubberband/filter_rbpitch.cpp +++ b/src/modules/rubberband/filter_rbpitch.cpp @@ -1,6 +1,6 @@ /* * filter_rbpitch.c -- adjust audio pitch - * Copyright (C) 2020 Meltytech, LLC + * Copyright (C) 2020-2024 Meltytech, LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -295,11 +295,7 @@ mlt_filter filter_rbpitch_init(mlt_profile profile, mlt_service_type type, const if (filter) { mlt_filter_close(filter); } - - if (pdata) { - free(pdata); - } - + free(pdata); filter = NULL; } return filter; From 0a7a3feafe3b3d226fa1c010d81ae7bd899e47aa Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 17 Apr 2024 14:39:41 -0700 Subject: [PATCH 098/130] fix #980 building with FFmpeg v7 --- src/modules/avformat/common.c | 11 ++- src/modules/avformat/common.h | 7 +- src/modules/avformat/common_swr.c | 26 ++++++- src/modules/avformat/consumer_avformat.c | 66 +++++++++++++++-- src/modules/avformat/filter_avfilter.c | 33 ++++++++- src/modules/avformat/link_avfilter.c | 37 +++++++++- src/modules/avformat/producer_avformat.c | 90 ++++++++++++++++++++---- 7 files changed, 240 insertions(+), 30 deletions(-) diff --git a/src/modules/avformat/common.c b/src/modules/avformat/common.c index 717d57802..a316f8d18 100644 --- a/src/modules/avformat/common.c +++ b/src/modules/avformat/common.c @@ -1,6 +1,6 @@ /* * common.h - * Copyright (C) 2018-2023 Meltytech, LLC + * Copyright (C) 2018-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -156,9 +156,18 @@ int64_t mlt_to_av_channel_layout(mlt_channel_layout layout) return 0; } +#if HAVE_FFMPEG_CH_LAYOUT +mlt_channel_layout av_channel_layout_to_mlt(AVChannelLayout *layout) +{ + if (layout->order != AV_CHANNEL_ORDER_NATIVE && layout->order != AV_CHANNEL_ORDER_AMBISONIC) { + return mlt_channel_independent; + } + switch (layout->u.mask) { +#else mlt_channel_layout av_channel_layout_to_mlt(int64_t layout) { switch (layout) { +#endif case 0: return mlt_channel_independent; case AV_CH_LAYOUT_MONO: diff --git a/src/modules/avformat/common.h b/src/modules/avformat/common.h index c6f2bbca4..0e1e28bd8 100644 --- a/src/modules/avformat/common.h +++ b/src/modules/avformat/common.h @@ -1,6 +1,6 @@ /* * common.h - * Copyright (C) 2018 Meltytech, LLC + * Copyright (C) 2018-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,10 +25,15 @@ #include #define MLT_AVFILTER_SWS_FLAGS "bicubic+accurate_rnd+full_chroma_int+full_chroma_inp" +#define HAVE_FFMPEG_CH_LAYOUT (LIBAVUTIL_VERSION_MAJOR >= 59) int mlt_to_av_sample_format(mlt_audio_format format); int64_t mlt_to_av_channel_layout(mlt_channel_layout layout); +#if HAVE_FFMPEG_CH_LAYOUT +mlt_channel_layout av_channel_layout_to_mlt(AVChannelLayout *layout); +#else mlt_channel_layout av_channel_layout_to_mlt(int64_t layout); +#endif mlt_channel_layout mlt_get_channel_layout_or_default(const char *name, int channels); int mlt_set_luma_transfer(struct SwsContext *context, int src_colorspace, diff --git a/src/modules/avformat/common_swr.c b/src/modules/avformat/common_swr.c index 409f51289..4a5388458 100644 --- a/src/modules/avformat/common_swr.c +++ b/src/modules/avformat/common_swr.c @@ -1,6 +1,6 @@ /* - * common.h - * Copyright (C) 2022-2023 Meltytech, LLC + * common_swr.c + * Copyright (C) 2022-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -50,16 +50,27 @@ int mlt_configure_swr_context(mlt_service service, mlt_swr_private_data *pdata) // Configure format, frequency and channels. av_opt_set_int(pdata->ctx, "osf", mlt_to_av_sample_format(pdata->out_format), 0); av_opt_set_int(pdata->ctx, "osr", pdata->out_frequency, 0); - av_opt_set_int(pdata->ctx, "och", pdata->out_channels, 0); av_opt_set_int(pdata->ctx, "isf", mlt_to_av_sample_format(pdata->in_format), 0); av_opt_set_int(pdata->ctx, "isr", pdata->in_frequency, 0); +#if !HAVE_FFMPEG_CH_LAYOUT + av_opt_set_int(pdata->ctx, "och", pdata->out_channels, 0); av_opt_set_int(pdata->ctx, "ich", pdata->in_channels, 0); +#endif if (pdata->in_layout != mlt_channel_independent && pdata->out_layout != mlt_channel_independent) { // Use standard channel layout and matrix for known channel configurations. +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout ochl = AV_CHANNEL_LAYOUT_MASK(pdata->out_channels, + mlt_to_av_channel_layout(pdata->out_layout)); + AVChannelLayout ichl = AV_CHANNEL_LAYOUT_MASK(pdata->in_channels, + mlt_to_av_channel_layout(pdata->in_layout)); + av_opt_set_chlayout(pdata->ctx, "ochl", &ochl, 0); + av_opt_set_chlayout(pdata->ctx, "ichl", &ichl, 0); +#else av_opt_set_int(pdata->ctx, "ocl", mlt_to_av_channel_layout(pdata->out_layout), 0); av_opt_set_int(pdata->ctx, "icl", mlt_to_av_channel_layout(pdata->in_layout), 0); +#endif } else { // Use a custom channel layout and matrix for independent channels. // This matrix will simply map input channels to output channels in order. @@ -81,8 +92,17 @@ int mlt_configure_swr_context(mlt_service service, mlt_swr_private_data *pdata) matrix_row[i] = 1.0; } } +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout ochl + = {AV_CHANNEL_ORDER_UNSPEC, pdata->out_channels, {custom_out_layout}, NULL}; + AVChannelLayout ichl + = {AV_CHANNEL_ORDER_UNSPEC, pdata->in_channels, {custom_in_layout}, NULL}; + av_opt_set_chlayout(pdata->ctx, "ochl", &ochl, 0); + av_opt_set_chlayout(pdata->ctx, "ichl", &ichl, 0); +#else av_opt_set_int(pdata->ctx, "ocl", custom_out_layout, 0); av_opt_set_int(pdata->ctx, "icl", custom_in_layout, 0); +#endif error = swr_set_matrix(pdata->ctx, matrix, stride); av_free(matrix); if (error != 0) { diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index aee8b3ebf..a6e238283 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -1,6 +1,6 @@ /* * consumer_avformat.c -- an encoder based on avformat - * Copyright (C) 2003-2023 Meltytech, LLC + * Copyright (C) 2003-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -720,7 +720,12 @@ static AVStream *add_audio_stream(mlt_consumer consumer, const AVCodec *codec, AVCodecContext **codec_context, int channels, - int64_t channel_layout) +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout *channel_layout +#else + int64_t channel_layout +#endif +) { // Get the properties mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer); @@ -740,7 +745,11 @@ static AVStream *add_audio_stream(mlt_consumer consumer, c->codec_id = codec->id; c->codec_type = AVMEDIA_TYPE_AUDIO; c->sample_fmt = pick_sample_fmt(properties, codec); +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_copy(&c->ch_layout, channel_layout); +#else c->channel_layout = channel_layout; +#endif // disabled until some audio codecs are multi-threaded #if 0 @@ -783,7 +792,11 @@ static AVStream *add_audio_stream(mlt_consumer consumer, // Set parameters controlled by MLT c->sample_rate = mlt_properties_get_int(properties, "frequency"); st->time_base = (AVRational){1, c->sample_rate}; +#if HAVE_FFMPEG_CH_LAYOUT + c->ch_layout.nb_channels = channels; +#else c->channels = channels; +#endif if (mlt_properties_get(properties, "alang") != NULL) av_dict_set(&oc->metadata, "language", mlt_properties_get(properties, "alang"), 0); @@ -1195,7 +1208,11 @@ typedef struct size_t size; } buffer_t; +#if LIBAVFORMAT_VERSION_MAJOR >= 61 +static int mlt_write(void *h, const uint8_t *buf, int size) +#else static int mlt_write(void *h, uint8_t *buf, int size) +#endif { mlt_properties properties = (mlt_properties) h; buffer_t buffer = {buf, size}; @@ -1295,7 +1312,11 @@ static int encode_audio(encode_ctx_t *ctx) ctx->audio_avframe->pts = ctx->sample_count[i]; ctx->sample_count[i] += ctx->audio_avframe->nb_samples; avcodec_fill_audio_frame(ctx->audio_avframe, +#if HAVE_FFMPEG_CH_LAYOUT + codec->ch_layout.nb_channels, +#else codec->channels, +#endif codec->sample_fmt, (const uint8_t *) p, AUDIO_ENCODE_BUFFER_SIZE, @@ -1371,7 +1392,11 @@ static int encode_audio(encode_ctx_t *ctx) ctx->audio_avframe->pts = ctx->sample_count[i]; ctx->sample_count[i] += ctx->audio_avframe->nb_samples; avcodec_fill_audio_frame(ctx->audio_avframe, +#if HAVE_FFMPEG_CH_LAYOUT + codec->ch_layout.nb_channels, +#else codec->channels, +#endif codec->sample_fmt, (const uint8_t *) ctx->audio_buf_2, AUDIO_ENCODE_BUFFER_SIZE, @@ -1625,6 +1650,11 @@ static void *consumer_thread(void *arg) } if (enc_ctx->audio_codec_id != AV_CODEC_ID_NONE) { int is_multi = 0; +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout ch_layout; +#else + int64_t ch_layout; +#endif enc_ctx->total_channels = 0; // multitrack audio @@ -1634,12 +1664,24 @@ static void *consumer_thread(void *arg) if (j) { is_multi = 1; enc_ctx->total_channels += j; +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_default(&ch_layout, j); + enc_ctx->audio_st[i] = add_audio_stream(consumer, + enc_ctx->oc, + audio_codec, + &enc_ctx->acodec_ctx[i], + j, + &ch_layout); + av_channel_layout_uninit(&ch_layout); +#else + ch_layout = av_get_default_channel_layout(j); enc_ctx->audio_st[i] = add_audio_stream(consumer, enc_ctx->oc, audio_codec, &enc_ctx->acodec_ctx[i], j, - av_get_default_channel_layout(j)); + ch_layout); +#endif } } // single track @@ -1650,12 +1692,24 @@ static void *consumer_thread(void *arg) || mlt_audio_channel_layout_channels(layout) != enc_ctx->channels) { layout = mlt_audio_channel_layout_default(enc_ctx->channels); } +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_from_mask(&ch_layout, mlt_to_av_channel_layout(layout)); enc_ctx->audio_st[0] = add_audio_stream(consumer, enc_ctx->oc, audio_codec, &enc_ctx->acodec_ctx[0], enc_ctx->channels, - mlt_to_av_channel_layout(layout)); + &ch_layout); + av_channel_layout_uninit(&ch_layout); +#else + ch_layout = mlt_to_av_channel_layout(layout); + enc_ctx->audio_st[0] = add_audio_stream(consumer, + enc_ctx->oc, + audio_codec, + &enc_ctx->acodec_ctx[0], + enc_ctx->channels, + ch_layout); +#endif enc_ctx->total_channels = enc_ctx->channels; } } @@ -1780,8 +1834,12 @@ static void *consumer_thread(void *arg) AVCodecContext *c = enc_ctx->acodec_ctx[0]; enc_ctx->audio_avframe->format = c->sample_fmt; enc_ctx->audio_avframe->nb_samples = enc_ctx->audio_input_frame_size; +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_copy(&enc_ctx->audio_avframe->ch_layout, &c->ch_layout); +#else enc_ctx->audio_avframe->channel_layout = c->channel_layout; enc_ctx->audio_avframe->channels = c->channels; +#endif } else { mlt_log_error(MLT_CONSUMER_SERVICE(consumer), "failed to allocate audio AVFrame\n"); mlt_events_fire(properties, "consumer-fatal-error", mlt_event_data_none()); diff --git a/src/modules/avformat/filter_avfilter.c b/src/modules/avformat/filter_avfilter.c index ec957795e..06bc8101f 100644 --- a/src/modules/avformat/filter_avfilter.c +++ b/src/modules/avformat/filter_avfilter.c @@ -1,6 +1,6 @@ /* * filter_avfilter.c -- provide various filters based on libavfilter - * Copyright (C) 2016-2022 Meltytech, LLC + * Copyright (C) 2016-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -182,7 +182,6 @@ static void init_audio_filtergraph(mlt_filter filter, int sample_fmts[] = {-1, -1}; int sample_rates[] = {-1, -1}; int channel_counts[] = {-1, -1}; - int64_t channel_layouts[] = {-1, -1}; char channel_layout_str[64]; int ret; @@ -192,11 +191,19 @@ static void init_audio_filtergraph(mlt_filter filter, sample_fmts[0] = mlt_to_av_sample_format(format); sample_rates[0] = frequency; channel_counts[0] = channels; +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout ch_layout; + av_channel_layout_default(&ch_layout, channels); + av_channel_layout_describe(&ch_layout, channel_layout_str, sizeof(channel_layout_str)); + av_channel_layout_uninit(&ch_layout); +#else + int64_t channel_layouts[] = {-1, -1}; channel_layouts[0] = av_get_default_channel_layout(channels); av_get_channel_layout_string(channel_layout_str, sizeof(channel_layout_str), 0, channel_layouts[0]); +#endif // Destroy the current filter graph avfilter_graph_free(&pdata->avfilter_graph); @@ -290,6 +297,16 @@ static void init_audio_filtergraph(mlt_filter filter, mlt_log_error(filter, "Cannot set sink channel counts\n"); goto fail; } +#if HAVE_FFMPEG_CH_LAYOUT + ret = av_opt_set(pdata->avbuffsink_ctx, + "ch_layouts", + channel_layout_str, + AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + mlt_log_error(filter, "Cannot set sink ch_layouts\n"); + goto fail; + } +#else ret = av_opt_set_int_list(pdata->avbuffsink_ctx, "channel_layouts", channel_layouts, @@ -299,6 +316,7 @@ static void init_audio_filtergraph(mlt_filter filter, mlt_log_error(filter, "Cannot set sink channel_layouts\n"); goto fail; } +#endif ret = avfilter_init_str(pdata->avbuffsink_ctx, NULL); if (ret < 0) { mlt_log_error(filter, "Cannot init buffer sink\n"); @@ -676,8 +694,12 @@ static int filter_get_audio(mlt_frame frame, *channels); pdata->avinframe->sample_rate = *frequency; pdata->avinframe->format = mlt_to_av_sample_format(*format); +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_from_mask(&pdata->avinframe->ch_layout, mlt_to_av_channel_layout(layout)); +#else pdata->avinframe->channel_layout = mlt_to_av_channel_layout(layout); pdata->avinframe->channels = *channels; +#endif pdata->avinframe->nb_samples = *samples; pdata->avinframe->pts = samplepos; ret = av_frame_get_buffer(pdata->avinframe, 1); @@ -707,7 +729,12 @@ static int filter_get_audio(mlt_frame frame, } // Sanity check the output frame - if (*channels != pdata->avoutframe->channels || *samples != pdata->avoutframe->nb_samples +#if HAVE_FFMPEG_CH_LAYOUT + if (*channels != pdata->avoutframe->ch_layout.nb_channels +#else + if (*channels != pdata->avoutframe->channels +#endif + || *samples != pdata->avoutframe->nb_samples || *frequency != pdata->avoutframe->sample_rate) { mlt_log_error(filter, "Unexpected return format\n"); goto exit; diff --git a/src/modules/avformat/link_avfilter.c b/src/modules/avformat/link_avfilter.c index f822aff81..e1106191c 100644 --- a/src/modules/avformat/link_avfilter.c +++ b/src/modules/avformat/link_avfilter.c @@ -1,6 +1,6 @@ /* * link_avfilter.c -- provide various links based on libavfilter - * Copyright (C) 2023 Meltytech, LLC + * Copyright (C) 2023-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -207,7 +207,6 @@ static void init_audio_filtergraph(mlt_link self, int sample_fmts[] = {-1, -1}; int sample_rates[] = {-1, -1}; int channel_counts[] = {-1, -1}; - int64_t channel_layouts[] = {-1, -1}; char channel_layout_str[64]; int ret; @@ -217,11 +216,19 @@ static void init_audio_filtergraph(mlt_link self, sample_fmts[0] = mlt_to_av_sample_format(format); sample_rates[0] = frequency; channel_counts[0] = channels; +#if HAVE_FFMPEG_CH_LAYOUT + AVChannelLayout ch_layout; + av_channel_layout_default(&ch_layout, channels); + av_channel_layout_describe(&ch_layout, channel_layout_str, sizeof(channel_layout_str)); + av_channel_layout_uninit(&ch_layout); +#else + int64_t channel_layouts[] = {-1, -1}; channel_layouts[0] = av_get_default_channel_layout(channels); av_get_channel_layout_string(channel_layout_str, sizeof(channel_layout_str), 0, channel_layouts[0]); +#endif // Destroy the current filter graph avfilter_graph_free(&pdata->avfilter_graph); @@ -315,6 +322,16 @@ static void init_audio_filtergraph(mlt_link self, mlt_log_error(self, "Cannot set sink channel counts\n"); goto fail; } +#if HAVE_FFMPEG_CH_LAYOUT + ret = av_opt_set(pdata->avbuffsink_ctx, + "ch_layouts", + channel_layout_str, + AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + mlt_log_error(self, "Cannot set sink ch_layouts\n"); + goto fail; + } +#else ret = av_opt_set_int_list(pdata->avbuffsink_ctx, "channel_layouts", channel_layouts, @@ -324,6 +341,7 @@ static void init_audio_filtergraph(mlt_link self, mlt_log_error(self, "Cannot set sink channel_layouts\n"); goto fail; } +#endif ret = avfilter_init_str(pdata->avbuffsink_ctx, NULL); if (ret < 0) { mlt_log_error(self, "Cannot init buffer sink\n"); @@ -762,8 +780,12 @@ static int link_get_audio(mlt_frame frame, int inbufsize = mlt_audio_format_size(in.format, in.samples, in.channels); pdata->avinframe->sample_rate = in.frequency; pdata->avinframe->format = mlt_to_av_sample_format(in.format); +#if HAVE_FFMPEG_CH_LAYOUT + av_channel_layout_from_mask(&pdata->avinframe->ch_layout, mlt_to_av_channel_layout(layout)); +#else pdata->avinframe->channel_layout = mlt_to_av_channel_layout(layout); pdata->avinframe->channels = in.channels; +#endif pdata->avinframe->nb_samples = in.samples; pdata->avinframe->pts = samplepos; ret = av_frame_get_buffer(pdata->avinframe, 1); @@ -798,12 +820,21 @@ static int link_get_audio(mlt_frame frame, } // Sanity check the output frame - if (*channels != pdata->avoutframe->channels || *samples != pdata->avoutframe->nb_samples +#if HAVE_FFMPEG_CH_LAYOUT + if (*channels != pdata->avoutframe->ch_layout.nb_channels +#else + if (*channels != pdata->avoutframe->channels +#endif + || *samples != pdata->avoutframe->nb_samples || *frequency != pdata->avoutframe->sample_rate) { mlt_log_error(self, "Unexpected return format c %d->%d\tf %d->%d\tf %d->%d\n", *channels, +#if HAVE_FFMPEG_CH_LAYOUT + pdata->avoutframe->ch_layout.nb_channels, +#else pdata->avoutframe->channels, +#endif *samples, pdata->avoutframe->nb_samples, *frequency, diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 9573aeed8..6a73cd95d 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1,6 +1,6 @@ /* * producer_avformat.c -- avformat producer - * Copyright (C) 2003-2023 Meltytech, LLC + * Copyright (C) 2003-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -506,7 +506,11 @@ static mlt_properties find_default_streams(producer_avformat self) } break; case AVMEDIA_TYPE_AUDIO: +#if HAVE_FFMPEG_CH_LAYOUT + if (!codec_params->ch_layout.nb_channels) +#else if (!codec_params->channels) +#endif break; // Use first audio stream if (self->audio_index < 0 && pick_audio_format(codec_params->format) != mlt_audio_none) @@ -518,15 +522,27 @@ static mlt_properties find_default_streams(producer_avformat self) snprintf(key, sizeof(key), "meta.media.%u.codec.sample_rate", i); mlt_properties_set_int(meta_media, key, codec_params->sample_rate); snprintf(key, sizeof(key), "meta.media.%u.codec.channels", i); - mlt_properties_set_int(meta_media, key, codec_params->channels); - snprintf(key, sizeof(key), "meta.media.%u.codec.layout", i); mlt_channel_layout mlt_layout = mlt_channel_independent; +#if HAVE_FFMPEG_CH_LAYOUT + mlt_properties_set_int(meta_media, key, codec_params->ch_layout.nb_channels); + if (av_channel_layout_check(&codec_params->ch_layout)) { + mlt_layout = av_channel_layout_to_mlt(&codec_params->ch_layout); + } else { + AVChannelLayout ch_layout; + av_channel_layout_default(&ch_layout, codec_params->ch_layout.nb_channels); + mlt_layout = av_channel_layout_to_mlt(&ch_layout); + av_channel_layout_uninit(&ch_layout); + } +#else + mlt_properties_set_int(meta_media, key, codec_params->channels); if (codec_params->channel_layout == 0) mlt_layout = av_channel_layout_to_mlt( av_get_default_channel_layout(codec_params->channels)); else mlt_layout = av_channel_layout_to_mlt(codec_params->channel_layout); +#endif char *layout = mlt_audio_channel_layout_name(mlt_layout); + snprintf(key, sizeof(key), "meta.media.%u.codec.layout", i); mlt_properties_set(meta_media, key, layout); break; default: @@ -1425,9 +1441,15 @@ static void get_audio_streams_info(producer_avformat self) if (codec && avcodec_open2(codec_context, codec, NULL) >= 0) { self->audio_streams++; self->audio_max_stream = i; +#if HAVE_FFMPEG_CH_LAYOUT + self->total_channels += codec_params->ch_layout.nb_channels; + if (codec_params->ch_layout.nb_channels > self->max_channel) + self->max_channel = codec_params->ch_layout.nb_channels; +#else self->total_channels += codec_params->channels; if (codec_params->channels > self->max_channel) self->max_channel = codec_params->channels; +#endif if (codec_params->sample_rate > self->max_frequency) self->max_frequency = codec_params->sample_rate; avcodec_close(codec_context); @@ -2320,7 +2342,9 @@ static int producer_get_image(mlt_frame frame, // Decode the image if (must_decode || int_position >= req_position || !self->pkt.data) { +#if LIBAVCODEC_VERSION_MAJOR < 61 self->video_codec->reordered_opaque = int_position; +#endif if (int_position >= req_position) self->video_codec->skip_loop_filter = AVDISCARD_NONE; self->video_send_result = avcodec_send_packet(self->video_codec, &self->pkt); @@ -2373,7 +2397,9 @@ static int producer_get_image(mlt_frame frame, if (got_picture) { // Get position of reordered frame +#if LIBAVCODEC_VERSION_MAJOR < 61 int_position = self->video_frame->reordered_opaque; +#endif pts = best_pts(self, self->video_frame->pts, self->video_frame->pkt_dts); if (pts != AV_NOPTS_VALUE) { // Some streams are not marking their key frames even though @@ -3083,8 +3109,11 @@ static int decode_audio(producer_avformat self, // Obtain the audio buffers uint8_t *audio_buffer = self->audio_buffer[index]; - +#if HAVE_FFMPEG_CH_LAYOUT + int channels = codec_context->ch_layout.nb_channels; +#else int channels = codec_context->channels; +#endif int audio_used = self->audio_used[index]; int audio_used_at_start = audio_used; int ret = 0; @@ -3117,7 +3146,11 @@ static int decode_audio(producer_avformat self, } else { // Figure out how many samples will be needed after resampling int convert_samples = self->audio_frame->nb_samples; +#if HAVE_FFMPEG_CH_LAYOUT + channels = codec_context->ch_layout.nb_channels; +#else channels = codec_context->channels; +#endif ret += convert_samples * channels * sizeof_sample; // Resize audio buffer to prevent overflow @@ -3314,10 +3347,12 @@ static int producer_get_audio(mlt_frame frame, AVCodecContext *codec_context = self->audio_codec[index]; if (codec_context && !self->audio_buffer[index]) { +#if !HAVE_FFMPEG_CH_LAYOUT if (self->audio_index != INT_MAX && !mlt_properties_get(MLT_PRODUCER_PROPERTIES(self->parent), "request_channel_layout")) codec_context->request_channel_layout = av_get_default_channel_layout(*channels); +#endif sizeof_sample = sample_bytes(codec_context); // Check for audio buffer and create if necessary @@ -3334,7 +3369,7 @@ static int producer_get_audio(mlt_frame frame, int ret = 0; int got_audio = 0; AVPacket pkt; - mlt_channel_layout layout = mlt_channel_auto; + mlt_channel_layout mlt_layout = mlt_channel_auto; av_init_packet(&pkt); @@ -3417,18 +3452,31 @@ static int producer_get_audio(mlt_frame frame, // Set some additional return values *format = mlt_audio_s16; if (self->audio_index != INT_MAX) { + AVCodecContext *codec_ctx = self->audio_codec[self->audio_index]; index = self->audio_index; - *channels = self->audio_codec[index]->channels; - *frequency = self->audio_codec[index]->sample_rate; - *format = pick_audio_format(self->audio_codec[index]->sample_fmt); - sizeof_sample = sample_bytes(self->audio_codec[index]); - if (self->audio_codec[index]->channel_layout == 0) - layout = av_channel_layout_to_mlt( - av_get_default_channel_layout(self->audio_codec[index]->channels)); + *frequency = codec_ctx->sample_rate; + *format = pick_audio_format(codec_ctx->sample_fmt); + sizeof_sample = sample_bytes(codec_ctx); +#if HAVE_FFMPEG_CH_LAYOUT + *channels = codec_ctx->ch_layout.nb_channels; + if (av_channel_layout_check(&codec_ctx->ch_layout)) { + mlt_layout = av_channel_layout_to_mlt(&codec_ctx->ch_layout); + } else { + AVChannelLayout ch_layout; + av_channel_layout_default(&ch_layout, codec_ctx->ch_layout.nb_channels); + mlt_layout = av_channel_layout_to_mlt(&ch_layout); + av_channel_layout_uninit(&ch_layout); + } +#else + *channels = codec_ctx->channels; + if (codec_ctx->channel_layout == 0) + mlt_layout = av_channel_layout_to_mlt( + av_get_default_channel_layout(codec_ctx->channels)); else - layout = av_channel_layout_to_mlt(self->audio_codec[index]->channel_layout); + mlt_layout = av_channel_layout_to_mlt(codec_ctx->channel_layout); +#endif } else if (self->audio_index == INT_MAX) { - layout = mlt_channel_independent; + mlt_layout = mlt_channel_independent; for (index = 0; index < index_max; index++) if (self->audio_codec[index]) { // XXX: This only works if all audio tracks have the same sample format. @@ -3439,7 +3487,7 @@ static int producer_get_audio(mlt_frame frame, } mlt_properties_set(MLT_FRAME_PROPERTIES(frame), "channel_layout", - mlt_audio_channel_layout_name(layout)); + mlt_audio_channel_layout_name(mlt_layout)); // Allocate and set the frame's audio buffer int size = mlt_audio_format_size(*format, *samples, *channels); @@ -3453,7 +3501,11 @@ static int producer_get_audio(mlt_frame frame, for (i = 0; i < *samples; i++) { for (index = 0; index < index_max; index++) if (self->audio_codec[index]) { +#if HAVE_FFMPEG_CH_LAYOUT + int current_channels = self->audio_codec[index]->ch_layout.nb_channels; +#else int current_channels = self->audio_codec[index]->channels; +#endif uint8_t *src = self->audio_buffer[index] + i * current_channels * sizeof_sample; memcpy(dest, src, current_channels * sizeof_sample); @@ -3462,7 +3514,11 @@ static int producer_get_audio(mlt_frame frame, } for (index = 0; index < index_max; index++) if (self->audio_codec[index] && self->audio_used[index] >= *samples) { +#if HAVE_FFMPEG_CH_LAYOUT + int current_channels = self->audio_codec[index]->ch_layout.nb_channels; +#else int current_channels = self->audio_codec[index]->channels; +#endif uint8_t *src = self->audio_buffer[index] + *samples * current_channels * sizeof_sample; self->audio_used[index] -= *samples; @@ -3725,7 +3781,11 @@ static void producer_set_up_audio(producer_avformat self, mlt_frame frame) self->audio_codec[index]->sample_rate); mlt_properties_set_int(frame_properties, "audio_channels", +#if HAVE_FFMPEG_CH_LAYOUT + self->audio_codec[index]->ch_layout.nb_channels); +#else self->audio_codec[index]->channels); +#endif } if (context && index > -1) { // Add our audio operation From 245b243349afb3bc82755ed8ddba52bbcdd05758 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Wed, 17 Apr 2024 23:43:19 +0200 Subject: [PATCH 099/130] Include locale.h on any GNU libc platform (#925) locale.h & locale_t are implemented by GNU libc (at least), so any OS based on it has them; hence, extend the check to use __GLIBC__ as alternative to __linux__. Updates commit 7d82553a00e74af77e69cc74645e0a3ec6bb3aa1 by bringing __GLIBC__ back in use. Fixes commit 2a2ff9eeeca75b053dc7256de990562ecebd109d by dropping the check for macOS (__APPLE__) when GNU libc is available; there is no GNU libc on macOS, so that check is always false. --- src/framework/mlt_property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/mlt_property.h b/src/framework/mlt_property.h index e347d4b68..ad1a1978f 100644 --- a/src/framework/mlt_property.h +++ b/src/framework/mlt_property.h @@ -30,7 +30,7 @@ #include #endif -#if (defined(__linux__) && !defined(__APPLE__)) +#if defined(__linux__) || defined(__GLIBC__) #include typedef locale_t mlt_locale_t; #elif defined(__APPLE__) || (defined(__FreeBSD_version) && __FreeBSD_version >= 900506) From e64eee509a83246645889db807e26b607d6860ad Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 17 Apr 2024 15:04:45 -0700 Subject: [PATCH 100/130] update gitlab CI and fix debian stable --- .gitlab-ci.yml | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 80867648b..2b7b2bb83 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ ubuntu-latest: - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install ubuntu-lts: - image: ubuntu:20.04 + image: ubuntu:22.04 script: - sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" - DEBIAN_FRONTEND=noninteractive apt-get -qq update @@ -38,37 +38,29 @@ debian-stable: image: debian:stable script: - echo -e 'deb-src http://deb.debian.org/debian stable main\ndeb-src http://deb.debian.org/debian stable-updates main' >> /etc/apt/sources.list - - echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list + - echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list - apt-get -qq update - apt-get -yqq build-dep mlt - apt-get -yqq install cmake - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install -fedora-38: - image: fedora:38 - script: - - yum --assumeyes groupinstall "Development Tools" - - yum --assumeyes install yasm gavl-devel libsamplerate-devel libxml2-devel ladspa-devel jack-audio-connection-kit-devel sox-devel SDL-devel gtk2-devel qt-devel libexif-devel libtheora-devel libvorbis-devel libvdpau-devel libsoup-devel liboil-devel python-devel alsa-lib pulseaudio-libs-devel gcc-c++ cmake - # unclear why `gcc-c++` isn't in `Development Tools` - - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install - -fedora-36: - image: fedora:36 +fedora-39: + image: fedora:39 script: - yum --assumeyes groupinstall "Development Tools" - yum --assumeyes install yasm gavl-devel libsamplerate-devel libxml2-devel ladspa-devel jack-audio-connection-kit-devel sox-devel SDL-devel gtk2-devel qt-devel libexif-devel libtheora-devel libvorbis-devel libvdpau-devel libsoup-devel liboil-devel python-devel alsa-lib pulseaudio-libs-devel gcc-c++ cmake # unclear why `gcc-c++` isn't in `Development Tools` - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install -fedora-34: - image: fedora:34 +fedora-38: + image: fedora:38 script: - yum --assumeyes groupinstall "Development Tools" - yum --assumeyes install yasm gavl-devel libsamplerate-devel libxml2-devel ladspa-devel jack-audio-connection-kit-devel sox-devel SDL-devel gtk2-devel qt-devel libexif-devel libtheora-devel libvorbis-devel libvdpau-devel libsoup-devel liboil-devel python-devel alsa-lib pulseaudio-libs-devel gcc-c++ cmake # unclear why `gcc-c++` isn't in `Development Tools` - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install -fedora-30: +fedora-32: image: fedora:32 script: - yum --assumeyes groupinstall "Development Tools" From fd4d9add9d4ff5eefb72b7d820bec860f8e4de17 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sat, 27 Apr 2024 10:07:53 -0700 Subject: [PATCH 101/130] version 7.24.0 --- CMakeLists.txt | 2 +- Doxyfile | 2 +- NEWS | 36 ++++++++++++++++++++++++++++++++++++ docs/melt.1 | 4 ++-- src/framework/mlt_version.h | 4 ++-- src/melt/melt.c | 4 ++-- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b88a1da9..28af9b2fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) project(MLT - VERSION 7.23.0 + VERSION 7.24.0 DESCRIPTION "Multimedia Framework" HOMEPAGE_URL "https://www.mltframework.org" LANGUAGES C CXX diff --git a/Doxyfile b/Doxyfile index 65613b56f..ae551d7e7 100644 --- a/Doxyfile +++ b/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = MLT # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 7.22.0 +PROJECT_NUMBER = 7.24.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/NEWS b/NEWS index ea57dcbbc..66b464e81 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,42 @@ MLT Release Notes ----------------- +Version 7.24.0 + +Framework + * Fixed a small memory leak in `mlt_repository`. + * Fixed a small memory leak in `MltPushConsumer` C++ class. + * Block connecting a null producer to a service. + * Include `locale.h` on any GNU libc platform. + +Modules + * Added a new `spatialaudio` module with filters: + - `ambisonic-decoder` + - `ambisonic-encoder` + * Fixed building with FFmpeg 7. + * Fixed text keywords do not work with non-ASCII filenames on Windows: + - `pixbuf` producer + - `opencv_tracker` filter + - `dynamictext` filter + - `qimage` producer + * Added "meta.media.aspect_ratio" property to the `avformat` producer. + * Fixed `distort` property not working in `movit.rect` filter. + * Fixed frames dropping or repeating in the `multi` consumer. + * Fixed the `dynamic_loudness` filter maximizing audio gain. + * Fixed distortion in the `mono` filter. + * Also check for `WAYLAND_DISPLAY` to detect a graphical session in the `qt` + and `glaxnimate` modules. + * Fixed the `wave` filter distorts if `wave` = 1 with preview scaling. + * Added the read-only `meta.media.%u.codec.layout` property to `avformat` producer. + * Set the `channel_layout` property on the frame for the `noise` and `tone` + audio producers. + * Fixed `outline` maximum for the `text` and `dynamictext` filters. + +Other + * Fixed crash when using `-chain` from `melt`. + * Fixed a small memory leak on Windows `fopen()`. + + Version 7.22.0 Framework diff --git a/docs/melt.1 b/docs/melt.1 index 574cb1a82..de59facae 100644 --- a/docs/melt.1 +++ b/docs/melt.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.38.4. -.TH MELT "1" "November 2023" "melt 7.22.0" "User Commands" +.TH MELT "1" "April 2024" "melt 7.24.0" "User Commands" .SH NAME melt \- author, play, and encode multitrack audio/video compositions .SH SYNOPSIS @@ -149,7 +149,7 @@ Add a video\-only track .PP For more help: .SH COPYRIGHT -Copyright \(co 2002\-2023 Meltytech, LLC +Copyright \(co 2002\-2024 Meltytech, LLC .br This is free software; see the source for copying conditions. There is NO diff --git a/src/framework/mlt_version.h b/src/framework/mlt_version.h index 8fc33f35d..a3561fbfe 100644 --- a/src/framework/mlt_version.h +++ b/src/framework/mlt_version.h @@ -2,7 +2,7 @@ * \file mlt_version.h * \brief contains version information * - * Copyright (C) 2010-2023 Meltytech, LLC + * Copyright (C) 2010-2024 Meltytech, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #define MLT_STRINGIZE(s) MLT_STRINGIZE2(s) #define LIBMLT_VERSION_MAJOR 7 -#define LIBMLT_VERSION_MINOR 23 +#define LIBMLT_VERSION_MINOR 24 #define LIBMLT_VERSION_REVISION 0 #define LIBMLT_VERSION_INT \ ((LIBMLT_VERSION_MAJOR << 16) + (LIBMLT_VERSION_MINOR << 8) + LIBMLT_VERSION_REVISION) diff --git a/src/melt/melt.c b/src/melt/melt.c index 8a97b4ab1..224f4ebc7 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1,6 +1,6 @@ /* * melt.c -- MLT command line utility - * Copyright (C) 2002-2023 Meltytech, LLC + * Copyright (C) 2002-2024 Meltytech, LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -874,7 +874,7 @@ int main(int argc, char **argv) } else if (!strcmp(argv[i], "-version") || !strcmp(argv[i], "--version")) { fprintf(stdout, "%s " VERSION "\n" - "Copyright (C) 2002-2023 Meltytech, LLC\n" + "Copyright (C) 2002-2024 Meltytech, LLC\n" "\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", From ef36d29e89084f50648ae712c000541ab5cec1b8 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sun, 5 May 2024 22:14:25 -0700 Subject: [PATCH 102/130] fix movit transition with non-movit filter on input The chain fingerprint code did not handle the situation where one of its inputs could change. In this case, it was a transition whose inputs were not from the same chain: a non-movit filter interrupts it. `filter_movit_convert.cpp:set_movit_parameters()` would fail to locate the input, not set the pixel data, and return making rendering non- deterministic. https://forum.shotcut.org/t/text-simple-bug-with-gpu-efx-on/43892 --- CMakeLists.txt | 2 +- src/framework/mlt_version.h | 2 +- src/modules/movit/filter_glsl_manager.cpp | 17 +----------- src/modules/movit/filter_glsl_manager.h | 4 +-- src/modules/movit/filter_movit_convert.cpp | 31 +++++++++++++--------- src/modules/qt/filter_qtext.cpp | 1 + 6 files changed, 24 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28af9b2fd..ebaa833a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) project(MLT - VERSION 7.24.0 + VERSION 7.25.0 DESCRIPTION "Multimedia Framework" HOMEPAGE_URL "https://www.mltframework.org" LANGUAGES C CXX diff --git a/src/framework/mlt_version.h b/src/framework/mlt_version.h index a3561fbfe..79f27d24b 100644 --- a/src/framework/mlt_version.h +++ b/src/framework/mlt_version.h @@ -27,7 +27,7 @@ #define MLT_STRINGIZE(s) MLT_STRINGIZE2(s) #define LIBMLT_VERSION_MAJOR 7 -#define LIBMLT_VERSION_MINOR 24 +#define LIBMLT_VERSION_MINOR 25 #define LIBMLT_VERSION_REVISION 0 #define LIBMLT_VERSION_INT \ ((LIBMLT_VERSION_MAJOR << 16) + (LIBMLT_VERSION_MINOR << 8) + LIBMLT_VERSION_REVISION) diff --git a/src/modules/movit/filter_glsl_manager.cpp b/src/modules/movit/filter_glsl_manager.cpp index d73ee066f..bc862e759 100644 --- a/src/modules/movit/filter_glsl_manager.cpp +++ b/src/modules/movit/filter_glsl_manager.cpp @@ -1,7 +1,7 @@ /* * filter_glsl_manager.cpp * Copyright (C) 2011-2012 Christophe Thommeret - * Copyright (C) 2013-2023 Dan Dennedy + * Copyright (C) 2013-2024 Dan Dennedy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,6 @@ */ #include "filter_glsl_manager.h" -#include "mlt_flip_effect.h" #include "mlt_movit_input.h" #include #include @@ -265,20 +264,6 @@ void GlslManager::onClose(mlt_properties owner, GlslManager *filter, mlt_event_d filter->cleanupContext(); } -void GlslManager::onServiceChanged(mlt_properties owner, mlt_service aservice) -{ - Mlt::Service service(aservice); - service.lock(); - service.set("movit chain", NULL, 0); - service.unlock(); -} - -void GlslManager::onPropertyChanged(mlt_properties owner, mlt_service service, const char *property) -{ - if (property && std::string(property) == "disable") - onServiceChanged(owner, service); -} - extern "C" { mlt_filter filter_glsl_manager_init(mlt_profile profile, diff --git a/src/modules/movit/filter_glsl_manager.h b/src/modules/movit/filter_glsl_manager.h index fe6dd8827..00c56c0bf 100644 --- a/src/modules/movit/filter_glsl_manager.h +++ b/src/modules/movit/filter_glsl_manager.h @@ -1,6 +1,6 @@ /* * filter_glsl_manager.h - * Copyright (C) 2013-2023 Dan Dennedy + * Copyright (C) 2013-2024 Dan Dennedy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -141,8 +141,6 @@ class GlslManager : public Mlt::Filter static void onInit(mlt_properties owner, GlslManager *filter, mlt_event_data); static void onClose(mlt_properties owner, GlslManager *filter, mlt_event_data); - static void onServiceChanged(mlt_properties owner, mlt_service service); - static void onPropertyChanged(mlt_properties owner, mlt_service service, const char *property); movit::ResourcePool *resource_pool; Mlt::Deque texture_list; Mlt::Deque syncs_to_delete; diff --git a/src/modules/movit/filter_movit_convert.cpp b/src/modules/movit/filter_movit_convert.cpp index bd650a0cb..0663f49dd 100644 --- a/src/modules/movit/filter_movit_convert.cpp +++ b/src/modules/movit/filter_movit_convert.cpp @@ -1,6 +1,6 @@ /* * filter_movit_convert.cpp - * Copyright (C) 2013-2023 Dan Dennedy + * Copyright (C) 2013-2024 Dan Dennedy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -205,16 +205,23 @@ static void get_format_from_properties(mlt_properties properties, ycbcr_format->cb_y_position = ycbcr_format->cr_y_position = 0.5f; } -static void build_fingerprint(mlt_service service, mlt_frame frame, std::string *fingerprint) +static void build_fingerprint(GlslChain *chain, + mlt_service service, + mlt_frame frame, + std::string *fingerprint) { if (service == (mlt_service) -1) { - fingerprint->append("input"); + mlt_producer producer = mlt_producer_cut_parent(mlt_frame_get_original_producer(frame)); + if (producer && chain && chain->inputs[producer]) + fingerprint->append(mlt_properties_get(MLT_PRODUCER_PROPERTIES(producer), "_unique_id")); + else + fingerprint->append("input"); return; } mlt_service input_a = GlslManager::get_effect_input(service, frame); fingerprint->push_back('('); - build_fingerprint(input_a, frame, fingerprint); + build_fingerprint(chain, input_a, frame, fingerprint); fingerprint->push_back(')'); mlt_frame frame_b; @@ -222,14 +229,14 @@ static void build_fingerprint(mlt_service service, mlt_frame frame, std::string GlslManager::get_effect_secondary_input(service, frame, &input_b, &frame_b); if (input_b) { fingerprint->push_back('('); - build_fingerprint(input_b, frame_b, fingerprint); + build_fingerprint(chain, input_b, frame_b, fingerprint); fingerprint->push_back(')'); } GlslManager::get_effect_third_input(service, frame, &input_b, &frame_b); if (input_b) { fingerprint->push_back('('); - build_fingerprint(input_b, frame_b, fingerprint); + build_fingerprint(chain, input_b, frame_b, fingerprint); fingerprint->push_back(')'); } @@ -321,15 +328,15 @@ static void finalize_movit_chain(mlt_service leaf_service, mlt_frame frame, mlt_ GlslChain *chain = GlslManager::get_chain(leaf_service); std::string new_fingerprint; - build_fingerprint(leaf_service, frame, &new_fingerprint); + build_fingerprint(chain, leaf_service, frame, &new_fingerprint); // Build the chain if needed. if (!chain || new_fingerprint != chain->fingerprint) { - mlt_log_debug(leaf_service, - "=== CREATING NEW CHAIN (old chain=%p, leaf=%p, fingerprint=%s) ===\n", - chain, - leaf_service, - new_fingerprint.c_str()); + mlt_log_info(leaf_service, + "=== CREATING NEW CHAIN (old chain=%p, leaf=%p, fingerprint=%s) ===\n", + chain, + leaf_service, + new_fingerprint.c_str()); mlt_profile profile = mlt_service_profile(leaf_service); chain = new GlslChain; chain->effect_chain = new EffectChain(profile->display_aspect_num, diff --git a/src/modules/qt/filter_qtext.cpp b/src/modules/qt/filter_qtext.cpp index 949b4986c..79618477f 100644 --- a/src/modules/qt/filter_qtext.cpp +++ b/src/modules/qt/filter_qtext.cpp @@ -326,6 +326,7 @@ static int filter_get_image(mlt_frame frame, mlt_properties filter_properties = get_filter_properties(filter, frame); mlt_profile profile = mlt_service_profile(MLT_FILTER_SERVICE(filter)); mlt_position position = mlt_filter_get_position(filter, frame); + mlt_log_info(MLT_FILTER_SERVICE(filter), "get_image %p %d\n", filter, position); mlt_position length = mlt_filter_get_length2(filter, frame); bool isRichText = qstrlen(mlt_properties_get(filter_properties, "html")) > 0 || qstrlen(mlt_properties_get(filter_properties, "resource")) > 0; From 0aa27812f7716a5b8a4b568f1427ad18950a5a07 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Sun, 5 May 2024 22:29:19 -0700 Subject: [PATCH 103/130] revert log changes --- src/modules/movit/filter_movit_convert.cpp | 10 +++++----- src/modules/qt/filter_qtext.cpp | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/modules/movit/filter_movit_convert.cpp b/src/modules/movit/filter_movit_convert.cpp index 0663f49dd..73619d447 100644 --- a/src/modules/movit/filter_movit_convert.cpp +++ b/src/modules/movit/filter_movit_convert.cpp @@ -332,11 +332,11 @@ static void finalize_movit_chain(mlt_service leaf_service, mlt_frame frame, mlt_ // Build the chain if needed. if (!chain || new_fingerprint != chain->fingerprint) { - mlt_log_info(leaf_service, - "=== CREATING NEW CHAIN (old chain=%p, leaf=%p, fingerprint=%s) ===\n", - chain, - leaf_service, - new_fingerprint.c_str()); + mlt_log_debug(leaf_service, + "=== CREATING NEW CHAIN (old chain=%p, leaf=%p, fingerprint=%s) ===\n", + chain, + leaf_service, + new_fingerprint.c_str()); mlt_profile profile = mlt_service_profile(leaf_service); chain = new GlslChain; chain->effect_chain = new EffectChain(profile->display_aspect_num, diff --git a/src/modules/qt/filter_qtext.cpp b/src/modules/qt/filter_qtext.cpp index 79618477f..949b4986c 100644 --- a/src/modules/qt/filter_qtext.cpp +++ b/src/modules/qt/filter_qtext.cpp @@ -326,7 +326,6 @@ static int filter_get_image(mlt_frame frame, mlt_properties filter_properties = get_filter_properties(filter, frame); mlt_profile profile = mlt_service_profile(MLT_FILTER_SERVICE(filter)); mlt_position position = mlt_filter_get_position(filter, frame); - mlt_log_info(MLT_FILTER_SERVICE(filter), "get_image %p %d\n", filter, position); mlt_position length = mlt_filter_get_length2(filter, frame); bool isRichText = qstrlen(mlt_properties_get(filter_properties, "html")) > 0 || qstrlen(mlt_properties_get(filter_properties, "resource")) > 0; From f4785b6fe2b4f4ca332a6f0acf87b1a1c9ed45e1 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Mon, 6 May 2024 08:56:34 -0700 Subject: [PATCH 104/130] fix gitlab CI for ubuntu:24.04 --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b7b2bb83..a032a23b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,13 +1,13 @@ -ubuntu-latest: - image: ubuntu:latest +ubuntu-24.04: + image: ubuntu:24.04 script: - - sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" + - sed -i 's/^Types: deb/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources - DEBIAN_FRONTEND=noninteractive apt-get -qq update - DEBIAN_FRONTEND=noninteractive apt-get -yqq build-dep mlt - DEBIAN_FRONTEND=noninteractive apt-get -yqq install cmake - cmake -DCMAKE_BUILD_TYPE=Debug . && make -j -f Makefile install -ubuntu-lts: +ubuntu-22.04: image: ubuntu:22.04 script: - sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" From a2aa6548b158046535eba2d36cd98d121040b076 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Mon, 6 May 2024 09:07:35 -0700 Subject: [PATCH 105/130] fix gitlab CI YAML --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a032a23b9..5f6bc8af0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ ubuntu-24.04: image: ubuntu:24.04 script: - - sed -i 's/^Types: deb/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources + - "sed -i 's/^Types: deb/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources" - DEBIAN_FRONTEND=noninteractive apt-get -qq update - DEBIAN_FRONTEND=noninteractive apt-get -yqq build-dep mlt - DEBIAN_FRONTEND=noninteractive apt-get -yqq install cmake From 23b79f5b4eb013dc09e0ccabc656338fe634b06a Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Tue, 14 May 2024 17:43:13 -0700 Subject: [PATCH 106/130] add "nvdec" as alias for hwaccel "cuda" --- src/modules/avformat/producer_avformat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 6a73cd95d..dcc1d2d7f 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1105,7 +1105,7 @@ static int producer_open( self->hwaccel.pix_fmt = AV_PIX_FMT_VAAPI; self->hwaccel.device_type = AV_HWDEVICE_TYPE_VAAPI; device = "/dev/dri/renderD128"; - } else if (!strcmp(hwaccel->value, "cuda")) { + } else if (!strcmp(hwaccel->value, "cuda") || !strcmp(hwaccel->value, "nvdec")) { self->hwaccel.pix_fmt = AV_PIX_FMT_CUDA; self->hwaccel.device_type = AV_HWDEVICE_TYPE_CUDA; device = "0"; From 4c4053fd08ce54fff1d9204b041396173964b2ce Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Tue, 14 May 2024 18:26:25 -0700 Subject: [PATCH 107/130] prefer r_frame_rate over avg_frame_rate AVStream.r_frame_rate (tbr in ffmpeg/ffprobe output) gives the more common, standard frame rates smart phone cameras. It is what ffmpeg CLI uses if you use it to convert variable frame rate to constant. Extend the variable frame rate heuristic in property "meta.media.variable_frame_rate" by checking for bizarre AVStream.avg_frame_rate values. This also fixes a bug where raw DV files are reporting 60000 (sixty thousand) frames per second--at least with version 6 or 7 of FFmpeg. --- src/modules/avformat/producer_avformat.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index dcc1d2d7f..54d9fc659 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1309,10 +1309,23 @@ static void find_first_pts(producer_avformat self, int video_index) } av_packet_unref(&pkt); } - if (vfr_counter >= VFR_THRESHOLD) + + // Determine if this is variable frame rate video + int vfr = vfr_counter >= VFR_THRESHOLD; + if (!vfr) { + AVStream *stream = self->video_format ? self->video_format->streams[video_index] : NULL; + if (stream) { + int d = stream->avg_frame_rate.den; + vfr = d != 0 && d != 1 && d != 2 && d != 125 && d != 1001; + } + } + if (vfr) { mlt_properties_set_int(MLT_PRODUCER_PROPERTIES(self->parent), "meta.media.variable_frame_rate", 1); + } + + // Reset context position av_seek_frame(context, -1, 0, AVSEEK_FLAG_BACKWARD); } @@ -2734,12 +2747,12 @@ static int video_codec_init(producer_avformat self, int index, mlt_properties pr get_aspect_ratio(properties, stream, codec_params); // Start with the muxer frame rate. - AVRational frame_rate = stream->avg_frame_rate; + AVRational frame_rate = stream->r_frame_rate; double fps = av_q2d(frame_rate); // Verify and sanitize the muxer frame rate. if (isnan(fps) || isinf(fps) || fps == 0) { - frame_rate = stream->r_frame_rate; + frame_rate = stream->avg_frame_rate; fps = av_q2d(frame_rate); } // With my samples when r_frame_rate != 1000 but avg_frame_rate is valid, From 5f22110d8f5f9e50e7167af2a73729717f484b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 15 May 2024 13:21:56 +0200 Subject: [PATCH 108/130] producer_avformat: Fix lowres if set too high --- src/modules/avformat/producer_avformat.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 59d79fabd..bf5c343a8 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2281,6 +2281,13 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p if ( thread_count >= 0 ) codec_context->thread_count = thread_count; + // fix lowres if set too high + int lowres = mlt_properties_get_int(properties, "lowres"); + if (lowres > codec_context->codec->max_lowres) { + mlt_log_debug( MLT_PRODUCER_SERVICE( self->parent ), "clamping lowres=%i to max_lowres=%i\n", lowres, codec_context->codec->max_lowres ); + mlt_properties_set_int(properties, "lowres", codec_context->codec->max_lowres); + } + #if USE_HWACCEL if ( self->hwaccel.device_type == AV_HWDEVICE_TYPE_NONE || self->hwaccel.pix_fmt == AV_PIX_FMT_NONE ) { From fb3f2a980f7f6d0e837772fd74c37292f63a3ee0 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 15 May 2024 09:40:41 -0700 Subject: [PATCH 109/130] more places to prefer r_frame_rate Also used in property "meta.media.%u.stream.frame_rate" and filter graph for orientation. --- src/modules/avformat/producer_avformat.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 54d9fc659..3bc396236 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -448,10 +448,10 @@ static mlt_properties find_default_streams(producer_avformat self) } mlt_properties_set(meta_media, key, "video"); snprintf(key, sizeof(key), "meta.media.%u.stream.frame_rate", i); - double avg_frame_rate = av_q2d(context->streams[i]->avg_frame_rate); - double ffmpeg_fps = isfinite(avg_frame_rate) - ? avg_frame_rate - : av_q2d(context->streams[i]->r_frame_rate); + double r_frame_rate = av_q2d(context->streams[i]->r_frame_rate); + double ffmpeg_fps = isfinite(r_frame_rate) + ? r_frame_rate + : av_q2d(context->streams[i]->avg_frame_rate); mlt_properties_set_double(meta_media, key, ffmpeg_fps); const char *projection = get_projection(context->streams[i]); @@ -888,8 +888,8 @@ static int setup_video_filters(producer_avformat self) stream->time_base.den, mlt_properties_get_int(properties, "meta.media.sample_aspect_num"), FFMAX(mlt_properties_get_int(properties, "meta.media.sample_aspect_den"), 1), - stream->avg_frame_rate.num, - FFMAX(stream->avg_frame_rate.den, 1)); + stream->r_frame_rate.num, + FFMAX(stream->r_frame_rate.den, 1)); int result = avfilter_graph_create_filter(&self->vfilter_in, avfilter_get_by_name("buffer"), From 296da35699cd2d284d322fa6ceb6f9070a1ebe91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 15 May 2024 13:21:56 +0200 Subject: [PATCH 110/130] producer_avformat: Fix #985 lowres if set too high --- src/modules/avformat/producer_avformat.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 3bc396236..14bb54671 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2663,6 +2663,13 @@ static int video_codec_init(producer_avformat self, int index, mlt_properties pr if (thread_count >= 0) codec_context->thread_count = thread_count; + // fix lowres if set too high + int lowres = mlt_properties_get_int(properties, "lowres"); + if (lowres > codec_context->codec->max_lowres) { + mlt_log_debug( MLT_PRODUCER_SERVICE( self->parent ), "clamping lowres=%i to max_lowres=%i\n", lowres, codec_context->codec->max_lowres ); + mlt_properties_set_int(properties, "lowres", codec_context->codec->max_lowres); + } + #if USE_HWACCEL if (self->hwaccel.device_type == AV_HWDEVICE_TYPE_NONE || self->hwaccel.pix_fmt == AV_PIX_FMT_NONE) { From 857e35836c4ec85681040391c05e1f3173f08ef2 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 15 May 2024 16:11:18 -0700 Subject: [PATCH 111/130] clang-format --- src/modules/avformat/producer_avformat.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 14bb54671..d7b169f0b 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2663,12 +2663,15 @@ static int video_codec_init(producer_avformat self, int index, mlt_properties pr if (thread_count >= 0) codec_context->thread_count = thread_count; - // fix lowres if set too high - int lowres = mlt_properties_get_int(properties, "lowres"); - if (lowres > codec_context->codec->max_lowres) { - mlt_log_debug( MLT_PRODUCER_SERVICE( self->parent ), "clamping lowres=%i to max_lowres=%i\n", lowres, codec_context->codec->max_lowres ); - mlt_properties_set_int(properties, "lowres", codec_context->codec->max_lowres); - } + // fix lowres if set too high + int lowres = mlt_properties_get_int(properties, "lowres"); + if (lowres > codec_context->codec->max_lowres) { + mlt_log_debug(MLT_PRODUCER_SERVICE(self->parent), + "clamping lowres=%i to max_lowres=%i\n", + lowres, + codec_context->codec->max_lowres); + mlt_properties_set_int(properties, "lowres", codec_context->codec->max_lowres); + } #if USE_HWACCEL if (self->hwaccel.device_type == AV_HWDEVICE_TYPE_NONE From 5426d3bf4ec2a9d50f040e228a3a9fb22c7775ba Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 24 May 2024 14:47:54 -0700 Subject: [PATCH 112/130] fix compile warning pointer-to-int-cast --- src/modules/avformat/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/avformat/common.c b/src/modules/avformat/common.c index a316f8d18..11d03f210 100644 --- a/src/modules/avformat/common.c +++ b/src/modules/avformat/common.c @@ -223,7 +223,7 @@ mlt_channel_layout av_channel_layout_to_mlt(int64_t layout) case AV_CH_LAYOUT_7POINT1_WIDE_BACK: return mlt_channel_7p1_wide_back; } - mlt_log_error(NULL, "[avformat] Unknown channel layout: %lu\n", (unsigned long) layout); + mlt_log_error(NULL, "[avformat] Unknown channel layout: %lu\n", (unsigned long) layout->u.mask); return mlt_channel_independent; } From 5c398155b04d93e2909f6c2f47801fedb2d4576d Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 24 May 2024 14:49:09 -0700 Subject: [PATCH 113/130] fix compile warning in glaxnimate module on gcc 14 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebaa833a2..a7f105dfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE STREQUAL "Debug") set(GCC_FLAGS "-Wall -Werror -Wno-deprecated-declarations") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_FLAGS} -Wno-class-memaccess -Wno-array-compare -Wno-unused-result -Wno-maybe-uninitialized") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_FLAGS} -Wno-discarded-qualifiers") + # The following showed up in GCC 14, which I am using via msys2 on Windows. + # Remove the following when Glaxnimate is fixed. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++20-compat -Wno-dangling-reference") endif () if(MSVC) From a1e83149913ea3c611b4c43e7e9149cde385adbc Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 24 May 2024 14:55:57 -0700 Subject: [PATCH 114/130] fix compile error on FFmpeg < 7 --- src/modules/avformat/common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/avformat/common.c b/src/modules/avformat/common.c index 11d03f210..128a212ac 100644 --- a/src/modules/avformat/common.c +++ b/src/modules/avformat/common.c @@ -162,12 +162,13 @@ mlt_channel_layout av_channel_layout_to_mlt(AVChannelLayout *layout) if (layout->order != AV_CHANNEL_ORDER_NATIVE && layout->order != AV_CHANNEL_ORDER_AMBISONIC) { return mlt_channel_independent; } - switch (layout->u.mask) { + unsigned long layout_id = layout->u.mask; #else mlt_channel_layout av_channel_layout_to_mlt(int64_t layout) { - switch (layout) { + unsigned long layout_id = layout; #endif + switch (layout_id) { case 0: return mlt_channel_independent; case AV_CH_LAYOUT_MONO: @@ -223,7 +224,7 @@ mlt_channel_layout av_channel_layout_to_mlt(int64_t layout) case AV_CH_LAYOUT_7POINT1_WIDE_BACK: return mlt_channel_7p1_wide_back; } - mlt_log_error(NULL, "[avformat] Unknown channel layout: %lu\n", (unsigned long) layout->u.mask); + mlt_log_error(NULL, "[avformat] Unknown channel layout: %lu\n", layout_id); return mlt_channel_independent; } From f27a61e7508675e6d6526295e9422c9966139e3f Mon Sep 17 00:00:00 2001 From: Austin Brooks Date: Wed, 29 May 2024 16:00:45 -0400 Subject: [PATCH 115/130] switch AV1 encode presets to SVT-AV1 --- presets/consumer/avformat/AV1 | 1 + presets/consumer/avformat/SVT-AV1 | 16 ++++++++++++++++ presets/consumer/avformat/ten_bit/AV1 | 1 + presets/consumer/avformat/ten_bit/SVT-AV1 | 17 +++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 presets/consumer/avformat/SVT-AV1 create mode 100644 presets/consumer/avformat/ten_bit/SVT-AV1 diff --git a/presets/consumer/avformat/AV1 b/presets/consumer/avformat/AV1 index a53d986bc..b9a9101de 100644 --- a/presets/consumer/avformat/AV1 +++ b/presets/consumer/avformat/AV1 @@ -16,3 +16,4 @@ strict=experimental meta.preset.name=AV1 WebM meta.preset.extension=webm meta.preset.note=AV1 video with Opus audio in Matroska container: Just say no to patents +meta.preset.hidden=1 diff --git a/presets/consumer/avformat/SVT-AV1 b/presets/consumer/avformat/SVT-AV1 new file mode 100644 index 000000000..991e49acb --- /dev/null +++ b/presets/consumer/avformat/SVT-AV1 @@ -0,0 +1,16 @@ +f=webm + +acodec=libopus +ar=48000 +ab=192k +vbr=off + +vcodec=libsvtav1 +crf=32 +bf=1 +svtav1-params=preset=5:tile-columns=1:fast-decode=0:tune=0:film-grain=0:film-grain-denoise=0:enable-overlays=1:enable-variance-boost=1:variance-boost-strength=1:variance-octile=7:enable-qm=1:qm-min=0 +progressive=1 + +meta.preset.name=AV1 WebM +meta.preset.extension=webm +meta.preset.note=AV1 video with Opus audio in WebM container: Just say no to patents diff --git a/presets/consumer/avformat/ten_bit/AV1 b/presets/consumer/avformat/ten_bit/AV1 index f7c890edc..8f0fb0ca5 100644 --- a/presets/consumer/avformat/ten_bit/AV1 +++ b/presets/consumer/avformat/ten_bit/AV1 @@ -17,3 +17,4 @@ pix_fmt=yuv420p10le meta.preset.name=ten_bit/10-bit AV1 WebM meta.preset.extension=webm meta.preset.note=10-bit AV1 video with Opus audio in Matroska container: Just say no to patents +meta.preset.hidden=1 diff --git a/presets/consumer/avformat/ten_bit/SVT-AV1 b/presets/consumer/avformat/ten_bit/SVT-AV1 new file mode 100644 index 000000000..24660093e --- /dev/null +++ b/presets/consumer/avformat/ten_bit/SVT-AV1 @@ -0,0 +1,17 @@ +f=webm + +acodec=libopus +ar=48000 +ab=192k +vbr=off + +vcodec=libsvtav1 +crf=32 +bf=1 +svtav1-params=preset=5:tile-columns=1:fast-decode=0:tune=0:film-grain=0:film-grain-denoise=0:enable-overlays=1:enable-variance-boost=1:variance-boost-strength=1:variance-octile=7:enable-qm=1:qm-min=0 +pix_fmt=yuv420p10le +progressive=1 + +meta.preset.name=ten_bit/10-bit AV1 WebM +meta.preset.extension=webm +meta.preset.note=10-bit AV1 video with Opus audio in WebM container: Just say no to patents From 9dc23e6cc39ad57794d3be6886f1c086040d7779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 31 May 2024 14:16:22 +0200 Subject: [PATCH 116/130] jit.c: Tabs -> spaces --- src/melt/jit.c | 314 ++++++++++++++++++++++++------------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/src/melt/jit.c b/src/melt/jit.c index cf3928498..f46be60cd 100644 --- a/src/melt/jit.c +++ b/src/melt/jit.c @@ -18,83 +18,83 @@ static socklen_t jit_sock_addr_len = 0; static void jit_action( mlt_producer producer, char *value ) { - mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); - mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); - mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); - - JitControl *const jit_control = (JitControl*) value; - switch (jit_control->type) { - case CONTROL_TYPE__PAUSE: - if (mlt_producer_get_speed( producer ) != 0) { - mlt_producer_set_speed( producer, 0 ); - mlt_consumer_purge( consumer ); - if (jit_status.playing) { - if (jit_control->has_seek_position) { - mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); - } else { - //mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); - } - } - } - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - jit_status.playing = 0; - break; - case CONTROL_TYPE__PLAY: - if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { - mlt_producer_set_speed( producer, jit_control->play_rate ); - } - mlt_consumer_purge( consumer ); - mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); - jit_status.playing = 1; - break; - - case CONTROL_TYPE__PLAY_RATE: - mlt_producer_set_speed( producer, jit_control->play_rate ); - break; - - case CONTROL_TYPE__SEEK: - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); - fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); - break; - case CONTROL_TYPE__SEEK_REL: ; - const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); - mlt_consumer_purge( consumer ); - mlt_producer_seek( producer, pos); - fire_jack_seek_event(jack, pos); - break; - case CONTROL_TYPE__QUIT: - mlt_properties_set_int( properties, "done", 1 ); - mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); - break; - default: - break; - } - mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); + mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); + mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); + + JitControl *const jit_control = (JitControl*) value; + switch (jit_control->type) { + case CONTROL_TYPE__PAUSE: + if (mlt_producer_get_speed( producer ) != 0) { + mlt_producer_set_speed( producer, 0 ); + mlt_consumer_purge( consumer ); + if (jit_status.playing) { + if (jit_control->has_seek_position) { + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); + } else { + //mlt_producer_seek( producer, mlt_consumer_position( consumer ) - 2 ); + } + } + } + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + jit_status.playing = 0; + break; + case CONTROL_TYPE__PLAY: + if ( !jack || mlt_producer_get_speed( producer ) != 0 ) { + mlt_producer_set_speed( producer, jit_control->play_rate ); + } + mlt_consumer_purge( consumer ); + mlt_events_fire( jack, "jack-start", mlt_event_data_none() ); + jit_status.playing = 1; + break; + + case CONTROL_TYPE__PLAY_RATE: + mlt_producer_set_speed( producer, jit_control->play_rate ); + break; + + case CONTROL_TYPE__SEEK: + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, llround(fps_multiplier * jit_control->seek_position)); + fire_jack_seek_event(jack, llround(fps_multiplier * jit_control->seek_position)); + break; + case CONTROL_TYPE__SEEK_REL: ; + const mlt_position pos = mlt_producer_position(producer) + (jit_control->seek_position < 0 ? floor(fps_multiplier * jit_control->seek_position) : ceil(fps_multiplier * jit_control->seek_position)); + mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, pos); + fire_jack_seek_event(jack, pos); + break; + case CONTROL_TYPE__QUIT: + mlt_properties_set_int( properties, "done", 1 ); + mlt_events_fire( jack, "jack-stop", mlt_event_data_none() ); + break; + default: + break; + } + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); } static JitControl *read_control() { - static uint8_t buf[1 * 1024 * 1024]; // 1 MB - fd_set set; - FD_ZERO(&set); - FD_SET(melt_sock_fd, &set); - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (melt_sock_fd < 0 || select(melt_sock_fd + 1, &set, NULL, NULL, &timeout) <= 0) { - return NULL; - } - - jit_sock_addr_len = sizeof jit_sock_addr; - const ssize_t r = recvfrom(melt_sock_fd, buf, sizeof buf, 0, (struct sockaddr*) &jit_sock_addr, &jit_sock_addr_len); - if (r < 1) { - perror("read"); - exit(1); - } else if (r == sizeof buf) { - fprintf(stderr, "read buffer overflow\n"); - exit(1); - } - return jit_control__unpack(NULL, r, buf); + static uint8_t buf[1 * 1024 * 1024]; // 1 MB + fd_set set; + FD_ZERO(&set); + FD_SET(melt_sock_fd, &set); + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (melt_sock_fd < 0 || select(melt_sock_fd + 1, &set, NULL, NULL, &timeout) <= 0) { + return NULL; + } + + jit_sock_addr_len = sizeof jit_sock_addr; + const ssize_t r = recvfrom(melt_sock_fd, buf, sizeof buf, 0, (struct sockaddr*) &jit_sock_addr, &jit_sock_addr_len); + if (r < 1) { + perror("read"); + exit(1); + } else if (r == sizeof buf) { + fprintf(stderr, "read buffer overflow\n"); + exit(1); + } + return jit_control__unpack(NULL, r, buf); } static void write_status(JitStatus *const jit_status) { @@ -109,102 +109,102 @@ static void write_status(JitStatus *const jit_status) { if (buf_len < len) { buf = realloc(buf, len); if (!buf) { - perror("realloc"); + perror("realloc"); exit(1); } buf_len = len; } - jit_status__pack(jit_status, buf); - if (sendto(melt_sock_fd, buf, len, 0, (struct sockaddr*) &jit_sock_addr, jit_sock_addr_len) != len) { - perror("sendto"); - exit(1); - } + jit_status__pack(jit_status, buf); + if (sendto(melt_sock_fd, buf, len, 0, (struct sockaddr*) &jit_sock_addr, jit_sock_addr_len) != len) { + perror("sendto"); + exit(1); + } } static mlt_producer find_producer_avformat(mlt_producer p) { - mlt_tractor tractor = (mlt_tractor) p; - mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); - mlt_playlist playlist = (mlt_playlist) mlt_multitrack_track(multitrack, 0); - return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); + mlt_tractor tractor = (mlt_tractor) p; + mlt_multitrack multitrack = mlt_tractor_multitrack(tractor); + mlt_playlist playlist = (mlt_playlist) mlt_multitrack_track(multitrack, 0); + return mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(mlt_playlist_get_clip(playlist, 0)), "_cut_parent", NULL); } static void open_status_pipe(void) { - melt_sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (melt_sock_fd < 0) { - perror("socket"); - exit(2); - } - - memset(&jit_sock_addr, 0, sizeof jit_sock_addr); - jit_sock_addr.sun_family = AF_UNIX; - snprintf(jit_sock_addr.sun_path, sizeof jit_sock_addr, "/tmp/melt-sock-%lld", (long long) getppid()); - fprintf(stdout, "Creating status socket: %s\n", jit_sock_addr.sun_path); - fflush(stdout); - - if (bind(melt_sock_fd, (struct sockaddr*) &jit_sock_addr, sizeof jit_sock_addr) < 0) { - perror("bind"); - exit(2); - } - fprintf(stdout, "Status socket created\n"); - fflush(stdout); + melt_sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (melt_sock_fd < 0) { + perror("socket"); + exit(2); + } + + memset(&jit_sock_addr, 0, sizeof jit_sock_addr); + jit_sock_addr.sun_family = AF_UNIX; + snprintf(jit_sock_addr.sun_path, sizeof jit_sock_addr, "/tmp/melt-sock-%lld", (long long) getppid()); + fprintf(stdout, "Creating status socket: %s\n", jit_sock_addr.sun_path); + fflush(stdout); + + if (bind(melt_sock_fd, (struct sockaddr*) &jit_sock_addr, sizeof jit_sock_addr) < 0) { + perror("bind"); + exit(2); + } + fprintf(stdout, "Status socket created\n"); + fflush(stdout); } static void print_media_info(void) { - mlt_producer av = find_producer_avformat(melt); - jit_status.media_info = calloc(1, sizeof (MediaInfo)); - media_info__init(jit_status.media_info); - jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); - jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); - const int frame_rate_num = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_num"); - const int frame_rate_den = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_den"); - if (frame_rate_num > 0 && frame_rate_den > 0) { - jit_status.has_frame_rate = 1; - jit_status.frame_rate = ((double) frame_rate_num) / ((double) frame_rate_den); - } - for (int i = 0; i < jit_status.media_info->n_streams; i++) { - Stream *s = calloc(sizeof (Stream), 1); - stream__init(s); - jit_status.media_info->streams[i] = s; - s->has_type = 1; - s->type = STREAM_TYPE__UNKNOWN; - char key[100]; - sprintf(key, "meta.media.%d.stream.type", i); - char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); - if (!value) { - continue; - } else if (!strcmp(value, "audio")) { - s->type = STREAM_TYPE__AUDIO; - s->audio = calloc(1, sizeof (AudioStream)); - audio_stream__init(s->audio); - sprintf(key, "meta.media.%d.codec.channels", i); - s->audio->has_channels = 1; - s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - jit_status.has_total_channels = 1; - jit_status.total_channels += s->audio->channels; - sprintf(key, "meta.attr.%d.stream.language.markup", i); - value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); - if (value) { - s->audio->language = strdup(value); - } - } else if (!strcmp(value, "video")) { - s->type = STREAM_TYPE__VIDEO; - s->video = calloc(1, sizeof (VideoStream)); - video_stream__init(s->video); - sprintf(key, "meta.media.%d.stream.frame_rate", i); - s->video->has_frame_rate = 1; - s->video->frame_rate = mlt_properties_get_double(MLT_PRODUCER_PROPERTIES(av), key); - if (!jit_status.has_frame_rate) { - jit_status.has_frame_rate = 1; - jit_status.frame_rate = s->video->frame_rate; - } - sprintf(key, "meta.media.%d.codec.width", i); - s->video->has_width = 1; - s->video->width = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - sprintf(key, "meta.media.%d.codec.height", i); - s->video->has_height = 1; - s->video->height = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); - } - } + mlt_producer av = find_producer_avformat(melt); + jit_status.media_info = calloc(1, sizeof (MediaInfo)); + media_info__init(jit_status.media_info); + jit_status.media_info->n_streams = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.nb_streams"); + jit_status.media_info->streams = calloc(jit_status.media_info->n_streams, sizeof (Stream*)); + const int frame_rate_num = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_num"); + const int frame_rate_den = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), "meta.media.frame_rate_den"); + if (frame_rate_num > 0 && frame_rate_den > 0) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = ((double) frame_rate_num) / ((double) frame_rate_den); + } + for (int i = 0; i < jit_status.media_info->n_streams; i++) { + Stream *s = calloc(sizeof (Stream), 1); + stream__init(s); + jit_status.media_info->streams[i] = s; + s->has_type = 1; + s->type = STREAM_TYPE__UNKNOWN; + char key[100]; + sprintf(key, "meta.media.%d.stream.type", i); + char *value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (!value) { + continue; + } else if (!strcmp(value, "audio")) { + s->type = STREAM_TYPE__AUDIO; + s->audio = calloc(1, sizeof (AudioStream)); + audio_stream__init(s->audio); + sprintf(key, "meta.media.%d.codec.channels", i); + s->audio->has_channels = 1; + s->audio->channels = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + jit_status.has_total_channels = 1; + jit_status.total_channels += s->audio->channels; + sprintf(key, "meta.attr.%d.stream.language.markup", i); + value = mlt_properties_get(MLT_PRODUCER_PROPERTIES(av), key); + if (value) { + s->audio->language = strdup(value); + } + } else if (!strcmp(value, "video")) { + s->type = STREAM_TYPE__VIDEO; + s->video = calloc(1, sizeof (VideoStream)); + video_stream__init(s->video); + sprintf(key, "meta.media.%d.stream.frame_rate", i); + s->video->has_frame_rate = 1; + s->video->frame_rate = mlt_properties_get_double(MLT_PRODUCER_PROPERTIES(av), key); + if (!jit_status.has_frame_rate) { + jit_status.has_frame_rate = 1; + jit_status.frame_rate = s->video->frame_rate; + } + sprintf(key, "meta.media.%d.codec.width", i); + s->video->has_width = 1; + s->video->width = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + sprintf(key, "meta.media.%d.codec.height", i); + s->video->has_height = 1; + s->video->height = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(av), key); + } + } } From 77892ffe26aeb25112a30f9978c0465f9cfb306b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 31 May 2024 14:28:49 +0200 Subject: [PATCH 117/130] consumer_avformat: Also silence when speed == 0 --- src/modules/avformat/consumer_avformat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index 8c0e5609b..b49fbde1e 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -1924,7 +1924,7 @@ static void *consumer_thread(void *arg) } if (pcm) { // Silence only if going backward - if (mlt_properties_get_double(frame_properties, "_speed") < 0) + if (mlt_properties_get_double(frame_properties, "_speed") <= 0) memset(pcm, 0, samples * enc_ctx->channels * enc_ctx->sample_bytes); // Append the samples From b200315bc564f992c2e2e494d4b637848f1b8ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Fri, 31 May 2024 14:41:22 +0200 Subject: [PATCH 118/130] consumer_avformat: Set mute_on_pause=1 instead --- src/modules/avformat/consumer_avformat.c | 2 +- src/modules/avformat/producer_avformat.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index b49fbde1e..8c0e5609b 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -1924,7 +1924,7 @@ static void *consumer_thread(void *arg) } if (pcm) { // Silence only if going backward - if (mlt_properties_get_double(frame_properties, "_speed") <= 0) + if (mlt_properties_get_double(frame_properties, "_speed") < 0) memset(pcm, 0, samples * enc_ctx->channels * enc_ctx->sample_bytes); // Append the samples diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 6b340f0f5..6fb4c644c 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -266,7 +266,7 @@ mlt_producer producer_avformat_init(mlt_profile profile, const char *service, ch self, 0, (mlt_destructor) producer_avformat_close); - mlt_properties_set_int(properties, "mute_on_pause", 0); + mlt_properties_set_int(properties, "mute_on_pause", 1); mlt_events_listen(properties, self, "property-changed", From 27a99843d31d65d5548cffc03e247e088644a0d5 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 31 May 2024 10:24:09 -0700 Subject: [PATCH 119/130] fix duration in glaxnimate producer --- src/modules/glaxnimate/producer_glaxnimate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/glaxnimate/producer_glaxnimate.cpp b/src/modules/glaxnimate/producer_glaxnimate.cpp index 556918e49..6aa053dc0 100644 --- a/src/modules/glaxnimate/producer_glaxnimate.cpp +++ b/src/modules/glaxnimate/producer_glaxnimate.cpp @@ -1,6 +1,6 @@ /* * producer_glaxnimate.cpp -- a Glaxnimate/Qt based producer for MLT - * Copyright (C) 2022-2023 Meltytech, LLC + * Copyright (C) 2022-2024 Meltytech, LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +57,7 @@ class Glaxnimate int duration() const { auto frames = composition()->animation->last_frame.get() - - composition()->animation->first_frame.get() + 1.f; + - composition()->animation->first_frame.get(); return toMltFps(frames); } @@ -86,7 +86,7 @@ class Glaxnimate auto pos = mlt_frame_original_position(frame); if (mlt_properties_get(properties(), "eof") && !::strcmp("loop", mlt_properties_get(properties(), "eof"))) { - pos %= duration(); + pos %= duration() - 1; } auto bg = mlt_properties_get_color(properties(), "background"); auto background = QColor(bg.r, bg.g, bg.b, bg.a); From d4bdbccd2054dcc0e2a71be24e95ca1ad651a33d Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 31 May 2024 13:29:17 -0700 Subject: [PATCH 120/130] add dropshadow filter to qt module --- src/modules/qt/CMakeLists.txt | 2 + src/modules/qt/factory.c | 8 +- src/modules/qt/filter_dropshadow.cpp | 107 +++++++++++++++++++++++++++ src/modules/qt/filter_dropshadow.yml | 53 +++++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/modules/qt/filter_dropshadow.cpp create mode 100644 src/modules/qt/filter_dropshadow.yml diff --git a/src/modules/qt/CMakeLists.txt b/src/modules/qt/CMakeLists.txt index 658823108..597b0bce6 100644 --- a/src/modules/qt/CMakeLists.txt +++ b/src/modules/qt/CMakeLists.txt @@ -21,6 +21,7 @@ function(mlt_add_qt_module ARG_TARGET) factory.c filter_audiolevelgraph.cpp filter_audiowaveform.cpp + filter_dropshadow.cpp filter_gpsgraphic.cpp filter_gpsgraphic.h filter_gpstext.cpp filter_qtext.cpp @@ -100,6 +101,7 @@ function(mlt_add_qt_module ARG_TARGET) filter_audiolevelgraph.yml filter_audiospectrum.yml filter_audiowaveform.yml + filter_dropshadow.yml filter_gpsgraphic.yml filter_gpstext.yml filter_qtblend.yml diff --git a/src/modules/qt/factory.c b/src/modules/qt/factory.c index 9bc41f872..10d94bde2 100644 --- a/src/modules/qt/factory.c +++ b/src/modules/qt/factory.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2023 Meltytech, LLC + * Copyright (C) 2008-2024 Meltytech, LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,10 @@ extern mlt_filter filter_audiowaveform_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg); +extern mlt_filter filter_dropshadow_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg); extern mlt_filter filter_gpsgraphic_init(mlt_profile profile, mlt_service_type type, const char *id, @@ -109,6 +113,7 @@ MLT_REPOSITORY #endif MLT_REGISTER(mlt_service_filter_type, "audiolevelgraph", filter_audiolevelgraph_init); MLT_REGISTER(mlt_service_filter_type, "audiowaveform", filter_audiowaveform_init); + MLT_REGISTER(mlt_service_filter_type, "dropshadow", filter_dropshadow_init); MLT_REGISTER(mlt_service_filter_type, "gpsgraphic", filter_gpsgraphic_init); MLT_REGISTER(mlt_service_filter_type, "gpstext", filter_gpstext_init); MLT_REGISTER(mlt_service_filter_type, "qtext", filter_qtext_init); @@ -138,6 +143,7 @@ MLT_REPOSITORY "audiowaveform", metadata, "filter_audiowaveform.yml"); + MLT_REGISTER_METADATA(mlt_service_filter_type, "dropshadow", metadata, "filter_dropshadow.yml"); MLT_REGISTER_METADATA(mlt_service_filter_type, "gpsgraphic", metadata, "filter_gpsgraphic.yml"); MLT_REGISTER_METADATA(mlt_service_filter_type, "gpstext", metadata, "filter_gpstext.yml"); MLT_REGISTER_METADATA(mlt_service_filter_type, "qtext", metadata, "filter_qtext.yml"); diff --git a/src/modules/qt/filter_dropshadow.cpp b/src/modules/qt/filter_dropshadow.cpp new file mode 100644 index 000000000..f4efc9e15 --- /dev/null +++ b/src/modules/qt/filter_dropshadow.cpp @@ -0,0 +1,107 @@ +/* + * filter_dropshadow.cpp -- Drop Shadow Effect + * Copyright (c) 2024 Meltytech, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include +#include +#include +#include +#include +#include + +static int get_image(mlt_frame frame, + uint8_t **image, + mlt_image_format *image_format, + int *width, + int *height, + int writable) +{ + auto error = 0; + auto filter = Mlt::Filter(mlt_filter(mlt_frame_pop_service(frame))); + + *image_format = mlt_image_rgba; + error = mlt_frame_get_image(frame, image, image_format, width, height, writable); + + if (!error) { + QImage qimg; + convert_mlt_to_qimage_rgba(*image, &qimg, *width, *height); + + auto shadow = new QGraphicsDropShadowEffect; + auto f = Mlt::Frame(frame); + mlt_position pos = filter.get_position(f); + mlt_position len = filter.get_length2(f); + auto color = filter.anim_get_color("color", pos, len); + shadow->setColor(QColor(color.r, color.g, color.b, color.a)); + shadow->setBlurRadius(filter.anim_get_double("radius", pos, len)); + shadow->setXOffset(filter.anim_get_double("x", pos, len)); + shadow->setYOffset(filter.anim_get_double("y", pos, len)); + + QGraphicsScene scene; + QGraphicsPixmapItem item; + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + item.setPixmap(QPixmap::fromImage(qimg)); + item.setGraphicsEffect(shadow); + scene.addItem(&item); + + QPainter painter(&qimg); + scene.render(&painter); + painter.end(); + convert_qimage_to_mlt_rgba(&qimg, *image, *width, *height); + } + + return error; +} + +static mlt_frame process(mlt_filter filter, mlt_frame frame) +{ + mlt_frame_push_service(frame, filter); + mlt_frame_push_get_image(frame, get_image); + + return frame; +} + +extern "C" { + +mlt_filter filter_dropshadow_init(mlt_profile profile, + mlt_service_type type, + const char *id, + char *arg) +{ + mlt_filter filter = mlt_filter_new(); + + if (!filter) + return nullptr; + + if (!createQApplicationIfNeeded(MLT_FILTER_SERVICE(filter))) { + mlt_filter_close(filter); + return nullptr; + } + + filter->process = process; + + auto properties = Mlt::Properties(filter); + properties.set("color", "#b4636363"); + properties.set("radius", 1.0); + properties.set("x", 8.0); + properties.set("y", 8.0); + + return filter; +} + +} // extern "C" diff --git a/src/modules/qt/filter_dropshadow.yml b/src/modules/qt/filter_dropshadow.yml new file mode 100644 index 000000000..124d893de --- /dev/null +++ b/src/modules/qt/filter_dropshadow.yml @@ -0,0 +1,53 @@ +schema_version: 7.0 +type: filter +identifier: dropshadow +title: Drop Shadow +version: 1 +copyright: Meltytech, LLC +license: LGPLv2.1 +language: en +tags: + - Video +description: Create a shadow effect from the alpha channel. + +parameters: + - identifier: color + title: Color + type: color + description: The color of the shadow including alpha + default: "#b4636363" + readonly: no + mutable: yes + animation: yes + widget: color + + - identifier: radius + title: Blur radius + type: float + description: The amount to blur the edge of the shadow + default: 1 + readonly: no + mutable: yes + animation: yes + widget: spinner + unit: pixels + + - identifier: x + title: X Offset + type: float + description: The relative horizontal position of the shadow + default: 8.0 + readonly: no + mutable: yes + animation: yes + widget: spinner + + - identifier: y + title: Y Offset + type: float + description: The relative vertical position of the shadow + default: 8.0 + readonly: no + mutable: yes + animation: yes + widget: spinner From dc15d1db4aa6d1f891966756e0f512073d2db7b4 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Tue, 4 Jun 2024 10:00:22 -0700 Subject: [PATCH 121/130] fix #990 compile error: undeclared identifiers --- src/modules/rubberband/filter_rbpitch.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/rubberband/filter_rbpitch.cpp b/src/modules/rubberband/filter_rbpitch.cpp index 03ef7e620..767d99da6 100644 --- a/src/modules/rubberband/filter_rbpitch.cpp +++ b/src/modules/rubberband/filter_rbpitch.cpp @@ -23,8 +23,9 @@ #include #include +#include +#include #include -#include using namespace RubberBand; From 65a411bbb8994c2971123189ea45df386bf315c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 4 Jun 2024 18:47:05 +0200 Subject: [PATCH 122/130] avformat_producer: Use AVRational in video timestamp calculation and seeking Don't touch the initialization, metadata or audio code --- src/modules/avformat/producer_avformat.c | 43 ++++++++++++++++-------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index d7b169f0b..2eb074d84 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1348,8 +1348,10 @@ static int seek_video(producer_avformat self, AVFormatContext *context = self->video_format; // We may want to use the source fps if available - double source_fps = mlt_properties_get_double(properties, "meta.media.frame_rate_num") - / mlt_properties_get_double(properties, "meta.media.frame_rate_den"); + AVRational source_fps = av_make_q( + mlt_properties_get_double(properties, "meta.media.frame_rate_num"), + mlt_properties_get_double(properties, "meta.media.frame_rate_den") + ); if (self->first_pts == AV_NOPTS_VALUE && self->last_position == POSITION_INITIAL) find_first_pts(self, self->video_index); @@ -1361,15 +1363,20 @@ static int seek_video(producer_avformat self, || position - self->video_expected >= seek_threshold || self->last_position < 0) { // Calculate the timestamp for the requested frame - int64_t timestamp = req_position / (av_q2d(self->video_time_base) * source_fps); + int64_t timestamp = av_rescale_q_rnd( + req_position, + av_inv_q(self->video_time_base), + source_fps, + AV_ROUND_ZERO + ); if (req_position <= 0) timestamp = 0; else if (self->first_pts != AV_NOPTS_VALUE) timestamp += self->first_pts; else if (context->start_time != AV_NOPTS_VALUE) timestamp += context->start_time; - if (preseek && av_q2d(self->video_time_base) != 0) - timestamp -= 2 / av_q2d(self->video_time_base); + if (preseek && self->video_time_base.num != 0) + timestamp = av_add_stable(self->video_time_base, timestamp, AV_TIME_BASE_Q, -2 * AV_TIME_BASE); if (timestamp < 0) timestamp = 0; mlt_log_debug(MLT_PRODUCER_SERVICE(producer), @@ -2182,17 +2189,21 @@ static int producer_get_image(mlt_frame frame, // Cache miss // We may want to use the source fps if available - double source_fps = mlt_properties_get_double(properties, "meta.media.frame_rate_num") - / mlt_properties_get_double(properties, "meta.media.frame_rate_den"); + int source_fps_num = mlt_properties_get_int(properties, "meta.media.frame_rate_num"); + int source_fps_den = mlt_properties_get_int(properties, "meta.media.frame_rate_den"); + mlt_profile profile = mlt_service_profile(MLT_PRODUCER_SERVICE(self->parent)); + AVRational source_fps = av_make_q(source_fps_num, source_fps_den); + AVRational profile_fps = av_make_q(profile->frame_rate_num, profile->frame_rate_den); // This is the physical frame position in the source - int64_t req_position = (int64_t) (position / mlt_producer_get_fps(producer) * source_fps + 0.5); + int64_t req_position = av_rescale_q(position, source_fps, profile_fps); // Determines if we have to decode all frames in a sequence - when there temporal compression is used. const AVCodecDescriptor *descriptor = avcodec_descriptor_get(codec_params->codec_id); int must_decode = descriptor && !(descriptor->props & AV_CODEC_PROP_INTRA_ONLY); double delay = mlt_properties_get_double(properties, "video_delay"); + int64_t delay64 = (int64_t)(delay * AV_TIME_BASE); // Seek if necessary double speed = mlt_producer_get_speed(producer); @@ -2320,9 +2331,11 @@ static int producer_get_image(mlt_frame frame, pts -= self->first_pts; else if (context->start_time != AV_NOPTS_VALUE) pts -= context->start_time; - int_position = (int64_t) ((av_q2d(self->video_time_base) * pts + delay) - * source_fps - + 0.5); + int_position = av_rescale_q( + av_add_stable(self->video_time_base, pts, AV_TIME_BASE_Q, delay64), + source_fps, + av_inv_q(self->video_time_base) + ); if (int_position == self->last_position) int_position = self->last_position + 1; } @@ -2426,9 +2439,11 @@ static int producer_get_image(mlt_frame frame, pts -= self->first_pts; else if (context->start_time != AV_NOPTS_VALUE) pts -= context->start_time; - int_position = (int64_t) ((av_q2d(self->video_time_base) * pts + delay) - * source_fps - + 0.5); + int_position = av_rescale_q( + av_add_stable(self->video_time_base, pts, AV_TIME_BASE_Q, delay64), + source_fps, + av_inv_q(self->video_time_base) + ); } if (int_position < req_position) From 2fdbf9bdf57bbd49a23093df19460dbf6c2a8d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 4 Jun 2024 19:17:25 +0200 Subject: [PATCH 123/130] producer_avformat: Only bother decoding intra-only packets that we'll need --- src/modules/avformat/producer_avformat.c | 37 +++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 2eb074d84..69b3c2bc9 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2324,6 +2324,8 @@ static int producer_get_image(mlt_frame frame, // We only deal with video from the selected video_index if (self->pkt.stream_index == self->video_index) { int64_t pts = best_pts(self, self->pkt.pts, self->pkt.dts); + // default to decoding all intra-only frames from req_position to the future + int should_decode = int_position >= req_position; if (pts != AV_NOPTS_VALUE) { if (!self->video_seekable && self->first_pts == AV_NOPTS_VALUE) self->first_pts = pts; @@ -2338,6 +2340,39 @@ static int producer_get_image(mlt_frame frame, ); if (int_position == self->last_position) int_position = self->last_position + 1; + + if (self->pkt.duration != AV_NOPTS_VALUE) { + // compute the interval this intra-only packet covers + // [int_position, int_end) + int64_t int_end = av_rescale_q( + av_add_stable(self->video_time_base, pts + self->pkt.duration, AV_TIME_BASE_Q, delay64), + source_fps, + av_inv_q(self->video_time_base) + ); + + /* req_position2 is a "future" req_position computed in a clever way. + * If the input fps is 50 and the output fps is 25, then + * req_position2 relates to int_position and int_end like this: + * + * int_position req_position2 int_end decode? + * 0 0 1 yes + * 1 2 2 no + * 2 2 3 yes + * 3 4 4 no + * 4 4 5 yes + * + * and so on. In other words, for intra-only, only frames where + * int_position <= req_position2 < int_end are worthwhile decoding. + */ + int64_t req_position2 = av_rescale_q( + av_rescale_q_rnd(int_position, profile_fps, source_fps, AV_ROUND_UP), + source_fps, + profile_fps + ); + + // only decode intra-only frames that are worthwhile to decode + should_decode = int_position >= req_position2 && req_position2 < int_end; + } } mlt_log_debug(MLT_PRODUCER_SERVICE(producer), "V pkt.pts %" PRId64 " pkt.dts %" PRId64 " req_pos %" PRId64 @@ -2367,7 +2402,7 @@ static int producer_get_image(mlt_frame frame, self->last_position = int_position; // Decode the image - if (must_decode || int_position >= req_position || !self->pkt.data) { + if (must_decode || should_decode || !self->pkt.data) { #if LIBAVCODEC_VERSION_MAJOR < 61 self->video_codec->reordered_opaque = int_position; #endif From acb4c235b3e5c583e8165484b96a139eabf217bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 4 Jun 2024 19:20:23 +0200 Subject: [PATCH 124/130] producer_avformat: Remove the intra-only seek hack --- src/modules/avformat/producer_avformat.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 2cf7577d7..6d5716116 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -1340,11 +1340,10 @@ static int seek_video(producer_avformat self, int seek_threshold = mlt_properties_get_int(properties, "seek_threshold"); if (seek_threshold <= 0) seek_threshold = 64; - int intra_only = self->video_codec->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY; pthread_mutex_lock(&self->packets_mutex); - if (self->video_seekable && ((position != self->video_expected || self->last_position < 0) || intra_only) ) { + if (self->video_seekable && (position != self->video_expected || self->last_position < 0)) { // Fetch the video format context AVFormatContext *context = self->video_format; @@ -1362,8 +1361,7 @@ static int seek_video(producer_avformat self, paused = 1; } else if (position < self->video_expected || position - self->video_expected >= seek_threshold - || self->last_position < 0 - || intra_only) { + || self->last_position < 0) { // Calculate the timestamp for the requested frame int64_t timestamp = av_rescale_q_rnd( req_position, From 7a6cc5d3d036bc2cc725e3147342c68aa32ad5bb Mon Sep 17 00:00:00 2001 From: Brian Matherly Date: Tue, 4 Jun 2024 21:59:21 -0500 Subject: [PATCH 125/130] Fix double free crash If the caller frees the returned object (which they should), then a double free error will occur because the encapsulated mlt_profile will be freed by the Profile and by the origional service that owned it. --- src/mlt++/MltService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlt++/MltService.cpp b/src/mlt++/MltService.cpp index 113dc9b0a..c8202d8e8 100644 --- a/src/mlt++/MltService.cpp +++ b/src/mlt++/MltService.cpp @@ -117,7 +117,7 @@ Service *Service::consumer() Profile *Service::profile() { - return new Profile(mlt_service_profile(get_service())); + return new Profile(mlt_profile_clone(mlt_service_profile(get_service()))); } mlt_profile Service::get_profile() From 80e634791d4510dd7bb9da7b265095f103b2f542 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Tue, 4 Jun 2024 20:36:01 -0700 Subject: [PATCH 126/130] stop using temporary Mlt::Profile related to #992 --- src/mlt++/MltFilteredProducer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlt++/MltFilteredProducer.cpp b/src/mlt++/MltFilteredProducer.cpp index 34c385d32..228b161b0 100644 --- a/src/mlt++/MltFilteredProducer.cpp +++ b/src/mlt++/MltFilteredProducer.cpp @@ -1,6 +1,6 @@ /** * MltFilteredProducer.cpp - MLT Wrapper - * Copyright (C) 2004-2015 Meltytech, LLC + * Copyright (C) 2004-2024 Meltytech, LLC * Author: Charles Yates * * This library is free software; you can redistribute it and/or @@ -66,8 +66,7 @@ int FilteredProducer::detach(Filter &filter) Service *consumer = it->consumer(); if (consumer->is_valid()) consumer->connect_producer(*producer); - Profile p(get_profile()); - Producer dummy(p, "colour"); + Producer dummy(get_profile(), "colour"); dummy.connect_producer(*it); if (last->get_service() == it->get_service()) { delete last; From fda7c026e959cfe9e549ad229827499cf8912bc7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Wed, 5 Jun 2024 09:15:15 +0200 Subject: [PATCH 127/130] Fix resetting title animation --- src/modules/qt/kdenlivetitle_wrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/qt/kdenlivetitle_wrapper.cpp b/src/modules/qt/kdenlivetitle_wrapper.cpp index c253edadd..de8d35a22 100644 --- a/src/modules/qt/kdenlivetitle_wrapper.cpp +++ b/src/modules/qt/kdenlivetitle_wrapper.cpp @@ -709,8 +709,11 @@ void loadFromXml(producer_ktitle self, // Check if node exists, if it has an x attribute, it is an old version title, don't use viewport if (!n.isNull() && !n.toElement().hasAttribute("x")) { QString rect = n.attributes().namedItem("rect").nodeValue(); - if (startRect != rect) + if (startRect != rect) { mlt_properties_set(producer_props, "_endrect", rect.toUtf8().data()); + } else { + mlt_properties_clear(producer_props, "_endrect"); + } } if (!startRect.isEmpty()) { mlt_properties_set(producer_props, "_startrect", startRect.toUtf8().data()); From 8b860000be90f18d266cb2abe38c126e8a81b0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 11 Jun 2024 12:25:36 +0200 Subject: [PATCH 128/130] producer_avformat: Check audio_index=all and astream=all before using them as ints This fixes #993 --- src/modules/avformat/producer_avformat.c | 31 +++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index d7b169f0b..d3a0c3784 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -3672,8 +3672,24 @@ static int pick_audio_stream(producer_avformat self) { AVFormatContext *context = self->audio_format; mlt_properties properties = MLT_PRODUCER_PROPERTIES(self->parent); - int absolute_index; + int absolute_index = -1; + + // Handle all audio tracks + if (self->audio_index > -1) { + if (mlt_properties_get(properties, "audio_index") + && !strcmp(mlt_properties_get(properties, "audio_index"), "all")) { + absolute_index = INT_MAX; + mlt_properties_set(properties, "astream", "all"); + } + if (mlt_properties_get(properties, "astream") + && !strcmp(mlt_properties_get(properties, "astream"), "all")) { + absolute_index = INT_MAX; + mlt_properties_set(properties, "audio_index", "all"); + } + } + // Are both audio_index != all and astream != all? + if (absolute_index == -1) { if (context && mlt_properties_get(properties, "astream")) { // Get the relative stream index absolute_index = absolute_stream_index(context, @@ -3696,19 +3712,6 @@ static int pick_audio_stream(producer_avformat self) mlt_properties_set_int(properties, "audio_index", absolute_index); self->audio_index = absolute_index; } - - // Handle all audio tracks - if (self->audio_index > -1) { - if (mlt_properties_get(properties, "audio_index") - && !strcmp(mlt_properties_get(properties, "audio_index"), "all")) { - absolute_index = INT_MAX; - mlt_properties_set(properties, "astream", "all"); - } - if (mlt_properties_get(properties, "astream") - && !strcmp(mlt_properties_get(properties, "astream"), "all")) { - absolute_index = INT_MAX; - mlt_properties_set(properties, "audio_index", "all"); - } } // Exception handling for audio_index From 15a46c9ff4e289e3a313b8c1236ef6cdbf09be98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Tue, 11 Jun 2024 12:26:59 +0200 Subject: [PATCH 129/130] producer_avformat: Reindent --- src/modules/avformat/producer_avformat.c | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index d3a0c3784..c60df1a69 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -3690,28 +3690,28 @@ static int pick_audio_stream(producer_avformat self) // Are both audio_index != all and astream != all? if (absolute_index == -1) { - if (context && mlt_properties_get(properties, "astream")) { - // Get the relative stream index - absolute_index = absolute_stream_index(context, - AVMEDIA_TYPE_AUDIO, - mlt_properties_get_int(properties, "astream")); - } else { - // Failover to the absolute index - absolute_index = mlt_properties_get_int(properties, "audio_index"); - if (context) { - // Compute the relative stream index - mlt_properties_set_int(properties, - "astream", - relative_stream_index(context, - AVMEDIA_TYPE_AUDIO, - absolute_index)); + if (context && mlt_properties_get(properties, "astream")) { + // Get the relative stream index + absolute_index = absolute_stream_index(context, + AVMEDIA_TYPE_AUDIO, + mlt_properties_get_int(properties, "astream")); + } else { + // Failover to the absolute index + absolute_index = mlt_properties_get_int(properties, "audio_index"); + if (context) { + // Compute the relative stream index + mlt_properties_set_int(properties, + "astream", + relative_stream_index(context, + AVMEDIA_TYPE_AUDIO, + absolute_index)); + } + } + if (mlt_properties_get_int(properties, "audio_index") != absolute_index) { + // Update the absolute index + mlt_properties_set_int(properties, "audio_index", absolute_index); + self->audio_index = absolute_index; } - } - if (mlt_properties_get_int(properties, "audio_index") != absolute_index) { - // Update the absolute index - mlt_properties_set_int(properties, "audio_index", absolute_index); - self->audio_index = absolute_index; - } } // Exception handling for audio_index From 886cfbc0e958760eeff9d5df59a54d956de80d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Wed, 19 Jun 2024 11:17:47 +0200 Subject: [PATCH 130/130] src/modules/core/transition_mix.c: Increase MAX_CHANNELS to 32 This matches filter_audiomap.c --- src/modules/core/transition_mix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/core/transition_mix.c b/src/modules/core/transition_mix.c index 453257b71..1807701bf 100644 --- a/src/modules/core/transition_mix.c +++ b/src/modules/core/transition_mix.c @@ -26,7 +26,7 @@ #include #include -#define MAX_CHANNELS (6) +#define MAX_CHANNELS (32) #define MAX_SAMPLES (192000) #define SAMPLE_BYTES(samples, channels) ((samples) * (channels) * sizeof(float)) #define MAX_BYTES SAMPLE_BYTES(MAX_SAMPLES, MAX_CHANNELS)