From: Good Guy Date: Thu, 25 Apr 2019 01:32:33 +0000 (-0600) Subject: tweak ffmpeg mpeg hw probe, update bld prepare, insert tracer source X-Git-Tag: 2019-08~64 X-Git-Url: https://cinelerra-gg.org/git/?a=commitdiff_plain;h=f06e8ed85bd5937d704d57b65e0fb26ed288996d;p=goodguy%2Fcinelerra.git tweak ffmpeg mpeg hw probe, update bld prepare, insert tracer source --- diff --git a/cinelerra-5.1/blds/bld_prepare.sh b/cinelerra-5.1/blds/bld_prepare.sh index c79c8ef5..7c1eec81 100755 --- a/cinelerra-5.1/blds/bld_prepare.sh +++ b/cinelerra-5.1/blds/bld_prepare.sh @@ -26,8 +26,8 @@ case "$dir" in libavc1394 festival-devel libiec61883-devel flac-devel inkscape \ libsndfile-devel libtheora-devel linux-firmware ivtv-firmware \ libvorbis-devel texinfo xz-devel lzma-devel cmake udftools git \ - autoconf automake rpm-build jbigkit-devel libvdpau-devel alsa-lib-devel \ - gtk2-devel + autoconf automake rpm-build jbigkit-devel libvdpau-devel libva-devel \ + alsa-lib-devel gtk2-devel yasm=yasm-1.3.0-3.fc24.x86_64.rpm release=http://archives.fedoraproject.org/pub/fedora/linux/releases/24 url=$release/Everything/x86_64/os/Packages/y/$yasm @@ -51,7 +51,7 @@ case "$dir" in ivtv-firmware libvorbis-devel texinfo xz-devel lzma-devel cmake git \ ctags patch gcc-c++ perl-XML-XPath libtiff-devel python dvdauthor \ gettext-devel inkscape udftools autoconf automake numactl-devel \ - jbigkit-devel libvdpau-devel gtk2-devel + jbigkit-devel libvdpau-devel libva-devel gtk2-devel ;; "suse" | "leap") zypper -n install nasm gcc gcc-c++ zlib-devel texinfo libpng16-devel \ @@ -62,8 +62,8 @@ case "$dir" in libdvdnav-devel libdvdread-devel libiec61883-devel libuuid-devel \ ilmbase-devel fftw3-devel libsndfile-devel libtheora-devel flac-devel \ libtiff-devel inkscape cmake patch libnuma-devel lzma-devel udftools git \ - yasm autoconf automake rpm-build libjbig-devel libvdpau-devel gtk2-devel \ - libusb-1_0-devel + yasm autoconf automake rpm-build libjbig-devel libvdpau-devel libva-devel \ + gtk2-devel libusb-1_0-devel if [ ! -f /usr/lib64/libtermcap.so ]; then ln -s libtermcap.so.2 /usr/lib64/libtermcap.so fi @@ -75,7 +75,7 @@ case "$dir" in libncurses5-dev libxinerama-dev libfreetype6-dev libxft-dev libgif-dev \ libtiff5-dev exuberant-ctags ttf-bitstream-vera xfonts-75dpi xfonts-100dpi \ fonts-dejavu libopenexr-dev festival libfftw3-dev gdb libusb-1.0-0-dev \ - libdc1394-22-dev libflac-dev libjbig-dev libvdpau-dev \ + libdc1394-22-dev libflac-dev libjbig-dev libvdpau-dev libva-dev \ inkscape libsndfile1-dev libtheora-dev cmake udftools libxml2-utils git \ autoconf automake debhelper libgtk2.0-dev ;; @@ -88,8 +88,8 @@ case "$dir" in libtiff5-dev exuberant-ctags ttf-bitstream-vera xfonts-75dpi xfonts-100dpi \ fonts-dejavu libopenexr-dev libavc1394-dev festival-dev fftw3-dev gdb \ libdc1394-22-dev libiec61883-dev libflac-dev libjbig-dev libusb-1.0-0-dev \ - libvdpau-dev libsndfile1-dev libtheora-dev cmake udftools libxml2-utils \ - git inkscape autoconf automake debhelper libgtk2.0-dev + libvdpau-dev libva-dev libsndfile1-dev libtheora-dev cmake udftools \ + libxml2-utils git inkscape autoconf automake debhelper libgtk2.0-dev ;; *) echo "unknown os: $dir" diff --git a/cinelerra-5.1/plugins/tracer/.gdb_history b/cinelerra-5.1/plugins/tracer/.gdb_history new file mode 100644 index 00000000..a1ff470a --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/.gdb_history @@ -0,0 +1 @@ +p 82*541/352 diff --git a/cinelerra-5.1/plugins/tracer/Makefile b/cinelerra-5.1/plugins/tracer/Makefile new file mode 100644 index 00000000..be988037 --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/Makefile @@ -0,0 +1,13 @@ +include ../../plugin_defs + +OBJS := \ + $(OBJDIR)/tracer.o \ + $(OBJDIR)/tracerwindow.o + +PLUGIN = tracer + +include ../../plugin_config + +$(OBJDIR)/tracer.o: tracer.C +$(OBJDIR)/tracerwindow.o: tracerwindow.C + diff --git a/cinelerra-5.1/plugins/tracer/tracer.C b/cinelerra-5.1/plugins/tracer/tracer.C new file mode 100644 index 00000000..be58496d --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/tracer.C @@ -0,0 +1,687 @@ +/* + * CINELERRA + * Copyright (C) 1997-2015 Adam Williams + * + * 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 + * + */ + +#include +#include +#include +#include +#include + +#include "arraylist.h" +#include "bccmodels.h" +#include "bccolors.h" +#include "clip.h" +#include "edlsession.h" +#include "filexml.h" +#include "tracer.h" +#include "tracerwindow.h" +#include "language.h" +#include "vframe.h" + +REGISTER_PLUGIN(Tracer) + +void tracer_pgm(const char *fn,VFrame *vfrm) +{ + FILE *fp = fopen(fn,"w"); + int w = vfrm->get_w(), h = vfrm->get_h(); + fprintf(fp,"P5\n%d %d\n255\n",w,h); + fwrite(vfrm->get_data(),w,h,fp); + fclose(fp); +} + +TracerPoint::TracerPoint(float x, float y) +{ + this->x = x; this->y = y; +} +TracerPoint::~TracerPoint() +{ +} + +TracerConfig::TracerConfig() +{ + drag = draw = fill = 0; + radius = 0; scale = 1; + selected = 0; +} +TracerConfig::~TracerConfig() +{ +} + +int TracerConfig::equivalent(TracerConfig &that) +{ + if( this->drag != that.drag ) return 0; + if( this->draw != that.draw ) return 0; + if( this->fill != that.fill ) return 0; + if( this->radius != that.radius ) return 0; + if( this->scale != that.scale ) return 0; + if( this->points.size() != that.points.size() ) return 0; + for( int i=0, n=points.size(); ipoints[i], *bp = that.points[i]; + if( !EQUIV(ap->x, bp->x) ) return 0; + if( !EQUIV(ap->y, bp->y) ) return 0; + } + return 1; +} + +void TracerConfig::copy_from(TracerConfig &that) +{ + this->drag = that.drag; + this->draw = that.draw; + this->fill = that.fill; + this->selected = that.selected; + this->radius = that.radius; + this->scale = that.scale; + points.remove_all_objects(); + for( int i=0,n=that.points.size(); ix, pt->y); + } +} + +void TracerConfig::interpolate(TracerConfig &prev, TracerConfig &next, + long prev_frame, long next_frame, long current_frame) +{ + copy_from(prev); +} + +void TracerConfig::limits() +{ +} + +int TracerConfig::add_point(float x, float y) +{ + int i = points.size(); + points.append(new TracerPoint(x, y)); + return i; +} + +void TracerConfig::del_point(int i) +{ + points.remove_object_number(i); +} + + +Tracer::Tracer(PluginServer *server) + : PluginVClient(server) +{ + frm = 0; frm_rows = 0; + msk = 0; msk_rows = 0; + edg = 0; edg_rows = 0; + w = 0; w1 = w-1; + h = 0; h1 = h-1; + color_model = bpp = 0; + is_float = is_yuv = 0; + comps = comp = 0; + ax = 0; ay = 0; + bx = 0; by = 0; + cx = 0; cy = 0; + ex = 0; ey = 0; +} + +Tracer::~Tracer() +{ + delete edg; + delete msk; +} + +const char* Tracer::plugin_title() { return N_("Tracer"); } +int Tracer::is_realtime() { return 1; } + +NEW_WINDOW_MACRO(Tracer, TracerWindow); +int Tracer::load_configuration1() +{ + KeyFrame *prev_keyframe = get_prev_keyframe(get_source_position()); + if( prev_keyframe->position == get_source_position() ) { + read_data(prev_keyframe); + return 1; + } + return load_configuration(); +} +LOAD_CONFIGURATION_MACRO(Tracer, TracerConfig); + +int Tracer::new_point() +{ + EDLSession *session = get_edlsession(); + float x = !session ? 0.f : session->output_w / 2.f; + float y = !session ? 0.f : session->output_h / 2.f; + return config.add_point(x, y); +} + +void Tracer::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->xbuf); + + output.tag.set_title("TRACER"); + output.tag.set_property("DRAG", config.drag); + output.tag.set_property("DRAW", config.draw); + output.tag.set_property("FILL", config.fill); + output.tag.set_property("RADIUS", config.radius); + output.tag.set_property("SCALE", config.scale); + output.tag.set_property("SELECTED", config.selected); + output.append_tag(); + output.append_newline(); + output.tag.set_title("/TRACER"); + output.append_tag(); + output.append_newline(); + for( int i=0, n=config.points.size(); ix); + output.tag.set_property("Y", pt->y); + output.append_tag(); + output.tag.set_title(point+0); + output.append_tag(); + output.append_newline(); + } + output.terminate_string(); +} + +void Tracer::read_data(KeyFrame *keyframe) +{ + FileXML input; + input.set_shared_input(keyframe->xbuf); + config.points.remove_all_objects(); + int result = 0; + + while( !(result=input.read_tag()) ) { + if( input.tag.title_is("TRACER") ) { + config.drag = input.tag.get_property("DRAG", config.drag); + config.draw = input.tag.get_property("DRAW", config.draw); + config.fill = input.tag.get_property("FILL", config.fill); + config.radius = input.tag.get_property("RADIUS", config.radius); + config.scale = input.tag.get_property("SCALE", config.scale); + config.selected = input.tag.get_property("SELECTED", 0); + config.limits(); + } + else if( !strncmp(input.tag.get_title(),"POINT_",6) ) { + float x = input.tag.get_property("X", 0.f); + float y = input.tag.get_property("Y", 0.f); + config.add_point(x, y); + } + } + + if( !config.points.size() ) new_point(); +} + +void Tracer::update_gui() +{ + if( !thread ) return; + thread->window->lock_window("Tracer::update_gui"); + TracerWindow *window = (TracerWindow*)thread->window; + if( load_configuration1() ) { + window->update_gui(); + window->flush(); + } + thread->window->unlock_window(); +} + +void Tracer::draw_point(TracerPoint *pt) +{ + int d = bmax(w,h) / 200 + 2; + int r = d/2+1, x = pt->x, y = pt->y; + frm->draw_smooth(x-r,y+0, x-r, y-r, x+0,y-r); + frm->draw_smooth(x+0,y-r, x+r, y-r, x+r,y+0); + frm->draw_smooth(x+r,y+0, x+r, y+r, x+0,y+r); + frm->draw_smooth(x+0,y+r, x-r, y+r, x-r,y+0); +} + +void Tracer::draw_points() +{ + for( int i=0, n=config.points.size(); iset_pixel_color(config.selected == i ? GREEN : WHITE); + draw_point(pt); + } +} +void Tracer::draw_edge() +{ + float scale = 1 / 255.0f; + int color_model = frm->get_color_model(); + int bpp = BC_CModels::calculate_pixelsize(color_model); + switch( color_model ) { + case BC_RGB_FLOAT: + for( int y=0; y 0 ) PIX_GRADIENT(type,-1, iy); \ + if( iy != 0) PIX_GRADIENT(type, 0, iy); \ + if( vx < w1) PIX_GRADIENT(type, 1, iy); \ +} while(0) +#define MAX_GRADIENT(type) do { \ + type *xp = (type *)(frm_rows[vy] + vx*bpp); \ + if( vy > 0 ) ROW_GRADIENT(type,-1); \ + ROW_GRADIENT(type, 0); \ + if( vy < h1 ) ROW_GRADIENT(type, 1); \ +} while(0) + +#define MAX_PIXEL(type, ix, iy) do { \ + int vx = cx + ix, vy = cy + iy; \ + if( edg_rows[vy][vx] ) break; \ + float vv = FLT_MAX; \ + int dx = ex-vx, dy = ey-vy; \ + int rr = dx*dx + dy*dy; \ + if( rr > dd ) break; \ + if( rr > 0 ) { \ + float r = (float)(ix*dx + iy*dy) / rr; \ + float vmax = 0; \ + MAX_GRADIENT(type); \ + vv = r + vmax; \ + } \ + if( maxv < vv ) { \ + maxv = vv; \ + nx = vx; ny = vy; \ + } \ +} while(0) +#define ROW_MAX(type, iy) do { \ + if( cx > 0 ) MAX_PIXEL(type,-1, iy); \ + if( iy != 0 ) MAX_PIXEL(type, 0, iy); \ + if( cx < w1 ) MAX_PIXEL(type, 1, iy); \ +} while(0) + +int Tracer::step() +{ + int ret = 0; + if( !edg_rows[cy][cx] ) { + points.add(cx,cy); + edg_rows[cy][cx] = 0xff; + } + int dx = ex-cx, dy = ey-cy; + int dd = dx*dx + dy*dy; + if( !dd ) return ret; + int nx = cx, ny = cy; + double maxv = -FLT_MAX; + if( cy > 0 ) ROW_MAX(uint8_t,-1); + ROW_MAX(uint8_t, 0); + if( cy < h1 ) ROW_MAX(uint8_t, 1); + cx = nx; cy = ny; + return maxv > 0 ? 1 : 0; +} + +void Tracer::trace(int i0, int i1) +{ + TracerPoint *pt0 = config.points[i0]; + TracerPoint *pt1 = config.points[i1]; + cx = pt0->x; bclamp(cx, 0, w1); + cy = pt0->y; bclamp(cy, 0, h1); + ex = pt1->x; bclamp(ex, 0, w1); + ey = pt1->y; bclamp(ey, 0, h1); + while( step() ); +} + +int Tracer::smooth() +{ + int &n = points.total, m = 0; + if( n < 3 ) return m; + TracePoint *ap; + TracePoint *bp = &points[0]; + TracePoint *cp = &points[1]; + for( ; n>=3; --n ) { + ap = &points[n-1]; + if( abs(ap->x-cp->x)<2 && abs(ap->y-cp->y)<2 ) { + edg_rows[bp->y][bp->x] = 0; + ++m; + } + else + break; + } + if( n < 3 ) return m; + ap = &points[0]; + bp = &points[1]; + for( int i=2; ix-cp->x)<2 && abs(ap->y-cp->y)<2 && + ( (bp->x==ap->x || bp->x==cp->x) && + (bp->y==ap->y || bp->y==cp->y) ) ) { + edg_rows[bp->y][bp->x] = 0; + ++m; + } + else { + ++ap; ++bp; + } + bp->x = cp->x; bp->y = cp->y; + } + n -= m; + return m; +} + +#if 0 +int winding2(int x, int y, TracePoints &pts, int n) +{ + int w = 0; + int x0 = pts[0].x-x, y0 = pts[0].y-y; + for( int x1,y1,i=1; i 0 ) w += y0<0 ? 2 : -2; // crosses x on plus side + } + else if( !y0 && x0 > 0 ) w += y1>0 ? 1 : -1; + else if( !y1 && x1 > 0 ) w += y0>0 ? 1 : -1; + } + return w; +} +#endif + +class FillRegion +{ + class segment { public: int y, lt, rt; }; + ArrayList stack; + + void push(int y, int lt, int rt) { + segment &seg = stack.append(); + seg.y = y; seg.lt = lt; seg.rt = rt; + } + void pop(int &y, int <, int &rt) { + segment &seg = stack.last(); + y = seg.y; lt = seg.lt; rt = seg.rt; + stack.remove(); + } + + int w, h; + uint8_t *edg; + uint8_t *msk; + bool edge_pixel(int i) { return edg[i] > 0; } + +public: + void fill(int x, int y); + void run(); + + FillRegion(VFrame *edg, VFrame *msk); +}; + +FillRegion::FillRegion(VFrame *edg, VFrame *msk) +{ + this->w = msk->get_w(); + this->h = msk->get_h(); + this->msk = (uint8_t*) msk->get_data(); + this->edg = (uint8_t*) edg->get_data(); +} + +void FillRegion::fill(int x, int y) +{ + push(y, x, x); +} + +void FillRegion::run() +{ + while( stack.size() > 0 ) { + int y, ilt, irt; + pop(y, ilt, irt); + int ofs = y*w + ilt; + for( int x=ilt; x<=irt; ++x,++ofs ) { + if( msk[ofs] ) continue; + msk[ofs] = 0xff; + if( edge_pixel(ofs) ) continue; + int lt = x, rt = x; + int lofs = ofs; + for( int i=lt; --i>=0; lt=i ) { + if( msk[--lofs] ) break; + msk[lofs] = 0xff; + if( edge_pixel(lofs) ) break; + } + int rofs = ofs; + for( int i=rt; ++i< w; rt=i ) { + if( msk[++rofs] ) break; + msk[rofs] = 0xff; + if( edge_pixel(rofs) ) break; + } + if( y+1 < h ) push(y+1, lt, rt); + if( y-1 >= 0 ) push(y-1, lt, rt); + } + } +} + +void Tracer::feather(int r, double s) +{ + if( !r || !s ) return; + int dir = r<0 ? (r=-r, -1) : 1; + if( dir < 0 ) s = 1./s; + int rr = r * r; + int psf[rr]; // pt spot fn + int k = dir>=0 ? 0 : rr-1; + for( int i=0; i 0 ? 0xff : 0; + for( int i=0,n=points.size(); ix-r, xn=pt->x+r; + bclamp(xs, 0, w); + bclamp(xn, 0, w); + int ys = pt->y-r, yn=pt->y+r; + bclamp(ys, 0, h); + bclamp(yn, 0, h); + for( int y=ys ; yx, dy = y-pt->y; + int dd = dx*dx + dy*dy; + if( dd >= rr ) continue; + int pix = msk_rows[y][x], v = psf[dd]; + msk_rows[y][x] = dir >= 0 ? pix+v-(pix*v)/255 : (pix*v)/255; + } + } + } +} + +void Tracer::draw_mask() +{ + switch( color_model ) { + case BC_RGB888: + for( int y=0; yget_rows(); + w = frm->get_w(); w1 = w-1; + h = frm->get_h(); h1 = h-1; + color_model = frm->get_color_model(); + bpp = BC_CModels::calculate_pixelsize(color_model); + is_float = BC_CModels::is_float(color_model); + is_yuv = BC_CModels::is_yuv(color_model); + has_alpha = BC_CModels::has_alpha(color_model); + comps = BC_CModels::components(color_model); + comp = bmin(comps, 3); + read_frame(frm, 0, start_position, frame_rate, 0); + if( !edg ) redraw = 1; + VFrame::get_temp(edg, w, h, BC_GREY8); + if( redraw ) { + edg->clear_frame(); + edg_rows = edg->get_rows(); + + int n = config.points.size()-1; + points.clear(); + for( int i=0; i 0 ) + trace(n,0); + while( smooth() > 0 ); + + if( config.fill && points.size() > 2 ) { + int l = points.size(), l2 = l/2; + TracePoint *pt0 = &points[0], *pt1 = &points[l2]; + int cx = (pt0->x+pt1->x)/2, cy = (pt0->y+pt1->y)/2; + VFrame::get_temp(msk, w, h, BC_GREY8); + msk->clear_frame(); + msk_rows = msk->get_rows(); + + FillRegion fill_region(edg, msk); + fill_region.fill(cx, cy); + fill_region.run(); + + feather(config.radius, config.scale); + } + } + if( config.fill ) + draw_mask(); + if( config.draw ) + draw_edge(); + if( config.drag ) + draw_points(); + return 0; +} + diff --git a/cinelerra-5.1/plugins/tracer/tracer.h b/cinelerra-5.1/plugins/tracer/tracer.h new file mode 100644 index 00000000..cc2364e5 --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/tracer.h @@ -0,0 +1,130 @@ +/* + * CINELERRA + * Copyright (C) 1997-2014 Adam Williams + * + * 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 + * + */ + + + +#ifndef __TRACER_H__ +#define __TRACER_H__ + +#include "loadbalance.h" +#include "pluginvclient.h" + +class Tracer; + +enum { PT_X, PT_Y, PT_SZ }; + +class TracerPoint +{ +public: + float x, y; + + TracerPoint(float x, float y); + ~TracerPoint(); +}; +class TracerPoints : public ArrayList +{ +public: + TracerPoints() {} + ~TracerPoints() { remove_all_objects(); } +}; + +class TracerConfig +{ +public: + TracerConfig(); + ~TracerConfig(); + + int equivalent(TracerConfig &that); + void copy_from(TracerConfig &that); + void interpolate(TracerConfig &prev, TracerConfig &next, + long prev_frame, long next_frame, long current_frame); + void limits(); + + TracerPoints points; + int add_point(float x, float y); + int add_point(); + void del_point(int i); + + int drag, draw, fill; + int radius; + double scale; + int selected; +}; + +class TracePoint +{ +public: + int x, y, n; + TracePoint() {} + TracePoint(int x, int y) { + this->x = x; this->y = y; + this->n = 0; + } +}; + +class TracePoints : public ArrayList +{ +public: + TracePoints() {} + void add(int x, int y) { + TracePoint *np = &append(); + np->x = x; np->y = y; + } + void clear() { remove_all(); } +}; + + +class Tracer : public PluginVClient +{ +public: + Tracer(PluginServer *server); + ~Tracer(); +// required for all realtime plugins + PLUGIN_CLASS_MEMBERS2(TracerConfig) + int is_realtime(); + void update_gui(); + int new_point(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + int process_buffer(VFrame *frame, int64_t start_position, double frame_rate); + void draw_edge(); + void draw_mask(); + void draw_point(TracerPoint *pt); + void draw_points(); + int step(); + void trace(int i0, int i1); + int smooth(); + void feather(int r, double s); + int load_configuration1(); + + VFrame *edg, *msk, *frm; + uint8_t **edg_rows; + uint8_t **msk_rows; + uint8_t **frm_rows; + TracePoints points; + int w, w1, h, h1, pts; + int ax, ay, bx, by, cx, cy; + int ex, ey, nx, ny; + int color_model, bpp; + int is_float, is_yuv, has_alpha; + int comps, comp; +}; + +#endif diff --git a/cinelerra-5.1/plugins/tracer/tracerwindow.C b/cinelerra-5.1/plugins/tracer/tracerwindow.C new file mode 100644 index 00000000..af0ec2f2 --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/tracerwindow.C @@ -0,0 +1,619 @@ +/* + * CINELERRA + * Copyright (C) 2014 Adam Williams + * + * 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 + * + */ + +#include "automation.h" +#include "bcdisplayinfo.h" +#include "clip.h" +#include "tracer.h" +#include "tracerwindow.h" +#include "cstrdup.h" +#include "cwindow.h" +#include "cwindowgui.h" +#include "edl.h" +#include "edlsession.h" +#include "language.h" +#include "mainerror.h" +#include "mwindow.h" +#include "plugin.h" +#include "pluginserver.h" +#include "theme.h" +#include "track.h" + +#define COLOR_W 50 +#define COLOR_H 30 + +TracerNum::TracerNum(TracerWindow *gui, int x, int y, float output) + : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 120) +{ + this->gui = gui; + set_increment(1); + set_precision(1); +} + +TracerNum::~TracerNum() +{ +} + +int TracerPointX::handle_event() +{ + if( !TracerNum::handle_event() ) return 0; + TracerPointList *point_list = gui->point_list; + int hot_point = point_list->get_selection_number(0, 0); + TracerPoints &points = gui->plugin->config.points; + int sz = points.size(); + if( hot_point >= 0 && hot_point < sz ) { + float v = atof(get_text()); + points[hot_point]->x = v; + point_list->set_point(hot_point, PT_X, v); + } + point_list->update_list(hot_point); + gui->send_configure_change(); + return 1; +} +int TracerPointY::handle_event() +{ + if( !TracerNum::handle_event() ) return 0; + TracerPointList *point_list = gui->point_list; + int hot_point = point_list->get_selection_number(0, 0); + TracerPoints &points = gui->plugin->config.points; + int sz = points.size(); + if( hot_point >= 0 && hot_point < sz ) { + float v = atof(get_text()); + points[hot_point]->y = v; + point_list->set_point(hot_point, PT_Y, v); + } + point_list->update_list(hot_point); + gui->send_configure_change(); + return 1; +} + +TracerWindow::TracerWindow(Tracer *plugin) + : PluginClientWindow(plugin, 400, 300, 400, 300, 0) +{ + this->plugin = plugin; + this->title_x = 0; this->point_x = 0; + this->title_y = 0; this->point_y = 0; + this->new_point = 0; this->del_point = 0; + this->point_up = 0; this->point_dn = 0; + this->drag = 0; this->draw = 0; + this->dragging = 0; + this->title_r = 0; this->title_s = 0; + this->radius = 0; this->scale = 0; + this->last_x = 0; this->last_y = 0; + this->point_list = 0; this->pending_config = 0; +} + +TracerWindow::~TracerWindow() +{ + delete point_x; + delete point_y; +} + +void TracerWindow::create_objects() +{ + int x = 10, y = 10; + int margin = plugin->get_theme()->widget_border; + TracerPoint *pt = plugin->config.points[plugin->config.selected]; + add_subwindow(title_x = new BC_Title(x, y, _("X:"))); + int x1 = x + title_x->get_w() + margin; + point_x = new TracerPointX(this, x1, y, pt->x); + point_x->create_objects(); + x1 += point_x->get_w() + margin; + add_subwindow(new_point = new TracerNewPoint(this, plugin, x1, y)); + x1 += new_point->get_w() + margin; + add_subwindow(point_up = new TracerPointUp(this, x1, y)); + y += point_x->get_h() + margin; + add_subwindow(title_y = new BC_Title(x, y, _("Y:"))); + x1 = x + title_y->get_w() + margin; + point_y = new TracerPointY(this, x1, y, pt->y); + point_y->create_objects(); + x1 += point_y->get_w() + margin; + add_subwindow(del_point = new TracerDelPoint(this, plugin, x1, y)); + x1 += del_point->get_w() + margin; + add_subwindow(point_dn = new TracerPointDn(this, x1, y)); + y += point_y->get_h() + margin + 10; + + add_subwindow(drag = new TracerDrag(this, x, y)); + if( plugin->config.drag ) { + if( !grab(plugin->server->mwindow->cwindow->gui) ) + eprintf("drag enabled, but compositor already grabbed\n"); + } + x1 = x + drag->get_w() + margin + 20; + add_subwindow(draw = new TracerDraw(this, x1, y)); + x1 += draw->get_w() + margin + 20; + add_subwindow(fill = new TracerFill(this, x1, y)); + x1 += drag->get_w() + margin + 20; + add_subwindow(reset = new TracerReset(this, plugin, x1, y+3)); + y += drag->get_h() + margin; + + add_subwindow(title_r = new BC_Title(x1=x, y, _("Radius:"))); + x1 += title_r->get_w() + margin; + add_subwindow(radius = new TracerRadius(this, x1, y, 100)); + x1 += radius->get_w() + margin + 20; + add_subwindow(title_s = new BC_Title(x1, y, _("Scale:"))); + x1 += title_s->get_w() + margin; + add_subwindow(scale = new TracerScale(this, x1, y, 100)); + y += radius->get_h() + margin + 20; + + add_subwindow(point_list = new TracerPointList(this, plugin, x, y)); + point_list->update(plugin->config.selected); +// y += point_list->get_h() + 10; + + show_window(1); +} + +void TracerWindow::send_configure_change() +{ + pending_config = 0; + plugin->send_configure_change(); +} + +int TracerWindow::grab_event(XEvent *event) +{ + int ret = do_grab_event(event); + if( pending_config && !grab_event_count() ) + send_configure_change(); + return ret; +} + +int TracerWindow::do_grab_event(XEvent *event) +{ + switch( event->type ) { + case ButtonPress: break; + case ButtonRelease: break; + case MotionNotify: break; + default: + return 0; + } + + MWindow *mwindow = plugin->server->mwindow; + CWindowGUI *cwindow_gui = mwindow->cwindow->gui; + CWindowCanvas *canvas = cwindow_gui->canvas; + int cx, cy; cwindow_gui->get_relative_cursor(cx, cy); + cx -= canvas->view_x; + cy -= canvas->view_y; + + if( !dragging ) { + if( cx < 0 || cx >= canvas->view_w || + cy < 0 || cy >= canvas->view_h ) + return 0; + } + + switch( event->type ) { + case ButtonPress: + if( dragging ) return 0; + dragging = event->xbutton.state & ShiftMask ? -1 : 1; + break; + case ButtonRelease: + if( !dragging ) return 0; + dragging = 0; + return 1; + case MotionNotify: + if( !dragging ) return 0; + break; + default: + return 0; + } + + float cursor_x = cx, cursor_y = cy; + canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y); + int64_t position = plugin->get_source_position(); + float projector_x, projector_y, projector_z; + Track *track = plugin->server->plugin->track; + int track_w = track->track_w, track_h = track->track_h; + track->automation->get_projector( + &projector_x, &projector_y, &projector_z, + position, PLAY_FORWARD); + projector_x += mwindow->edl->session->output_w / 2; + projector_y += mwindow->edl->session->output_h / 2; + float output_x = (cursor_x - projector_x) / projector_z + track_w / 2; + float output_y = (cursor_y - projector_y) / projector_z + track_h / 2; + point_x->update((int64_t)(output_x)); + point_y->update((int64_t)(output_y)); + TracerPoints &points = plugin->config.points; + + if( dragging > 0 ) { + switch( event->type ) { + case ButtonPress: { + int button_no = event->xbutton.button; + int hot_point = -1; + if( button_no == RIGHT_BUTTON ) { + hot_point = plugin->new_point(); + TracerPoint *pt = points[hot_point]; + pt->x = output_x; pt->y = output_y; + point_list->update(hot_point); + break; + } + int sz = points.size(); + if( hot_point < 0 && sz > 0 ) { + TracerPoint *pt = points[hot_point=0]; + double dist = DISTANCE(output_x,output_y, pt->x,pt->y); + for( int i=1; ix,pt->y); + if( d >= dist ) continue; + dist = d; hot_point = i; + } + pt = points[hot_point]; + float px = (pt->x - track_w / 2) * projector_z + projector_x; + float py = (pt->y - track_h / 2) * projector_z + projector_y; + dist = DISTANCE(px, py, cursor_x,cursor_y); + if( dist >= HANDLE_W ) hot_point = -1; + } + if( hot_point >= 0 && sz > 0 ) { + TracerPoint *pt = points[hot_point]; + point_list->set_point(hot_point, PT_X, pt->x = output_x); + point_list->set_point(hot_point, PT_Y, pt->y = output_y); + point_list->update_list(hot_point); + } + break; } + case MotionNotify: { + int hot_point = point_list->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < points.size() ) { + TracerPoint *pt = points[hot_point]; + if( pt->x == output_x && pt->y == output_y ) break; + point_list->set_point(hot_point, PT_X, pt->x = output_x); + point_list->set_point(hot_point, PT_Y, pt->y = output_y); + point_x->update(pt->x); + point_y->update(pt->y); + point_list->update_list(hot_point); + } + break; } + } + } + else { + switch( event->type ) { + case MotionNotify: { + float dx = output_x - last_x, dy = output_y - last_y; + int sz = points.size(); + for( int i=0; iset_point(i, PT_X, pt->x += dx); + point_list->set_point(i, PT_Y, pt->y += dy); + } + int hot_point = point_list->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < sz ) { + TracerPoint *pt = points[hot_point]; + point_x->update(pt->x); + point_y->update(pt->y); + point_list->update_list(hot_point); + } + break; } + } + } + + last_x = output_x; last_y = output_y; + pending_config = 1; + return 1; +} + +void TracerWindow::done_event(int result) +{ + ungrab(client->server->mwindow->cwindow->gui); +} + +TracerPointList::TracerPointList(TracerWindow *gui, Tracer *plugin, int x, int y) + : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT) +{ + this->gui = gui; + this->plugin = plugin; + titles[PT_X] = _("X"); widths[PT_X] = 90; + titles[PT_Y] = _("Y"); widths[PT_Y] = 90; +} +TracerPointList::~TracerPointList() +{ + clear(); +} +void TracerPointList::clear() +{ + for( int i=PT_SZ; --i>=0; ) + cols[i].remove_all_objects(); +} + +int TracerPointList::column_resize_event() +{ + for( int i=PT_SZ; --i>=0; ) + widths[i] = get_column_width(i); + return 1; +} + +int TracerPointList::handle_event() +{ + int hot_point = get_selection_number(0, 0); + const char *x_text = "", *y_text = ""; + TracerPoints &points = plugin->config.points; + + int sz = points.size(); + if( hot_point >= 0 && sz > 0 ) { + x_text = gui->point_list->cols[PT_X].get(hot_point)->get_text(); + y_text = gui->point_list->cols[PT_Y].get(hot_point)->get_text(); + } + gui->point_x->update(x_text); + gui->point_y->update(y_text); + update(hot_point); + gui->send_configure_change(); + return 1; +} + +int TracerPointList::selection_changed() +{ + handle_event(); + return 1; +} + +void TracerPointList::new_point(const char *xp, const char *yp) +{ + cols[PT_X].append(new BC_ListBoxItem(xp)); + cols[PT_Y].append(new BC_ListBoxItem(yp)); +} + +void TracerPointList::del_point(int i) +{ + for( int sz1=cols[0].size()-1, c=PT_SZ; --c>=0; ) + cols[c].remove_object_number(sz1-i); +} + +void TracerPointList::set_point(int i, int c, float v) +{ + char s[BCSTRLEN]; sprintf(s,"%0.4f",v); + set_point(i,c,s); +} +void TracerPointList::set_point(int i, int c, const char *cp) +{ + cols[c].get(i)->set_text(cp); +} + +int TracerPointList::set_selected(int k) +{ + TracerPoints &points = plugin->config.points; + int sz = points.size(); + if( !sz ) return -1; + bclamp(k, 0, sz-1); + update_selection(&cols[0], k); + return k; +} +void TracerPointList::update_list(int k) +{ + int xpos = get_xposition(), ypos = get_yposition(); + if( k < 0 ) k = get_selection_number(0, 0); + update_selection(&cols[0], k); + BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k); + center_selection(); +} +void TracerPointList::update(int k) +{ + clear(); + TracerPoints &points = plugin->config.points; + int sz = points.size(); + for( int i=0; ix); + char ytxt[BCSTRLEN]; sprintf(ytxt,"%0.4f", pt->y); + new_point(xtxt, ytxt); + } + if( k >= 0 && k < sz ) { + gui->point_x->update(gui->point_list->cols[PT_X].get(k)->get_text()); + gui->point_y->update(gui->point_list->cols[PT_Y].get(k)->get_text()); + plugin->config.selected = k; + } + + update_list(k); +} + +void TracerWindow::update_gui() +{ + TracerConfig &config = plugin->config; + drag->update(config.drag); + draw->update(config.draw); + fill->update(config.fill); + radius->update(config.radius); + scale->update(config.scale); + drag->update(config.drag); + point_list->update(-1); +} + + +TracerPointUp::TracerPointUp(TracerWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Up")) +{ + this->gui = gui; +} +TracerPointUp::~TracerPointUp() +{ +} + +int TracerPointUp::handle_event() +{ + TracerPoints &points = gui->plugin->config.points; + int sz = points.size(); + int hot_point = gui->point_list->get_selection_number(0, 0); + + if( sz > 1 && hot_point > 0 ) { + TracerPoint *&pt0 = points[hot_point]; + TracerPoint *&pt1 = points[--hot_point]; + TracerPoint *t = pt0; pt0 = pt1; pt1 = t; + gui->point_list->update(hot_point); + } + gui->send_configure_change(); + return 1; +} + +TracerPointDn::TracerPointDn(TracerWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Dn")) +{ + this->gui = gui; +} +TracerPointDn::~TracerPointDn() +{ +} + +int TracerPointDn::handle_event() +{ + TracerPoints &points = gui->plugin->config.points; + int sz = points.size(); + int hot_point = gui->point_list->get_selection_number(0, 0); + if( sz > 1 && hot_point < sz-1 ) { + TracerPoint *&pt0 = points[hot_point]; + TracerPoint *&pt1 = points[++hot_point]; + TracerPoint *t = pt0; pt0 = pt1; pt1 = t; + gui->point_list->update(hot_point); + } + gui->send_configure_change(); + return 1; +} + +TracerDrag::TracerDrag(TracerWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag")) +{ + this->gui = gui; +} +int TracerDrag::handle_event() +{ + CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui; + int value = get_value(); + if( value ) { + if( !gui->grab(cwindow_gui) ) { + update(value = 0); + flicker(10,50); + } + } + else + gui->ungrab(cwindow_gui); + gui->plugin->config.drag = value; + gui->send_configure_change(); + return 1; +} + +TracerDraw::TracerDraw(TracerWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.draw, _("Draw")) +{ + this->gui = gui; +} +int TracerDraw::handle_event() +{ + gui->plugin->config.draw = get_value(); + gui->send_configure_change(); + return 1; +} + +TracerFill::TracerFill(TracerWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.fill, _("Fill")) +{ + this->gui = gui; +} +int TracerFill::handle_event() +{ + gui->plugin->config.fill = get_value(); + gui->send_configure_change(); + return 1; +} + +TracerRadius::TracerRadius(TracerWindow *gui, int x, int y, int w) + : BC_ISlider(x,y,0,w,w, -50,50, gui->plugin->config.radius) +{ + this->gui = gui; +} +int TracerRadius::handle_event() +{ + gui->plugin->config.radius = get_value(); + gui->send_configure_change(); + return 1; +} + +TracerScale::TracerScale(TracerWindow *gui, int x, int y, int w) + : BC_FSlider(x,y, 0,w,w, 1.f,10.f, gui->plugin->config.scale) +{ + this->gui = gui; +} +int TracerScale::handle_event() +{ + gui->plugin->config.scale = get_value(); + gui->send_configure_change(); + return 1; +} + +TracerNewPoint::TracerNewPoint(TracerWindow *gui, Tracer *plugin, int x, int y) + : BC_GenericButton(x, y, 80, _("New")) +{ + this->gui = gui; + this->plugin = plugin; +} +TracerNewPoint::~TracerNewPoint() +{ +} +int TracerNewPoint::handle_event() +{ + int k = plugin->new_point(); + gui->point_list->update(k); + gui->send_configure_change(); + return 1; +} + +TracerDelPoint::TracerDelPoint(TracerWindow *gui, Tracer *plugin, int x, int y) + : BC_GenericButton(x, y, 80, C_("Del")) +{ + this->gui = gui; + this->plugin = plugin; +} +TracerDelPoint::~TracerDelPoint() +{ +} +int TracerDelPoint::handle_event() +{ + int hot_point = gui->point_list->get_selection_number(0, 0); + TracerPoints &points = plugin->config.points; + if( hot_point >= 0 && hot_point < points.size() ) { + plugin->config.del_point(hot_point); + if( !points.size() ) plugin->new_point(); + int sz = points.size(); + if( hot_point >= sz && hot_point > 0 ) --hot_point; + gui->point_list->update(hot_point); + gui->send_configure_change(); + } + return 1; +} + +TracerReset::TracerReset(TracerWindow *gui, Tracer *plugin, int x, int y) + : BC_GenericButton(x, y, _("Reset")) +{ + this->gui = gui; + this->plugin = plugin; +} +TracerReset::~TracerReset() +{ +} +int TracerReset::handle_event() +{ + TracerConfig &config = plugin->config; + config.drag = 0; + config.draw = 0; + config.fill = 0; + config.radius = 0; + config.scale = 1; + config.selected = 0; + TracerPoints &points = plugin->config.points; + points.remove_all_objects(); + plugin->new_point(); + gui->point_list->update(0); + gui->update_gui(); + gui->send_configure_change(); + return 1; +} + diff --git a/cinelerra-5.1/plugins/tracer/tracerwindow.h b/cinelerra-5.1/plugins/tracer/tracerwindow.h new file mode 100644 index 00000000..b6231cf7 --- /dev/null +++ b/cinelerra-5.1/plugins/tracer/tracerwindow.h @@ -0,0 +1,245 @@ +/* + * CINELERRA + * Copyright (C) 2008-2015 Adam Williams + * + * 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 + * + */ + +#ifndef __TRACERWINDOW_H__ +#define __TRACERWINDOW_H__ + +#include "guicast.h" + +class Tracer; +class TracerWindow; +class TracerNum; +class TracerPointX; +class TracerPointY; +class TracerDrag; +class TracerDraw; +class TracerFill; +class TracerRadius; +class TracerScale; +class TracerPointList; +class TracerNewPoint; +class TracerDelPoint; +class TracerPointUp; +class TracerPointDn; +class TracerReset; + + +class TracerNum : public BC_TumbleTextBox +{ +public: + TracerWindow *gui; + + TracerNum(TracerWindow *gui, int x, int y, float output); + ~TracerNum(); +}; +class TracerPointX : public TracerNum +{ +public: + TracerPointX(TracerWindow *gui, int x, int y, float output) + : TracerNum(gui, x, y, output) {} + ~TracerPointX() {} + + int handle_event(); +}; +class TracerPointY : public TracerNum +{ +public: + TracerPointY(TracerWindow *gui, int x, int y, float output) + : TracerNum(gui, x, y, output) {} + ~TracerPointY() {} + + int handle_event(); +}; + +class TracerThreshold : public BC_FSlider +{ +public: + TracerThreshold(TracerWindow *gui, int x, int y, int w); + int handle_event(); + int wheel_event(int v); + TracerWindow *gui; +}; + +class TracerDrag : public BC_CheckBox +{ +public: + TracerDrag(TracerWindow *gui, int x, int y); + + int handle_event(); + TracerWindow *gui; +}; + +class TracerDraw : public BC_CheckBox +{ +public: + TracerDraw(TracerWindow *gui, int x, int y); + + int handle_event(); + TracerWindow *gui; +}; + +class TracerFill : public BC_CheckBox +{ +public: + TracerFill(TracerWindow *gui, int x, int y); + + int handle_event(); + TracerWindow *gui; +}; + +class TracerRadius : public BC_ISlider +{ +public: + TracerRadius(TracerWindow *gui, int x, int y, int w); + + int handle_event(); + TracerWindow *gui; +}; + +class TracerScale : public BC_FSlider +{ +public: + TracerScale(TracerWindow *gui, int x, int y, int w); + + int handle_event(); + TracerWindow *gui; +}; + +class TracerPointList : public BC_ListBox +{ +public: + TracerPointList(TracerWindow *gui, Tracer *plugin, int x, int y); + ~TracerPointList(); + + int handle_event(); + int selection_changed(); + int column_resize_event(); + ArrayList cols[PT_SZ]; + void clear(); + void new_point(const char *xp, const char *yp); + void del_point(int i); + void set_point(int i, int c, float v); + void set_point(int i, int c, const char *cp); + int set_selected(int k); + void update(int k); + void update_list(int k); + + + TracerWindow *gui; + Tracer *plugin; + const char *titles[PT_SZ]; + int widths[PT_SZ]; +}; + +class TracerNewPoint : public BC_GenericButton +{ +public: + TracerNewPoint(TracerWindow *gui, Tracer *plugin, int x, int y); + ~TracerNewPoint(); + + int handle_event(); + + TracerWindow *gui; + Tracer *plugin; +}; + +class TracerDelPoint : public BC_GenericButton +{ +public: + TracerDelPoint(TracerWindow *gui, Tracer *plugin, int x, int y); + ~TracerDelPoint(); + + int handle_event(); + + Tracer *plugin; + TracerWindow *gui; +}; + +class TracerPointUp : public BC_GenericButton +{ +public: + TracerPointUp(TracerWindow *gui, int x, int y); + ~TracerPointUp(); + + int handle_event(); + + TracerWindow *gui; +}; + +class TracerPointDn : public BC_GenericButton +{ +public: + TracerPointDn(TracerWindow *gui, int x, int y); + ~TracerPointDn(); + + int handle_event(); + + TracerWindow *gui; +}; + +class TracerReset : public BC_GenericButton +{ +public: + TracerReset(TracerWindow *gui, Tracer *plugin, int x, int y); + ~TracerReset(); + + int handle_event(); + + Tracer *plugin; + TracerWindow *gui; +}; + + +class TracerWindow : public PluginClientWindow +{ +public: + TracerWindow(Tracer *plugin); + ~TracerWindow(); + + void create_objects(); + void update_gui(); + void start_color_thread(); + int grab_event(XEvent *event); + int do_grab_event(XEvent *event); + void done_event(int result); + void send_configure_change(); + + Tracer *plugin; + BC_Title *title_x, *title_y; + TracerPointX *point_x; + TracerPointY *point_y; + TracerNewPoint *new_point; + TracerDelPoint *del_point; + TracerPointUp *point_up; + TracerPointDn *point_dn; + int dragging, pending_config; + float last_x, last_y; + TracerDrag *drag; + TracerDraw *draw; + TracerFill *fill; + BC_Title *title_r, *title_s; + TracerRadius *radius; + TracerScale *scale; + TracerPointList *point_list; + TracerReset *reset; +}; + +#endif + diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.1.patch6 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.1.patch6 new file mode 100644 index 00000000..b4a5c3fb --- /dev/null +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.1.patch6 @@ -0,0 +1,11 @@ +diff -u a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c +--- a/libavcodec/vdpau_mpeg12.c 2018-11-02 18:17:29.000000000 -0600 ++++ b/libavcodec/vdpau_mpeg12.c 2019-04-22 10:28:41.762275864 -0600 +@@ -114,6 +114,7 @@ + .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_mpeg1_init, + .uninit = ff_vdpau_common_uninit, ++ .frame_params = ff_vdpau_common_frame_params, + .priv_data_size = sizeof(VDPAUContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, + };