Skip to content

Commit

Permalink
Add video fade to auto fade filter
Browse files Browse the repository at this point in the history
  • Loading branch information
bmatherly committed Oct 29, 2023
1 parent 6f331b4 commit 39212fb
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 8 deletions.
92 changes: 84 additions & 8 deletions src/modules/core/filter_autofade.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ static int filter_get_audio(mlt_frame frame,
data++;
}
}
mlt_properties_set_int(filter_properties,
"fade_in_count",
mlt_properties_get_int(filter_properties, "fade_in_count") + 1);
} else if ((samples_to_clip_end - *samples) <= fade_samples) {
// Fade out
for (int i = 0; i < audio.samples; i++) {
Expand All @@ -86,28 +83,102 @@ static int filter_get_audio(mlt_frame frame,
data++;
}
}
mlt_properties_set_int(filter_properties,
"fade_out_count",
mlt_properties_get_int(filter_properties, "fade_out_count") + 1);
}

return 0;
}

static int filter_get_image(mlt_frame frame,
uint8_t **image,
mlt_image_format *format,
int *width,
int *height,
int writable)
{
int error = 0;
mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);

// Get the current image
*format = mlt_image_rgba;
error = mlt_frame_get_image(frame, image, format, width, height, 1);

if (error)
return error;

mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
int clip_position = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame),
"meta.playlist.clip_position");
int clip_length = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame),
"meta.playlist.clip_length");
double fade_duration = mlt_properties_get_int(filter_properties, "fade_duration");
double fps = mlt_profile_fps(mlt_service_profile(MLT_FILTER_SERVICE(filter)));
int fade_duration_frames = lrint(fade_duration * fps / 1000.0);
float image_factor = 1.0;
int frames_from_begining = clip_position + 1;
int frames_to_end = clip_length - clip_position - 1;

if (frames_from_begining <= fade_duration_frames) {
// Fade In
image_factor = decay_factor(clip_position, fade_duration_frames);
} else if (frames_to_end <= fade_duration_frames) {
// Fade Out
image_factor = decay_factor(frames_to_end, fade_duration_frames);
}

if (image_factor < 1.0) {
mlt_color color = mlt_properties_get_color(filter_properties, "fade_color");
float color_factor = 1.0 - image_factor;
float r_value = color.r * color_factor;
float g_value = color.g * color_factor;
float b_value = color.b * color_factor;
float a_value = color.a * color_factor;
uint8_t *p = *image;
int pixels = *width * *height;
for (int i = 0; i < pixels; i++) {
p[0] = ((float) p[0] * image_factor) + r_value;
p[1] = ((float) p[1] * image_factor) + g_value;
p[2] = ((float) p[2] * image_factor) + b_value;
p[3] = ((float) p[3] * image_factor) + a_value;
p += 4;
}
}

return error;
}

static mlt_frame filter_process(mlt_filter filter, mlt_frame frame)
{
mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
int clip_position = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame),
"meta.playlist.clip_position");
int clip_length = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame),
"meta.playlist.clip_length");
int fade_duration = mlt_properties_get_int(MLT_FILTER_PROPERTIES(filter), "fade_duration");
int fade_duration = mlt_properties_get_int(filter_properties, "fade_duration");
double fps = mlt_profile_fps(mlt_service_profile(MLT_FILTER_SERVICE(filter)));
int ms_from_begining = (double) clip_position * 1000.0 / fps;
int ms_from_end = (double) (clip_length - clip_position - 1) * 1000.0 / fps;
if (ms_from_begining <= fade_duration || ms_from_end <= fade_duration) {
int fade = 0;

if (ms_from_begining <= fade_duration) {
fade = 1;
mlt_properties_set_int(filter_properties,
"fade_in_count",
mlt_properties_get_int(filter_properties, "fade_in_count") + 1);
} else if (ms_from_end <= fade_duration) {
fade = 1;
mlt_properties_set_int(filter_properties,
"fade_out_count",
mlt_properties_get_int(filter_properties, "fade_out_count") + 1);
}

if (fade && mlt_properties_get_int(filter_properties, "fade_audio")) {
mlt_frame_push_audio(frame, filter);
mlt_frame_push_audio(frame, filter_get_audio);
}
if (fade && mlt_properties_get_int(filter_properties, "fade_video")) {
mlt_frame_push_get_image(frame, (void *) filter);
mlt_frame_push_get_image(frame, filter_get_image);
}
return frame;
}

Expand All @@ -129,6 +200,11 @@ mlt_filter filter_autofade_init(mlt_profile profile,
if (filter) {
filter->close = filter_close;
filter->process = filter_process;
mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
mlt_properties_set_int(filter_properties, "fade_duration", 20);
mlt_properties_set_int(filter_properties, "fade_audio", 1);
mlt_properties_set_int(filter_properties, "fade_video", 0);
mlt_properties_set_string(filter_properties, "fade_color", "0x000000ff");
}

return filter;
Expand Down
26 changes: 26 additions & 0 deletions src/modules/core/filter_autofade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ parameters:
maximum: 1000
unit: ms

- identifier: fade_video
title: Fade Video
type: boolean
description: Fade the video to/from the fade color
mutable: yes
default: 0

- identifier: fade_audio
title: Fade Audio
type: boolean
description: Fade the audio to/from silence
mutable: yes
default: 1

- identifier: fade_color
title: Fade color
type: color
description: >
The color to fade to.
A color value is a hexadecimal representation of RGB plus alpha channel
as 0xrrggbbaa. Colors can also be the words: white, black, red, green,
or blue. You can also use a HTML-style color values #rrggbb or #aarrggbb
default: 0x000000ff
mutable: yes
widget: color

- identifier: fade_in_count
title: Fade In Count
type: integer
Expand Down

0 comments on commit 39212fb

Please sign in to comment.