Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 65 additions & 55 deletions src/modules/core/producer_colour.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "framework/mlt_image.h"
#include <framework/mlt_frame.h>
#include <framework/mlt_log.h>
#include <framework/mlt_pool.h>
Expand Down Expand Up @@ -124,64 +125,73 @@ static int producer_get_image(mlt_frame frame,

mlt_service_unlock(MLT_PRODUCER_SERVICE(producer));

switch (*format) {
case mlt_image_yuv420p: {
int plane_size = *width * *height;
uint8_t y, u, v;

RGB2YUV_601_SCALED(color.r, color.g, color.b, y, u, v);
memset(p + 0, y, plane_size);
memset(p + plane_size, u, plane_size / 4);
memset(p + plane_size + plane_size / 4, v, plane_size / 4);
mlt_properties_set_int(properties, "colorspace", 601);
break;
}
case mlt_image_yuv422: {
int uneven = *width % 2;
int count = (*width - uneven) / 2 + 1;
uint8_t y, u, v;

RGB2YUV_601_SCALED(color.r, color.g, color.b, y, u, v);
i = *height + 1;
while (--i) {
int j = count;
while (--j) {
*p++ = y;
*p++ = u;
*p++ = y;
*p++ = v;
}
if (uneven) {
*p++ = y;
*p++ = u;
}
if (!strcmp(now, "checkerboard")) {
struct mlt_image_s img;
mlt_image_set_values(&img, NULL, *format, *width, *height);
mlt_image_alloc_data(&img);
mlt_image_fill_checkerboard(&img, 1.0);

memcpy(image, img.data, size);
} else {
switch (*format) {
case mlt_image_yuv420p: {
int plane_size = *width * *height;
uint8_t y, u, v;

RGB2YUV_601_SCALED(color.r, color.g, color.b, y, u, v);
memset(p + 0, y, plane_size);
memset(p + plane_size, u, plane_size / 4);
memset(p + plane_size + plane_size / 4, v, plane_size / 4);
mlt_properties_set_int(properties, "colorspace", 601);
break;
}
mlt_properties_set_int(properties, "colorspace", 601);
break;
}
case mlt_image_rgb:
while (--i) {
*p++ = color.r;
*p++ = color.g;
*p++ = color.b;
case mlt_image_yuv422: {
int uneven = *width % 2;
int count = (*width - uneven) / 2 + 1;
uint8_t y, u, v;

RGB2YUV_601_SCALED(color.r, color.g, color.b, y, u, v);
i = *height + 1;
while (--i) {
int j = count;
while (--j) {
*p++ = y;
*p++ = u;
*p++ = y;
*p++ = v;
}
if (uneven) {
*p++ = y;
*p++ = u;
}
}
mlt_properties_set_int(properties, "colorspace", 601);
break;
}
break;
case mlt_image_movit:
case mlt_image_opengl_texture:
memset(p, 0, size);
break;
case mlt_image_rgba:
while (--i) {
*p++ = color.r;
*p++ = color.g;
*p++ = color.b;
*p++ = color.a;
case mlt_image_rgb:
while (--i) {
*p++ = color.r;
*p++ = color.g;
*p++ = color.b;
}
break;
case mlt_image_movit:
case mlt_image_opengl_texture:
memset(p, 0, size);
break;
case mlt_image_rgba:
while (--i) {
*p++ = color.r;
*p++ = color.g;
*p++ = color.b;
*p++ = color.a;
}
break;
default:
mlt_log_error(MLT_PRODUCER_SERVICE(producer),
"invalid image format %s\n",
mlt_image_format_name(*format));
}
break;
default:
mlt_log_error(MLT_PRODUCER_SERVICE(producer),
"invalid image format %s\n",
mlt_image_format_name(*format));
}
} else {
mlt_service_unlock(MLT_PRODUCER_SERVICE(producer));
Expand Down
1 change: 1 addition & 0 deletions src/modules/qt/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <framework/mlt.h>


class QImage;

bool createQApplicationIfNeeded(mlt_service service);
Expand Down
116 changes: 86 additions & 30 deletions src/modules/qt/filter_qtblend.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* filter_lightshow.cpp -- animate color to the audio
* Copyright (C) 2015 Meltytech, LLC
* filter_qtblend.cpp -- Qt composite filter
* Copyright (C) 2015-2025 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,9 @@
#include <QPainter>
#include <QTransform>

#define MLT_QTBLEND_MAX_DIMENSION (16000)


/** Get the image.
*/
static int filter_get_image(mlt_frame frame,
Expand Down Expand Up @@ -66,19 +69,22 @@ static int filter_get_image(mlt_frame frame,
1.0};
int b_width = mlt_properties_get_int(frame_properties, "meta.media.width");
int b_height = mlt_properties_get_int(frame_properties, "meta.media.height");
bool distort = mlt_properties_get_int(properties, "distort");

if (b_height == 0) {
b_width = normalized_width;
b_height = normalized_height;
}
// Special case - aspect_ratio = 0
if (mlt_frame_get_aspect_ratio(frame) == 0) {
double output_ar = mlt_profile_sar(profile);
mlt_frame_set_aspect_ratio(frame, output_ar);
mlt_frame_set_aspect_ratio(frame, consumer_ar);
}
double b_ar = mlt_frame_get_aspect_ratio(frame);
double b_dar = b_ar * b_width / b_height;
double opacity = 1.0;

// If the _qtblend_scaled property is defined, a qtblend filter was already applied
int qtblendRescaled = mlt_properties_get_int(frame_properties, "qtblend_scaled");
if (mlt_properties_get(properties, "rect")) {
rect = mlt_properties_anim_get_rect(properties, "rect", position, length);
if (::strchr(mlt_properties_get(properties, "rect"), '%')) {
Expand All @@ -87,30 +93,82 @@ static int filter_get_image(mlt_frame frame,
rect.w *= normalized_width;
rect.h *= normalized_height;
}
double scale = mlt_profile_scale_width(profile, *width);
if (scale != 1.0) {
rect.x *= scale;
rect.w *= scale;
}
scale = mlt_profile_scale_height(profile, *height);
if (scale != 1.0) {
rect.y *= scale;
rect.h *= scale;
}
transform.translate(rect.x, rect.y);
opacity = rect.o;
hasAlpha = rect.o < 1 || rect.x != 0 || rect.y != 0 || rect.w != *width
|| rect.h != *height;
if (qtblendRescaled) {
// Another qtblend filter was already applied
// In this case, the *width and *height are set to the source resolution to ensure we don't lose too much details on multiple scaling operations
// We requested a image with full media resolution, adjust rect to profile
// Check if we have consumer scaling enabled since we cannot use *width and *height
double consumerScale = mlt_properties_get_double(frame_properties,
"qtblend_preview_scaling");
if (consumerScale > 0.) {
b_width *= consumerScale;
b_height *= consumerScale;
}

if (mlt_properties_get_int(properties, "distort") == 0) {
b_height = qMax(1, qMin(qRound(rect.h), b_height));
b_width = qMax(1, qRound(b_height * b_dar / b_ar / consumer_ar));
// Always request an image that follows the consumer aspect ratio
double consumer_dar = normalized_width * consumer_ar / normalized_height;
int tmpWidth = b_width;
int tmpHeight = b_height;
double scaleFactor = qMax(*width / rect.w, *height / rect.h);
if (scaleFactor > 1.) {
// Use the highest necessary resolution image
tmpWidth *= scaleFactor;
tmpHeight *= scaleFactor;
}
if (consumer_dar > b_dar) {
*width = qBound(qRound(normalized_width * consumerScale),
tmpWidth,
MLT_QTBLEND_MAX_DIMENSION);
*height = qRound(*width * consumer_ar * normalized_height / normalized_width);
} else {
*height = qBound(qRound(normalized_height * consumerScale),
tmpHeight,
MLT_QTBLEND_MAX_DIMENSION);
*width = qRound(*height * normalized_width / normalized_height / consumer_ar);
}
// Adjust rect to new scaling
double scale = (double) *width / normalized_width;
if (scale != 1.0) {
rect.x *= scale;
rect.w *= scale;
}
scale = (double) *height / normalized_height;
if (scale != 1.0) {
rect.y *= scale;
rect.h *= scale;
}
} else {
b_width = qMax(1, qRound(b_width * b_ar / consumer_ar));
}
if (!hasAlpha && (b_width < *width || b_height < *height)) {
hasAlpha = true;
// First instance of a qtblend filter
double scale = mlt_profile_scale_width(profile, *width);
// Store consumer scaling for further uses
mlt_properties_set_int(frame_properties, "qtblend_scaled", 1);
mlt_properties_set_double(frame_properties, "qtblend_preview_scaling", scale);
// Apply scaling
if (scale != 1.0) {
rect.x *= scale;
rect.w *= scale;
if (distort) {
b_width *= scale;
} else {
// Apply consumer scaling to the source image request
b_width *= scale;
b_height *= scale;
}
}
scale = mlt_profile_scale_height(profile, *height);
if (scale != 1.0) {
rect.y *= scale;
rect.h *= scale;
if (distort) {
b_height *= scale;
}
}
}
transform.translate(rect.x, rect.y);
opacity = rect.o;
hasAlpha = rect.o < 1 || rect.x != 0 || rect.y != 0 || rect.w != *width || rect.h != *height
|| rect.w / b_dar < *height || rect.h * b_dar < *width || b_width < *width
|| b_height < *height;
} else {
b_width = *width;
b_height = *height;
Expand Down Expand Up @@ -154,7 +212,6 @@ static int filter_get_image(mlt_frame frame,
// fetch image
*format = mlt_image_rgba;
uint8_t *src_image = NULL;

error = mlt_frame_get_image(frame, &src_image, format, &b_width, &b_height, 0);

// Put source buffer into QImage
Expand All @@ -164,13 +221,12 @@ static int filter_get_image(mlt_frame frame,
int image_size = mlt_image_format_size(*format, *width, *height, NULL);

// resize to rect
if (mlt_properties_get_int(properties, "distort")) {
if (distort) {
transform.scale(rect.w / b_width, rect.h / b_height);
} else {
// Determine scale with respect to aspect ratio.
double geometry_dar = rect.w * consumer_ar / rect.h;
double scale;
if (b_dar > geometry_dar) {
double resize_dar = rect.w * consumer_ar / rect.h;
if (b_dar >= resize_dar) {
scale = rect.w / b_width;
} else {
scale = rect.h / b_height * b_ar;
Expand Down
Loading