return get_current_job()->edl_path;
}
+int BatchRenderThread::test_errmsg(BatchRenderWarnJobs &err_jobs, const char *msg, int *warn)
+{
+ int count = err_jobs.size();
+ if( !count ) return 0;
+ fprintf(stderr, msg, count);
+ char string[BCTEXTLEN], *sp = string, *ep = sp+sizeof(string)-1;
+ sp += snprintf(sp,ep-sp, msg,count);
+ for( int i=0; i<count; ++i ) {
+ int no = err_jobs[i].no;
+ const char *path = err_jobs[i].path;
+ fprintf(stderr, "%d: %s\n", no, path);
+ sp += snprintf(sp,ep-sp, "%d: %s\n", no, path);
+ }
+ sp += snprintf(sp,ep-sp, _("press cancel to abandon batch render"));
+ mwindow->show_warning(warn, string);
+ if( mwindow->wait_warning() ) {
+ gui->button_enable();
+ }
+ return 1;
+}
// Test EDL files for existence
int BatchRenderThread::test_edl_files()
const char *path = 0;
BatchRenderWarnJobs not_equiv;
BatchRenderWarnJobs empty_jobs;
+ BatchRenderWarnJobs no_labels;
+ BatchRenderWarnJobs no_rendering;
for( int i=0; !ret && i<jobs.size(); ++i ) {
if( !jobs.values[i]->enabled ) continue;
- path = jobs.values[i]->edl_path;
+ path = jobs[i]->edl_path;
int is_script = *path == '@' ? 1 : 0;
if( is_script ) ++path;
FILE *fp = fopen(path, "r");
file.set_shared_input(&data);
edl->load_xml(&file, LOAD_ALL); }
double pos = edl->equivalent_output(mwindow->edl);
- if( pos >= 0 ) not_equiv.add(i+1, path);
+ if( pos >= 0 )
+ not_equiv.add(i+1, path);
double length = edl->tracks->total_playable_length();
double start = edl->local_session->get_selectionstart(1);
- if( start >= length ) empty_jobs.add(i+1, path);
+ if( start >= length )
+ empty_jobs.add(i+1, path);
+ if( jobs[i]->labeled && !edl->labels->first)
+ no_labels.add(i+1,path);
+ Asset *asset = jobs[i]->asset;
+ if( !asset->audio_data && !asset->video_data )
+ no_rendering.add(i+1,path);
edl->remove_user();
}
delete [] bfr;
fprintf(stderr, "%s", string);
}
is_rendering = 0;
+ ret = 1;
}
- int mismatched = not_equiv.size();
- if( is_rendering && warn && mwindow && mismatched > 0 ) {
- fprintf(stderr, _("%d job EDLs do not match session edl\n"), mismatched);
- char string[BCTEXTLEN], *sp = string, *ep = sp+sizeof(string)-1;
- sp += snprintf(sp,ep-sp, _("%d job EDLs do not match session edl\n"),mismatched);
- for( int i=0; i<mismatched; ++i ) {
- int no = not_equiv[i].no; const char *path = not_equiv[i].path;
- fprintf(stderr, "%d: %s\n", no, path);
- sp += snprintf(sp,ep-sp, "%d: %s\n", no, path);
- }
- sp += snprintf(sp,ep-sp, _("press cancel to abandon batch render"));
- mwindow->show_warning(&warn, string);
- if( mwindow->wait_warning() ) {
- gui->button_enable();
- is_rendering = 0;
- ret = 1;
- }
- gui->warning->update(warn);
+ if( !ret && warn && mwindow ) {
+ ret = test_errmsg(not_equiv, _("%d job EDLs do not match session edl\n"), &warn);
+ if( !warn ) gui->warning->update(0);
}
-
- int empty = empty_jobs.size();
- if( is_rendering && empty > 0 ) {
- fprintf(stderr, _("%d job EDLs begin position beyond end of media\n"), empty);
- char string[BCTEXTLEN], *sp = string, *ep = sp+sizeof(string)-1;
- sp += snprintf(sp,ep-sp, _("%d job EDLs begin position beyond end of media\n"), empty);
- for( int i=0; i<empty; ++i ) {
- int no = empty_jobs[i].no; const char *path = empty_jobs[i].path;
- fprintf(stderr, "%d: %s\n", no, path);
- sp += snprintf(sp,ep-sp, "%d: %s\n", no, path);
- }
- sp += snprintf(sp,ep-sp, _("press cancel to abandon batch render"));
- mwindow->show_warning(0, string);
- if( mwindow->wait_warning() ) {
- gui->button_enable();
- is_rendering = 0;
- ret = 1;
- }
- }
-
+ if( !ret && mwindow )
+ ret = test_errmsg(empty_jobs, _("%d job EDLs begin position beyond end of media\n"), 0);
+ if( !ret && mwindow )
+ ret = test_errmsg(no_rendering, _("%d job EDLs no audio or video in render asset format\n"), 0);
+ if( !ret && mwindow )
+ ret = test_errmsg(no_labels, _("%d job EDLs render file per label and no labels\n"), 0);
+ if( ret )
+ is_rendering = 0;
return ret;
}
command->playback_range_adjust_inout();
// Create test packages
- packages->create_packages(mwindow, command->get_edl(),
+ int result = packages->create_packages(mwindow, command->get_edl(),
preferences, job->get_strategy(), job->asset,
command->start_position, command->end_position, 0);
+ if( !result )
+ packages->get_package_paths(paths);
// Append output paths allocated to total
- packages->get_package_paths(paths);
// Delete package harness
delete packages;
BC_Window* new_gui();
int test_edl_files();
+ int test_errmsg(BatchRenderWarnJobs &err_jobs, const char *msg, int *warn);
void calculate_dest_paths(ArrayList<char*> *paths,
Preferences *preferences);
void reset(const char *path=0);
#include "edl.h"
#include "edlsession.h"
#include "labels.h"
+#include "mainerror.h"
#include "mutex.h"
#include "mwindow.h"
#include "packagedispatcher.h"
label = edl->labels->first;
total_packages = 0;
packages = new RenderPackage*[edl->labels->total() + 2];
+ if( !label ) {
+ eprintf(_("Render file per label and no labels\n"));
+ result = 1;
+ break;
+ }
Render::get_starting_number(default_asset->path,
current_number, number_start, total_digits, 3);
packaging_engine->get_package_paths(path_list);
else {
for( int i=0; i<total_allocated; ++i )
- path_list->append(strdup(packages[i]->path));
- path_list->set_free();
+ path_list->append(cstrdup(packages[i]->path));
}
}
#include "language.h"
#include "loadmode.h"
#include "localsession.h"
+#include "mainerror.h"
#include "mainprogress.h"
#include "mainsession.h"
#include "mainundo.h"
err_msg = _("zero render range");
result = 1;
}
+ if( !result && !asset->audio_data && !asset->video_data ) {
+ err_msg = _("no audio or video in render asset format\n");
+ result = 1;
+ }
+ EDL *edl = mwindow->edl;
+ if( !result && use_labels && !edl->labels->first ) {
+ eprintf(_("render file per label and no labels\n"));
+ result = 1;
+ }
if( !result && asset->video_data ) {
- double frame_rate = mwindow->edl->session->frame_rate;
+ double frame_rate = edl->session->frame_rate;
if( frame_rate > 0 && render_range+1e-3 < 1./frame_rate ) {
err_msg = _("Video data and range less than 1 frame");
result = 1;
}
}
if( !result && asset->audio_data ) {
- double sample_rate = mwindow->edl->session->sample_rate;
+ double sample_rate = edl->session->sample_rate;
if( sample_rate > 0 && render_range+1e-6 < 1./sample_rate ) {
err_msg = _("Audio data and range less than 1 sample");
result = 1;
}
if( !result && File::is_image_render(asset->format) ) {
if( asset->video_data ) {
- double frames = render_range * mwindow->edl->session->frame_rate;
+ double frames = render_range * edl->session->frame_rate;
if( !EQUIV(frames, 1.) ) {
err_msg = _("Image format and not 1 frame");
result = 1;
result = 1;
}
}
+
if( err_msg ) {
int cx, cy;
mwindow->gui->get_abs_cursor(cx, cy, 1);
render->result = 1;
}
}
+
render_frames = render->default_asset->frame_rate * total_length;
// Generate packages
{
int x = 10, y = 10;
lock_window("RenderWindow::create_objects");
- add_subwindow(new BC_Title(x, y,
- (char*)(render->use_labels ?
+ add_subwindow(file_format = new BC_Title(x, y,
+ (render->use_labels ?
_("Select the first file to render to:") :
_("Select a file to render to:"))));
y += 25;
FormatTools::update_format();
RenderWindow *render_window = (RenderWindow *)window;
if( render_window->is_hidden() ) return;
-
int is_image = File::is_image_render(asset->format);
if( is_image ) {
render_window->update_range_type(RANGE_1FRAME);
else
render_window->enable_render_range(1);
}
+int RenderFormat::handle_event()
+{
+ RenderWindow *render_window = (RenderWindow *)window;
+ render_window->file_format->update(
+ (render_window->render->use_labels ?
+ _("Select the first file to render to:") :
+ _("Select a file to render to:")));
+ return 1;
+}
RenderBeepOnDone::RenderBeepOnDone(RenderWindow *rwindow, int x, int y)
: BC_CheckBox(x, y, rwindow->render->beep, _("Beep on done"))
RenderFormat(MWindow *mwindow, BC_WindowBase *window, Asset *asset);
~RenderFormat();
void update_format();
+ int handle_event();
};
RenderProfile *renderprofile;
LoadMode *loadmode;
+ BC_Title *file_format;
RenderFormat *render_format;
MWindow *mwindow;
}
}
+ int64_t track_x, track_y, track_w, track_h;
+ track_dimensions(current,
+ track_x, track_y, track_w, track_h);
+ set_color((~get_resources()->get_bg_color()) & 0xffffff);
+ set_opaque();
+ int x1 = track_x, x2 = x1+track_w;
+ int y1 = track_y+track_h-1;
+ draw_line(x1,y1, x2,y1, background_pixmap);
}
#define CINELERRA_VERSION "Infinity"
#define REPOMAINTXT "git://git.cinelerra-gg.org/goodguy/cinelerra.git\n"
-#define COPYRIGHT_DATE "2018"
-#define COPYRIGHTTEXT1 "(c) 2006-2018 Heroine Virtual Ltd. by Adam Williams\n"
-#define COPYRIGHTTEXT2 "(c) 2007-2018 cin5 derivative by W.P. Morrow aka goodguy\n"
+#define COPYRIGHT_DATE "2019"
+#define COPYRIGHTTEXT1 "(c) 2006-2019 Heroine Virtual Ltd. by Adam Williams\n"
+#define COPYRIGHTTEXT2 "(c) 2007-2019 cin5 derivative by W.P. Morrow aka goodguy\n"
#undef COMPILEDATE
#endif
rm -f conftest.asm conftest.o
REQUIRE_PROG(YASM, [yasm])
fi
+if test "x$X86" = "x0" ; then
+ # incompatible instruction set
+ PKG_dav1d=no
+fi
+
## end arch dep tests
REQUIRE_PROG(OBJCOPY, [objcopy])
F_lumakey
- Geometry
Auto Scale
+ Crop & Position
Flip
Lens
Perspective
https://sami.boukortt.com/plugins/intersect#Intersect
https://sami.boukortt.com/plugins/intersect#SymmetricDifference
https://sami.boukortt.com/plugins/intersect#Upmix
+http://drumkv1.sourceforge.net/lv2
+http://rakarrack.sourceforge.net/effects.html#awha
#
# Rakarrack takes special handling to get these lv2 plugins to work;
# the library needs to be linked using -Bsymbolic-functions ;
Cakewalk and Neophyte themes by Olaf Wolff (CC BY 4.0,
https://creativecommons.org/licenses/by/4.0/)
.
+August 2019 New Features of note:
+ FFmpeg in use with Cinelerra is now version 4.2.
+ Lipvpx has been upgraded to version 1.8.1.
+ Dav1d is now the default/faster decoder for AV1 media.
+ Performance improvements were added for Mask feathering.
July 2019 New Features of note:
Completion of Masking improvements with Preset Shapes, Center
and Normalize buttons, plus x/y scaling in 1 direction only.
colorbalance \
compressor \
crikey \
+ crop \
crossfade \
dcoffset \
decimate \
--- /dev/null
+include ../../plugin_defs
+
+OBJS = $(OBJDIR)/crop.o \
+ $(OBJDIR)/cropwin.o
+
+PLUGIN = crop
+
+include ../../plugin_config
+
+$(OBJDIR)/crop.o: crop.C
+$(OBJDIR)/cropwin.o: cropwin.C
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * 2019. Derivative by Translate plugin. This plugin works also with Proxy.
+ * It uses Percent values instead of Pixel value coordinates.
+*/
+
+#include "clip.h"
+#include "filexml.h"
+#include "language.h"
+#include "crop.h"
+#include "cropwin.h"
+
+#include <string.h>
+
+
+
+
+REGISTER_PLUGIN(CropMain)
+
+CropConfig::CropConfig()
+{
+ reset(RESET_DEFAULT_SETTINGS);
+}
+
+void CropConfig::reset(int clear)
+{
+ switch(clear) {
+ case RESET_LEFT :
+ crop_l = 0.0;
+ break;
+ case RESET_TOP :
+ crop_t = 0.0;
+ break;
+ case RESET_RIGHT :
+ crop_r = 0.0;
+ break;
+ case RESET_BOTTOM :
+ crop_b = 0.0;
+ break;
+ case RESET_POSITION_X :
+ position_x = 0.0;
+ break;
+ case RESET_POSITION_Y :
+ position_y = 0.0;
+ break;
+ case RESET_ALL :
+ case RESET_DEFAULT_SETTINGS :
+ default:
+ crop_l = 0.0;
+ crop_t = 0.0;
+ crop_r = 0.0;
+ crop_b = 0.0;
+
+ position_x = 0.0;
+ position_y = 0.0;
+ break;
+ }
+}
+
+
+int CropConfig::equivalent(CropConfig &that)
+{
+ return EQUIV(crop_l, that.crop_l) &&
+ EQUIV(crop_t, that.crop_t) &&
+ EQUIV(crop_r, that.crop_r) &&
+ EQUIV(crop_b, that.crop_b) &&
+ EQUIV(position_x, that.position_x) &&
+ EQUIV(position_y, that.position_y);
+}
+
+void CropConfig::copy_from(CropConfig &that)
+{
+ crop_l = that.crop_l;
+ crop_t = that.crop_t;
+ crop_r = that.crop_r;
+ crop_b = that.crop_b;
+ position_x = that.position_x;
+ position_y = that.position_y;
+}
+
+void CropConfig::interpolate(CropConfig &prev,
+ CropConfig &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame)
+{
+ double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+ double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+
+ this->crop_l = prev.crop_l * prev_scale + next.crop_l * next_scale;
+ this->crop_t = prev.crop_t * prev_scale + next.crop_t * next_scale;
+ this->crop_r = prev.crop_r * prev_scale + next.crop_r * next_scale;
+ this->crop_b = prev.crop_b * prev_scale + next.crop_b * next_scale;
+ this->position_x = prev.position_x * prev_scale + next.position_x * next_scale;
+ this->position_y = prev.position_y * prev_scale + next.position_y * next_scale;
+}
+
+
+
+
+
+
+
+
+CropMain::CropMain(PluginServer *server)
+ : PluginVClient(server)
+{
+ temp_frame = 0;
+ overlayer = 0;
+
+}
+
+CropMain::~CropMain()
+{
+
+
+ if(temp_frame) delete temp_frame;
+ temp_frame = 0;
+ if(overlayer) delete overlayer;
+ overlayer = 0;
+}
+
+const char* CropMain::plugin_title() { return N_("Crop & Position"); }
+int CropMain::is_realtime() { return 1; }
+
+
+
+LOAD_CONFIGURATION_MACRO(CropMain, CropConfig)
+
+void CropMain::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+
+// cause data to be stored directly in text
+ output.set_shared_output(keyframe->xbuf);
+
+// Store data
+ output.tag.set_title("CROP");
+ output.tag.set_property("LEFT", config.crop_l);
+ output.tag.set_property("TOP", config.crop_t);
+ output.tag.set_property("RIGHT", config.crop_r);
+ output.tag.set_property("BOTTOM", config.crop_b);
+ output.tag.set_property("POSITION_X", config.position_x);
+ output.tag.set_property("POSITION_Y", config.position_y);
+ output.append_tag();
+ output.tag.set_title("/CROP");
+ output.append_tag();
+ output.append_newline();
+ output.terminate_string();
+// data is now in *text
+}
+
+void CropMain::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+
+ input.set_shared_input(keyframe->xbuf);
+
+ int result = 0;
+
+ while(!result)
+ {
+ result = input.read_tag();
+
+ if(!result)
+ {
+ if(input.tag.title_is("CROP"))
+ {
+ config.crop_l = input.tag.get_property("LEFT", config.crop_l);
+ config.crop_t = input.tag.get_property("TOP", config.crop_t);
+ config.crop_r = input.tag.get_property("RIGHT", config.crop_r);
+ config.crop_b = input.tag.get_property("BOTTOM", config.crop_b);
+ config.position_x = input.tag.get_property("POSITION_X", config.position_x);
+ config.position_y = input.tag.get_property("POSITION_Y", config.position_y);
+ }
+ }
+ }
+}
+
+
+#define EPSILON 0.001
+
+int CropMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
+{
+ VFrame *input = input_ptr;
+ VFrame *output = output_ptr;
+
+ load_configuration();
+
+//printf("CropMain::process_realtime 1 %p\n", input);
+ if( input->get_rows()[0] == output->get_rows()[0] ) {
+ if( temp_frame && (
+ temp_frame->get_w() != input_ptr->get_w() ||
+ temp_frame->get_h() != input_ptr->get_h() ||
+ temp_frame->get_color_model() != input_ptr->get_color_model() ) ) {
+ delete temp_frame;
+ temp_frame = 0;
+ }
+ if(!temp_frame)
+ temp_frame = new VFrame(input_ptr->get_w(), input_ptr->get_h(),
+ input->get_color_model(), 0);
+ temp_frame->copy_from(input);
+ input = temp_frame;
+ }
+//printf("CropMain::process_realtime 2 %p\n", input);
+
+
+ if(!overlayer)
+ {
+ overlayer = new OverlayFrame(smp + 1);
+ }
+
+ output->clear_frame();
+
+/* OLD code by "Translate" plugin
+ if( config.in_w < EPSILON ) return 1;
+ if( config.in_h < EPSILON ) return 1;
+ if( config.out_w < EPSILON ) return 1;
+ if( config.out_h < EPSILON ) return 1;
+*/
+
+
+/*
+ *** Little description of the points ***
+ Points (ix1, iy1) and (ix2, iy2) are the Camera coordinates:
+ (ix1, iy1) is the point on top-left,
+ (ix2, iy2) is the point on bottom-right.
+ Points (ox1, oy1) and (ox2, oy2) are the Projector coordinates:
+ (ox1, oy1) is the point on top-left,
+ (ox2, oy2) is the point on bottom-right.
+*/
+
+// Convert from Percent to Pixel coordinate (Percent value in plugin GUI)
+// so it works also for Proxy
+ float ix1 = config.crop_l / 100 * output->get_w();
+ float ox1 = ix1;
+ ox1 += config.position_x / 100 * output->get_w();
+ float ix2 = ((100.00 - config.crop_r) / 100) * output->get_w();
+
+ if( ix1 < 0 ) {
+ ox1 -= ix1;
+ ix1 = 0;
+ }
+
+ if(ix2 > output->get_w())
+ ix2 = output->get_w();
+
+// Convert from Percent to Pixel coordinate (Percent value in plugin GUI)
+// so it works also for Proxy
+ float iy1 = config.crop_t / 100 * output->get_h();
+ float oy1 = iy1;
+ oy1 += config.position_y / 100 * output->get_h();
+ float iy2 = ((100.00 - config.crop_b) / 100) * output->get_h();
+
+ if( iy1 < 0 ) {
+ oy1 -= iy1;
+ iy1 = 0;
+ }
+
+ if( iy2 > output->get_h() )
+ iy2 = output->get_h();
+
+// Scale features: OLD code by "Translate" plugin.
+// (I leave here for future development)
+// Scale_: scale_x=scale_y=1. It means NO SCALE.
+ float cx = 1.00;
+ float cy = cx;
+
+ float ox2 = ox1 + (ix2 - ix1) * cx;
+ float oy2 = oy1 + (iy2 - iy1) * cy;
+
+ if( ox1 < 0 ) {
+ ix1 += -ox1 / cx;
+ ox1 = 0;
+ }
+ if( oy1 < 0 ) {
+ iy1 += -oy1 / cy;
+ oy1 = 0;
+ }
+ if( ox2 > output->get_w() ) {
+ ix2 -= (ox2 - output->get_w()) / cx;
+ ox2 = output->get_w();
+ }
+ if( oy2 > output->get_h() ) {
+ iy2 -= (oy2 - output->get_h()) / cy;
+ oy2 = output->get_h();
+ }
+
+ if( ix1 >= ix2 ) return 1;
+ if( iy1 >= iy2 ) return 1;
+ if( ox1 >= ox2 ) return 1;
+ if( oy1 >= oy2 ) return 1;
+
+ overlayer->overlay(output, input,
+ ix1, iy1, ix2, iy2,
+ ox1, oy1, ox2, oy2,
+ 1, TRANSFER_REPLACE,
+ get_interpolation_type());
+ return 0;
+}
+
+NEW_WINDOW_MACRO(CropMain, CropWin)
+
+void CropMain::update_gui()
+{
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+
+ CropWin *window = (CropWin*)thread->window;
+ window->lock_window();
+/*
+ window->crop_l->update(config.crop_l);
+ window->crop_t->update(config.crop_t);
+ window->crop_r->update(config.crop_r);
+ window->crop_b->update(config.crop_b);
+ window->position_x->update(config.position_x);
+ window->position_y->update(config.position_y);
+*/
+ window->update(RESET_ALL);
+
+ window->unlock_window();
+}
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * 2019. Derivative by Translate plugin. This plugin works also with Proxy.
+ * It uses Percent values instead of Pixel value coordinates.
+*/
+
+#ifndef CROP_H
+#define CROP_H
+
+// the simplest plugin possible
+
+class CropMain;
+
+#include "bchash.h"
+#include "mutex.h"
+#include "cropwin.h"
+#include "overlayframe.h"
+#include "pluginvclient.h"
+
+class CropConfig
+{
+public:
+ CropConfig();
+ void reset(int clear);
+ int equivalent(CropConfig &that);
+ void copy_from(CropConfig &that);
+ void interpolate(CropConfig &prev,
+ CropConfig &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame);
+
+ float crop_l, crop_t, crop_r, crop_b;
+ float position_x, position_y;
+};
+
+
+class CropMain : public PluginVClient
+{
+public:
+ CropMain(PluginServer *server);
+ ~CropMain();
+
+// required for all realtime plugins
+ PLUGIN_CLASS_MEMBERS(CropConfig)
+ int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
+ int is_realtime();
+ void update_gui();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+
+
+ OverlayFrame *overlayer; // To translate images
+ VFrame *temp_frame;
+};
+
+
+#endif
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * 2019. Derivative by Translate plugin. This plugin works also with Proxy.
+ * It uses Percent values instead of Pixel value coordinates.
+*/
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "language.h"
+#include "theme.h"
+#include "crop.h"
+#include "cropwin.h"
+
+
+
+
+
+
+
+
+
+
+
+
+CropWin::CropWin(CropMain *client)
+ : PluginClientWindow(client,
+ 420,
+ 290,
+ 420,
+ 290,
+ 0)
+{
+ this->client = client;
+}
+
+CropWin::~CropWin()
+{
+}
+
+void CropWin::create_objects()
+{
+ int x = 10, x1 = 40, x2 = 80, x_middle= (get_w() / 2), x3 = 180;
+ int y = 10;
+ int clr_x = get_w()-x - 22; // note: clrBtn_w = 22
+
+ BC_TitleBar *title_bar;
+ BC_Bar *bar;
+
+// Crop section
+ add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Crop")));
+ y += 20;
+ add_tool(new BC_Title(x, y, _("Left")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_left_text = new CropLeftText(this, client, (x + x2), y);
+ crop_left_text->create_objects();
+ crop_left_slider = new CropLeftSlider(this, client, x3, y, 200);
+ add_subwindow(crop_left_slider);
+ clr_x = x3 + crop_left_slider->get_w() + x;
+ add_subwindow(crop_left_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_LEFT));
+ y += 30;
+ add_tool(new BC_Title(x, y, _("Top")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_top_text = new CropTopText(this, client, (x + x2), y);
+ crop_top_text->create_objects();
+ crop_top_slider = new CropTopSlider(this, client, x3, y, 200);
+ add_subwindow(crop_top_slider);
+ add_subwindow(crop_top_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_TOP));
+ y += 30;
+ add_tool(new BC_Title(x, y, _("Right")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_right_text = new CropRightText(this, client, (x + x2), y);
+ crop_right_text->create_objects();
+ crop_right_slider = new CropRightSlider(this, client, x3, y, 200);
+ add_subwindow(crop_right_slider);
+ add_subwindow(crop_right_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_RIGHT));
+ y += 30;
+ add_tool(new BC_Title(x, y, _("Bottom")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_bottom_text = new CropBottomText(this, client, (x + x2), y);
+ crop_bottom_text->create_objects();
+ crop_bottom_slider = new CropBottomSlider(this, client, x3, y, 200);
+ add_subwindow(crop_bottom_slider);
+ add_subwindow(crop_bottom_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_BOTTOM));
+ y += 40;
+
+// Position section
+ add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Position")));
+ y += 20;
+ add_tool(new BC_Title(x, y, _("X")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_position_x_text = new CropPositionXText(this, client, (x + x2), y);
+ crop_position_x_text->create_objects();
+ crop_position_x_slider = new CropPositionXSlider(this, client, x3, y, 200);
+ add_subwindow(crop_position_x_slider);
+ add_subwindow(crop_position_x_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_POSITION_X));
+ y += 30;
+ add_tool(new BC_Title(x, y, _("Y")));
+ add_tool(new BC_Title((x2-x), y, _("%")));
+ crop_position_y_text = new CropPositionYText(this, client, (x + x2), y);
+ crop_position_y_text->create_objects();
+ crop_position_y_slider = new CropPositionYSlider(this, client, x3, y, 200);
+ add_subwindow(crop_position_y_slider);
+ add_subwindow(crop_position_y_clr = new CropEdgesClr(this, client,
+ clr_x, y, RESET_POSITION_Y));
+ y += 40;
+
+// Reset section
+ add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
+ y += 10;
+ add_tool(reset = new CropReset(client, this, x, y));
+
+ show_window();
+ flush();
+}
+
+void CropWin::update(int clear)
+{
+ switch(clear) {
+ case RESET_LEFT :
+ crop_left_text->update((float)client->config.crop_l);
+ crop_left_slider->update((float)client->config.crop_l);
+ break;
+ case RESET_TOP :
+ crop_top_text->update((float)client->config.crop_t);
+ crop_top_slider->update((float)client->config.crop_t);
+ break;
+ case RESET_RIGHT :
+ crop_right_text->update((float)client->config.crop_r);
+ crop_right_slider->update((float)client->config.crop_r);
+ break;
+ case RESET_BOTTOM :
+ crop_bottom_text->update((float)client->config.crop_b);
+ crop_bottom_slider->update((float)client->config.crop_b);
+ break;
+ case RESET_POSITION_X :
+ crop_position_x_text->update((float)client->config.position_x);
+ crop_position_x_slider->update((float)client->config.position_x);
+ break;
+ case RESET_POSITION_Y :
+ crop_position_y_text->update((float)client->config.position_y);
+ crop_position_y_slider->update((float)client->config.position_y);
+ break;
+ case RESET_ALL :
+ case RESET_DEFAULT_SETTINGS :
+ default:
+ crop_left_text->update((float)client->config.crop_l);
+ crop_left_slider->update((float)client->config.crop_l);
+ crop_top_text->update((float)client->config.crop_t);
+ crop_top_slider->update((float)client->config.crop_t);
+ crop_right_text->update((float)client->config.crop_r);
+ crop_right_slider->update((float)client->config.crop_r);
+ crop_bottom_text->update((float)client->config.crop_b);
+ crop_bottom_slider->update((float)client->config.crop_b);
+
+ crop_position_x_text->update((float)client->config.position_x);
+ crop_position_x_slider->update((float)client->config.position_x);
+ crop_position_y_text->update((float)client->config.position_y);
+ crop_position_y_slider->update((float)client->config.position_y);
+ break;
+ }
+}
+
+
+
+
+
+
+
+/* *********************************** */
+/* **** CROP LEFT ******************** */
+CropLeftText::CropLeftText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.crop_l,
+ (float)0.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropLeftText::~CropLeftText()
+{
+}
+
+int CropLeftText::handle_event()
+{
+ client->config.crop_l = atof(get_text());
+ win->crop_left_slider->update(client->config.crop_l);
+ client->send_configure_change();
+ return 1;
+}
+
+CropLeftSlider::CropLeftSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.crop_l)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropLeftSlider::~CropLeftSlider()
+{
+}
+
+int CropLeftSlider::handle_event()
+{
+ client->config.crop_l = get_value();
+ win->crop_left_text->update(client->config.crop_l);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+/* *********************************** */
+/* **** CROP TOP ******************** */
+CropTopText::CropTopText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.crop_t,
+ (float)0.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropTopText::~CropTopText()
+{
+}
+
+int CropTopText::handle_event()
+{
+ client->config.crop_t = atof(get_text());
+ win->crop_top_slider->update(client->config.crop_t);
+ client->send_configure_change();
+ return 1;
+}
+
+CropTopSlider::CropTopSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.crop_t)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropTopSlider::~CropTopSlider()
+{
+}
+
+int CropTopSlider::handle_event()
+{
+ client->config.crop_t = get_value();
+ win->crop_top_text->update(client->config.crop_t);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+/* *********************************** */
+/* **** CROP RIGHT ******************* */
+CropRightText::CropRightText(CropWin *win, CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.crop_r,
+ (float)0.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropRightText::~CropRightText()
+{
+}
+
+int CropRightText::handle_event()
+{
+ client->config.crop_r = atof(get_text());
+ win->crop_right_slider->update(client->config.crop_r);
+ client->send_configure_change();
+ return 1;
+}
+
+CropRightSlider::CropRightSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.crop_r)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropRightSlider::~CropRightSlider()
+{
+}
+
+int CropRightSlider::handle_event()
+{
+ client->config.crop_r = get_value();
+ win->crop_right_text->update(client->config.crop_r);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+/* *********************************** */
+/* **** CROP BOTTOM ****************** */
+CropBottomText::CropBottomText(CropWin *win, CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.crop_b,
+ (float)0.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropBottomText::~CropBottomText()
+{
+}
+
+int CropBottomText::handle_event()
+{
+ client->config.crop_b = atof(get_text());
+ win->crop_bottom_slider->update(client->config.crop_b);
+ client->send_configure_change();
+ return 1;
+}
+
+CropBottomSlider::CropBottomSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.crop_b)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropBottomSlider::~CropBottomSlider()
+{
+}
+
+int CropBottomSlider::handle_event()
+{
+ client->config.crop_b = get_value();
+ win->crop_bottom_text->update(client->config.crop_b);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+/* *********************************** */
+/* **** CROP POSITION X ************** */
+CropPositionXText::CropPositionXText(CropWin *win, CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.position_x,
+ (float)-100.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropPositionXText::~CropPositionXText()
+{
+}
+
+int CropPositionXText::handle_event()
+{
+ client->config.position_x = atof(get_text());
+ win->crop_position_x_slider->update(client->config.position_x);
+ client->send_configure_change();
+ return 1;
+}
+
+CropPositionXSlider::CropPositionXSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, -100.00, 100.00, client->config.position_x)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropPositionXSlider::~CropPositionXSlider()
+{
+}
+
+int CropPositionXSlider::handle_event()
+{
+ client->config.position_x = get_value();
+ win->crop_position_x_text->update(client->config.position_x);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+/* *********************************** */
+/* **** CROP POSITION Y ************** */
+CropPositionYText::CropPositionYText(CropWin *win, CropMain *client,
+ int x,
+ int y)
+ : BC_TumbleTextBox(win,
+ client->config.position_y,
+ (float)-100.00,
+ (float)100.00,
+ x,
+ y,
+ 60, 2)
+{
+ this->win = win;
+ this->client = client;
+}
+
+CropPositionYText::~CropPositionYText()
+{
+}
+
+int CropPositionYText::handle_event()
+{
+ client->config.position_y = atof(get_text());
+ win->crop_position_y_slider->update(client->config.position_y);
+ client->send_configure_change();
+ return 1;
+}
+
+CropPositionYSlider::CropPositionYSlider(CropWin *win, CropMain *client,
+ int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, -100.00, 100.00, client->config.position_y)
+{
+ this->win = win;
+ this->client = client;
+ enable_show_value(0); // Hide caption
+ set_precision(0.01);
+}
+
+CropPositionYSlider::~CropPositionYSlider()
+{
+}
+
+int CropPositionYSlider::handle_event()
+{
+ client->config.position_y = get_value();
+ win->crop_position_y_text->update(client->config.position_y);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
+/* *********************************** */
+
+
+CropEdgesClr::CropEdgesClr(CropWin *win, CropMain *client, int x, int y, int clear)
+ : BC_Button(x, y, client->get_theme()->get_image_set("reset_button"))
+{
+ this->win = win;
+ this->client = client;
+ this->clear = clear;
+}
+CropEdgesClr::~CropEdgesClr()
+{
+}
+int CropEdgesClr::handle_event()
+{
+ client->config.reset(clear);
+ win->update(clear);
+ client->send_configure_change();
+ return 1;
+}
+
+CropReset::CropReset(CropMain *client, CropWin *win, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+ this->client = client;
+ this->win = win;
+}
+
+CropReset::~CropReset()
+{
+}
+
+int CropReset::handle_event()
+{
+ client->config.reset(RESET_ALL);
+ win->update(RESET_ALL);
+ client->send_configure_change();
+ return 1;
+}
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * 2019. Derivative by Translate plugin. This plugin works also with Proxy.
+ * It uses Percent values instead of Pixel value coordinates.
+*/
+
+#ifndef CROPWIN_H
+#define CROPWIN_H
+
+
+class CropThread;
+class CropWin;
+class CropLeftText;
+class CropLeftSlider;
+class CropTopText;
+class CropTopSlider;
+class CropRightText;
+class CropRightSlider;
+class CropBottomText;
+class CropBottomSlider;
+class CropPositionXText;
+class CropPositionXSlider;
+class CropPositionYText;
+class CropPositionYSlider;
+class CropReset;
+class CropEdgesClr;
+
+#include "guicast.h"
+#include "filexml.h"
+#include "mutex.h"
+#include "pluginclient.h"
+#include "crop.h"
+
+#define RESET_DEFAULT_SETTINGS 10
+#define RESET_ALL 0
+#define RESET_LEFT 1
+#define RESET_TOP 2
+#define RESET_RIGHT 3
+#define RESET_BOTTOM 4
+#define RESET_POSITION_X 5
+#define RESET_POSITION_Y 6
+
+
+class CropWin : public PluginClientWindow
+{
+public:
+ CropWin(CropMain *client);
+ ~CropWin();
+
+ void create_objects();
+ void update(int clear);
+
+ // Crop: Left, Top, Right, Bottom
+ CropLeftText *crop_left_text;
+ CropLeftSlider *crop_left_slider;
+ CropEdgesClr *crop_left_clr;
+
+ CropTopText *crop_top_text;
+ CropTopSlider *crop_top_slider;
+ CropEdgesClr *crop_top_clr;
+
+ CropRightText *crop_right_text;
+ CropRightSlider *crop_right_slider;
+ CropEdgesClr *crop_right_clr;
+
+ CropBottomText *crop_bottom_text;
+ CropBottomSlider *crop_bottom_slider;
+ CropEdgesClr *crop_bottom_clr;
+
+ // Crop: Position_X, Position_Y
+ CropPositionXText *crop_position_x_text;
+ CropPositionXSlider *crop_position_x_slider;
+ CropEdgesClr *crop_position_x_clr;
+
+ CropPositionYText *crop_position_y_text;
+ CropPositionYSlider *crop_position_y_slider;
+ CropEdgesClr *crop_position_y_clr;
+
+ CropMain *client;
+ CropReset *reset;
+};
+
+
+class CropLeftText : public BC_TumbleTextBox
+{
+public:
+ CropLeftText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropLeftText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropLeftSlider : public BC_FSlider
+{
+public:
+ CropLeftSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropLeftSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropTopText : public BC_TumbleTextBox
+{
+public:
+ CropTopText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropTopText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropTopSlider : public BC_FSlider
+{
+public:
+ CropTopSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropTopSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropRightText : public BC_TumbleTextBox
+{
+public:
+ CropRightText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropRightText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropRightSlider : public BC_FSlider
+{
+public:
+ CropRightSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropRightSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropBottomText : public BC_TumbleTextBox
+{
+public:
+ CropBottomText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropBottomText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropBottomSlider : public BC_FSlider
+{
+public:
+ CropBottomSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropBottomSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropPositionXText : public BC_TumbleTextBox
+{
+public:
+ CropPositionXText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropPositionXText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropPositionXSlider : public BC_FSlider
+{
+public:
+ CropPositionXSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropPositionXSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropPositionYText : public BC_TumbleTextBox
+{
+public:
+ CropPositionYText(CropWin *win,
+ CropMain *client,
+ int x,
+ int y);
+ ~CropPositionYText();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+class CropPositionYSlider : public BC_FSlider
+{
+public:
+ CropPositionYSlider(CropWin *win, CropMain *client,
+ int x, int y, int w);
+ ~CropPositionYSlider();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+};
+
+class CropEdgesClr : public BC_Button
+{
+public:
+ CropEdgesClr(CropWin *win, CropMain *client,
+ int x, int y, int clear);
+ ~CropEdgesClr();
+ int handle_event();
+ CropWin *win;
+ CropMain *client;
+ int clear;
+};
+
+class CropReset : public BC_GenericButton
+{
+public:
+ CropReset(CropMain *client, CropWin *win, int x, int y);
+ ~CropReset();
+ int handle_event();
+ CropMain *client;
+ CropWin *win;
+};
+
+#endif
https://sourceforge.net/projects/libuuid/files/latest/download?source=directory - 1.0.3
ftp://ftp.videolan.org/pub/x264/snapshots/x264-snapshot-20190131-2245-stable.tar.bz2
https://bitbucket.org/multicoreware/x265/downloads/x265_3.0.tar.gz
-http://ffmpeg.org/releases/ffmpeg-4.1.tar.gz
-https://github.com/webmproject/libvpx/releases/tag/v1.7.0
+https://ffmpeg.org/releases/ffmpeg-4.2.tar.bz2
+https://github.com/webmproject/libvpx/archive/v1.8.1.tar.gz
+https://code.videolan.org/videolan/dav1d/-/archive/0.4.0/dav1d-0.4.0.tar.gz
https://github.com/swh/ladspa/releases/tag/v0.4.17, plugin.org.uk
https://archive.mozilla.org/pub/opus/opus-1.3.tar.gz
https://github.com/webmproject/libwebp = libwebp-1.0.2