Skip to content

Commit

Permalink
Add support for XML embedded in chains (#1047)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmatherly authored Dec 18, 2024
1 parent bddc2c3 commit 71c4dfd
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 22 deletions.
42 changes: 30 additions & 12 deletions src/framework/mlt_chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* \brief link service class
* \see mlt_chain_s
*
* Copyright (C) 2020-2023 Meltytech, LLC
* Copyright (C) 2020-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
Expand All @@ -26,6 +26,7 @@
#include "mlt_log.h"
#include "mlt_tokeniser.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand All @@ -41,6 +42,7 @@ typedef struct
mlt_profile source_profile;
mlt_properties source_parameters;
mlt_producer begin;
mlt_link frc;
int relink_required;
} mlt_chain_base;

Expand Down Expand Up @@ -398,6 +400,7 @@ void mlt_chain_close(mlt_chain self)
mlt_producer_close(base->source);
mlt_properties_close(base->source_parameters);
mlt_profile_close(base->source_profile);
mlt_link_close(base->frc);
free(base);
self->parent.close = NULL;
mlt_producer_close(&self->parent);
Expand Down Expand Up @@ -515,36 +518,51 @@ static void relink_chain(mlt_chain self)
mlt_chain_base *base = self->local;
mlt_profile profile = mlt_service_profile(MLT_CHAIN_SERVICE(self));
int i = 0;
int frc = 0;
int frc_link = 0;

if (!base->source) {
return;
}

mlt_link_close(base->frc);
base->frc = NULL;

for (i = 0; i < base->link_count; i++) {
if (mlt_properties_get_int(MLT_LINK_PROPERTIES(base->links[i]), "_frc")) {
// A link will perform frame rate conversion.
frc = 1;
frc_link = 1;
break;
}
}

if (frc) {
if (mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(base->source), "static_profile")) {
// The producer does not support changing profile
if (!frc_link) {
// There are no links that can convert frame rate
double chain_fps = mlt_producer_get_fps(MLT_CHAIN_PRODUCER(self));
double source_fps = mlt_producer_get_fps(base->source);
if (fabs(chain_fps - source_fps) > 0.001) {
// The link frame rate does not match the chain frame rate
// A time remap link with no parameters can perform frame rate conversion
base->frc = mlt_factory_link("timeremap", NULL);
}
}
} else if (frc_link && base->source_profile) {
// Set the producer to be in native frame rate
mlt_service_set_profile(MLT_PRODUCER_SERVICE(base->source), base->source_profile);
} else {
// The producer can operate in the final frame rate.
mlt_service_set_profile(MLT_PRODUCER_SERVICE(base->source), profile);
}

if (base->link_count == 0) {
base->begin = base->source;
} else {
base->begin = MLT_LINK_PRODUCER(base->links[base->link_count - 1]);
mlt_link_connect_next(base->links[0], base->source, profile);
for (i = 1; i < base->link_count; i++) {
mlt_link_connect_next(base->links[i], MLT_LINK_PRODUCER(base->links[i - 1]), profile);
}
base->begin = base->source;
if (base->frc) {
mlt_link_connect_next(base->frc, base->begin, profile);
base->begin = MLT_LINK_PRODUCER(base->frc);
}
for (i = 0; i < base->link_count; i++) {
mlt_link_connect_next(base->links[i], base->begin, profile);
base->begin = MLT_LINK_PRODUCER(base->links[i]);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/framework/mlt_factory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* \file mlt_factory.c
* \brief the factory method interfaces
*
* Copyright (C) 2003-2022 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
Expand Down Expand Up @@ -310,7 +310,7 @@ static void set_common_properties(mlt_properties properties,
mlt_properties_set(properties, "mlt_type", type);
if (mlt_properties_get_int(properties, "_mlt_service_hidden") == 0)
mlt_properties_set(properties, "mlt_service", service);
if (profile != NULL)
if (profile != NULL && mlt_properties_get_data(properties, "_profile", NULL) == NULL)
mlt_properties_set_data(properties, "_profile", profile, 0, NULL, NULL);
}

Expand Down
38 changes: 33 additions & 5 deletions src/modules/avformat/link_avdeinterlace.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* link_avdeinterlace.c
* Copyright (C) 2023 Meltytech, LLC
* Copyright (C) 2023-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
Expand Down Expand Up @@ -376,7 +376,11 @@ static int link_get_image(mlt_frame frame,
// Operate on the native image format/size;
srcimg.width = mlt_properties_get_int(unique_properties, "width");
srcimg.height = mlt_properties_get_int(unique_properties, "height");
srcimg.format = mlt_properties_get_int(unique_properties, "format");
if (mlt_properties_exists(unique_properties, "format")) {
srcimg.format = mlt_properties_get_int(unique_properties, "format");
} else {
srcimg.format = *format;
}

// Sanitize the input
if (srcimg.width <= 1 || srcimg.height <= 1) {
Expand Down Expand Up @@ -522,10 +526,34 @@ static int link_get_frame(mlt_link self, mlt_frame_ptr frame, int index)
return error;
}

// Pass original producer dimensions with the frame
mlt_properties unique_properties = mlt_frame_unique_properties(*frame, MLT_LINK_SERVICE(self));
mlt_properties_pass_list(unique_properties,
MLT_PRODUCER_PROPERTIES(original_producer),
"width height format");
mlt_properties original_producer_properties = MLT_PRODUCER_PROPERTIES(original_producer);
if (mlt_properties_exists(original_producer_properties, "width")) {
mlt_properties_set_int(unique_properties,
"width",
mlt_properties_get_int(original_producer_properties, "width"));
} else if (mlt_properties_exists(original_producer_properties, "meta.media.width")) {
mlt_properties_set_int(unique_properties,
"width",
mlt_properties_get_int(original_producer_properties,
"meta.media.width"));
}
if (mlt_properties_exists(original_producer_properties, "height")) {
mlt_properties_set_int(unique_properties,
"height",
mlt_properties_get_int(original_producer_properties, "height"));
} else if (mlt_properties_exists(original_producer_properties, "meta.media.height")) {
mlt_properties_set_int(unique_properties,
"height",
mlt_properties_get_int(original_producer_properties,
"meta.media.height"));
}
if (mlt_properties_exists(original_producer_properties, "format")) {
mlt_properties_set_int(unique_properties,
"format",
mlt_properties_get_int(original_producer_properties, "format"));
}

// Pass future frames
int i = 0;
Expand Down
5 changes: 4 additions & 1 deletion src/modules/avformat/link_swresample.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* link_swresample.c
* 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
Expand Down Expand Up @@ -87,6 +87,9 @@ static int link_get_audio(mlt_frame frame,
// Get the producer's audio
int error
= mlt_frame_get_audio(frame, &in.data, &in.format, &in.frequency, &in.channels, &in.samples);
if (out.format == mlt_audio_none) {
out.format = in.format;
}
if (error || in.format == mlt_audio_none || out.format == mlt_audio_none || in.frequency <= 0
|| out.frequency <= 0 || in.channels <= 0 || out.channels <= 0) {
// Error situation. Do not attempt to convert.
Expand Down
9 changes: 8 additions & 1 deletion src/modules/core/link_timeremap.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* link_timeremap.c
* Copyright (C) 2020-2023 Meltytech, LLC
* Copyright (C) 2020-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
Expand Down Expand Up @@ -127,6 +127,7 @@ static int link_get_audio(mlt_frame frame,
// Validate the request
*channels = *channels <= 0 ? 2 : *channels;
*frequency = *frequency <= 0 ? 48000 : *frequency;
*format = *format == mlt_audio_none ? mlt_audio_float : *format;

if (source_speed < 0.1 || source_speed > 10) {
// Return silent samples for speeds less than 0.1 or > 10
Expand Down Expand Up @@ -224,6 +225,12 @@ static int link_get_audio(mlt_frame frame,
break;
}

if (in.format == mlt_audio_none) {
mlt_log_error(MLT_LINK_SERVICE(self), "Audio none: %d\n", in_frame_pos);
error = 1;
break;
}

int samples_to_copy = in.samples - samples_to_skip;
if (samples_to_copy > samples_needed) {
samples_to_copy = samples_needed;
Expand Down
2 changes: 2 additions & 0 deletions src/modules/xml/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_library(mltxml MODULE
consumer_xml.c
factory.c
producer_xml.c
producer_xml-clip.c
)

file(GLOB YML "*.yml")
Expand All @@ -24,6 +25,7 @@ install(FILES
producer_xml-nogl.yml
producer_xml-string.yml
producer_xml.yml
producer_xml-clip.yml
mlt-xml.dtd
DESTINATION ${MLT_INSTALL_DATA_DIR}/xml
)
8 changes: 7 additions & 1 deletion src/modules/xml/factory.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* factory.c -- the factory method interfaces
* Copyright (C) 2003-2014 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
Expand Down Expand Up @@ -29,6 +29,10 @@ extern mlt_producer producer_xml_init(mlt_profile profile,
mlt_service_type type,
const char *id,
char *arg);
extern mlt_producer producer_xmlclip_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)
{
Expand All @@ -43,6 +47,7 @@ MLT_REPOSITORY
MLT_REGISTER(mlt_service_producer_type, "xml", producer_xml_init);
MLT_REGISTER(mlt_service_producer_type, "xml-string", producer_xml_init);
MLT_REGISTER(mlt_service_producer_type, "xml-nogl", producer_xml_init);
MLT_REGISTER(mlt_service_producer_type, "xml-clip", producer_xmlclip_init);

MLT_REGISTER_METADATA(mlt_service_consumer_type, "xml", metadata, "consumer_xml.yml");
MLT_REGISTER_METADATA(mlt_service_producer_type, "xml", metadata, "producer_xml.yml");
Expand All @@ -51,4 +56,5 @@ MLT_REPOSITORY
metadata,
"producer_xml-string.yml");
MLT_REGISTER_METADATA(mlt_service_producer_type, "xml-nogl", metadata, "producer_xml-nogl.yml");
MLT_REGISTER_METADATA(mlt_service_producer_type, "xml-clip", metadata, "producer_xml-clip.yml");
}
Loading

0 comments on commit 71c4dfd

Please sign in to comment.