add lv2 plugin interface
[goodguy/history.git] / cinelerra-5.1 / cinelerra / pluginfclient.C
index 1bea7dd04ba1564c7fbbdfd748409e9c15f604c6..114d64e547d4559280abfa246c7936ae6da6306b 100644 (file)
@@ -68,7 +68,7 @@ void PluginFClientConfig::copy_from(PluginFClientConfig &that)
        }
 }
 
-void PluginFClientConfig::interpolate(PluginFClientConfig &prev, PluginFClientConfig &next, 
+void PluginFClientConfig::interpolate(PluginFClientConfig &prev, PluginFClientConfig &next,
        int64_t prev_frame, int64_t next_frame, int64_t current_frame)
 {
        copy_from(prev);
@@ -76,6 +76,7 @@ void PluginFClientConfig::interpolate(PluginFClientConfig &prev, PluginFClientCo
 
 void PluginFClientConfig::initialize(const char *name)
 {
+       delete ffilt;
        ffilt = PluginFFilter::new_ffilter(name);
        const AVOption *opt = 0;
        void *obj = ffilt->filter_config();
@@ -100,6 +101,13 @@ void PluginFClientConfig::initialize(const char *name)
                        append(fopt);
                }
        }
+       if( (ffilt->filter->flags & AVFILTER_FLAG_SLICE_THREADS) != 0 ) {
+               opt = av_opt_find(ffilt->fctx, "threads", NULL, 0, 0);
+               if( opt ) {
+                       PluginFClient_Opt *fopt = new PluginFClient_Opt(this, opt);
+                       append(fopt);
+               }
+       }
 }
 
 int PluginFClientConfig::update()
@@ -154,7 +162,7 @@ PluginFClientReset::
 
 int PluginFClientReset::handle_event()
 {
-       av_opt_set_defaults(fwin->ffmpeg->config.filter_config());
+       fwin->ffmpeg->config.initialize(fwin->ffmpeg->name);
        if( fwin->ffmpeg->config.update() > 0 )
                fwin->draw();
        fwin->ffmpeg->plugin->send_configure_change();
@@ -271,7 +279,7 @@ void PluginFClientWindow::update(PluginFClient_Opt *opt)
        *(sp=str) = 0;
        if( opt ) opt->ranges(sp);
        range->update(str);
-       while( units->total_items() ) units->remove_item(0);
+       while( units->total_items() ) units->del_item(0);
        ArrayList<const AVOption *> opts;
        int n = !opt ? 0 : opt->units(opts);
        for( int i=0; i<n; ++i )
@@ -397,7 +405,7 @@ int PluginFClient_Opt::units(ArrayList<const AVOption *> &opts)
                        if( strlen(opts[i]->name) < strlen(opt->name) ) opts[i] = opt;
                        break;
                }
-               if( i < 0 ) 
+               if( i < 0 )
                        opts.append(opt);
        }
        return opts.size();
@@ -524,7 +532,7 @@ PluginFClient::~PluginFClient()
        delete ffilt;
 }
 
-bool PluginFClient::is_audio(AVFilter *fp)
+bool PluginFClient::is_audio(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
@@ -536,7 +544,7 @@ bool PluginFClient::is_audio(AVFilter *fp)
        if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
        return 1;
 }
-bool PluginFClient::is_video(AVFilter *fp)
+bool PluginFClient::is_video(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
@@ -615,6 +623,13 @@ void PluginFClient::save_data(KeyFrame *keyframe)
                        av_freep(&buf);
                }
        }
+       if( (config.ffilt->filter->flags & AVFILTER_FLAG_SLICE_THREADS) != 0 ) {
+               uint8_t *buf = 0;
+               if( av_opt_get(config.ffilt->fctx, "threads", 0, &buf) >= 0 && buf ) {
+                       output.tag.set_property("threads", (const char *)buf);
+                       av_freep(&buf);
+               }
+       }
 
        output.append_tag();
        output.terminate_string();
@@ -623,7 +638,7 @@ void PluginFClient::save_data(KeyFrame *keyframe)
 void PluginFClient::read_data(KeyFrame *keyframe)
 {
        FileXML input;
-       char string[BCTEXTLEN], value[BCTEXTLEN];
+       char string[BCTEXTLEN];
        input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
 
        while( !input.read_tag() ) {
@@ -634,9 +649,12 @@ void PluginFClient::read_data(KeyFrame *keyframe)
                        void *obj = config.filter_config();
                        const AVOption *opt = NULL;
                        while( (opt=av_opt_next(obj, opt)) != 0 ) {
-                               to_upper(string, opt->name);
-                               if( !input.tag.get_property(string, value) ) continue;
-                               av_opt_set(obj, opt->name, value, 0);
+                               const char *v = input.tag.get_property(opt->name);
+                               if( v ) av_opt_set(obj, opt->name, v, 0);
+                       }
+                       if( (config.ffilt->filter->flags & AVFILTER_FLAG_SLICE_THREADS) != 0 ) {
+                               const char *v = input.tag.get_property("threads");
+                               if( v ) av_opt_set(config.ffilt->fctx, "threads", v, 0);
                        }
                }
        }
@@ -787,14 +805,14 @@ int PluginFAClient::get_inchannels()
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_inputs ? 0 : fctx->inputs;
-       return !links ? 0 : avfilter_link_get_channels(links[0]);
+       return !links ? 0 : links[0]->channels;
 }
 
 int PluginFAClient::get_outchannels()
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_outputs ? 0 : fctx->outputs;
-       return !links ? 0 : avfilter_link_get_channels(links[0]);
+       return !links ? 0 : links[0]->channels;
 }
 
 int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate)
@@ -818,6 +836,11 @@ int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start
        if( ret >= 0 ) {
                in_channels = get_inchannels();
                out_channels = get_outchannels();
+               frame->nb_samples = size;
+               frame->format = AV_SAMPLE_FMT_FLTP;
+               frame->channel_layout = (1<<in_channels)-1;
+               frame->sample_rate = sample_rate;
+               frame->pts = local_to_edl(filter_position);
        }
 
        int retry = 10;
@@ -828,11 +851,6 @@ int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start
                for( int i=0; i<total_in; ++i )
                        read_samples(buffer[i], i, sample_rate, filter_position, size);
                filter_position += size;
-               frame->nb_samples = size;
-               frame->format = AV_SAMPLE_FMT_FLTP;
-               frame->channel_layout = (1<<in_channels)-1;
-               frame->sample_rate = sample_rate;
-               frame->pts = local_to_edl(filter_position);
                ret = av_frame_get_buffer(frame, 0);
                if( ret < 0 ) break;
                float **in_buffers = (float **)&frame->extended_data[0];
@@ -909,7 +927,7 @@ int PluginFVClient::process_buffer(VFrame **frames, int64_t position, double fra
                color_model_to_pix_fmt(colormodel);
        if( pix_fmt <= AV_PIX_FMT_NONE || pix_fmt >= AV_PIX_FMT_NB )
                pix_fmt = AV_PIX_FMT_RGBA;
-               
+
        AVFrame *frame = 0;
        if( ret >= 0 && !(frame = av_frame_alloc()) ) {
                fprintf(stderr, "PluginFVClient::process_buffer: av_frame_alloc failed\n");
@@ -921,14 +939,14 @@ int PluginFVClient::process_buffer(VFrame **frames, int64_t position, double fra
                ret = av_buffersink_get_frame(fsink, frame);
                if( ret >= 0 || ret != AVERROR(EAGAIN) ) break;
                if( !fsrc ) { ret = AVERROR(EIO);  break; }
-               read_frame(vframe, 0, filter_position++, frame_rate, get_use_opengl());
+               read_frame(vframe, 0, filter_position++, frame_rate, 0);
                frame->format = pix_fmt;
                frame->width  = width;
                frame->height = height;
                frame->pts = local_to_edl(position);
                ret = av_frame_get_buffer(frame, 32);
                if( ret < 0 ) break;
-               ret = transfer_pixfmt(vframe, frame, pix_fmt, width, height);
+               ret = transfer_pixfmt(vframe, frame);
                if( ret < 0 ) break;
                ret = av_buffersrc_add_frame_flags(fsrc, frame, 0);
        }
@@ -937,7 +955,7 @@ int PluginFVClient::process_buffer(VFrame **frames, int64_t position, double fra
 
        if( ret >= 0 ) {
                pix_fmt = (AVPixelFormat) frame->format;
-               ret = transfer_cmodel(vframe, frame, pix_fmt, width, height);
+               ret = transfer_cmodel(vframe, frame);
        }
        if( ret < 0 ) {
                ff_err(ret, "PluginFVClient::process_buffer() %s\n", plugin_title());
@@ -984,23 +1002,35 @@ PluginFClient_Opt::~PluginFClient_Opt()
        delete item_value;
 }
 
-char *PluginFClient_Opt::get(char *vp, int sz)
+const char *PluginFClientConfig::get(const char *name)
 {
-       char *ret = 0;
-       void *obj = filter_config();
        uint8_t *bp = 0;
-       if( av_opt_get(obj, opt->name, 0, &bp) >= 0 && bp != 0 ) {
-               const char *val = (const char *)bp;
-               ret = sz >= 0 ? strncpy(vp,val,sz) : strcpy(vp, val);
-               if( sz > 0 ) vp[sz-1] = 0;
-               av_freep(&bp);
+       if( av_opt_get(filter_config(), name, 0, &bp) >= 0 ||
+           av_opt_get(ffilt->fctx, name, 0, &bp) >= 0 )
+               return (const char *)bp;
+       return 0;
+}
+char *PluginFClient_Opt::get(char *vp, int sz)
+{
+       const char *val = conf->get(opt->name);
+       if( val ) {
+               strncpy(vp, val, sz);
+               vp[sz-1] = 0;
        }
-       return ret;
+       else
+               vp = 0;
+       av_freep(&val);
+       return vp;
+}
+
+void PluginFClientConfig::set(const char *name, const char *val)
+{
+       if( av_opt_set(filter_config(), name, val, 0) < 0 )
+               av_opt_set(ffilt->fctx, name, val, 0);
 }
 void PluginFClient_Opt::set(const char *val)
 {
-       void *obj = filter_config();
-       av_opt_set(obj , opt->name, val, 0);
+       conf->set(opt->name, val);
 }
 
 void PluginFFilter::uninit()
@@ -1015,13 +1045,14 @@ static int get_defaults(const char *name, char *args)
        FILE *fp = fopen(defaults_path,"r");
        if( !fp ) return 0;
        char ff_plugin[BCSTRLEN], ff_args[BCTEXTLEN], *ap = 0;
-       while( !ap && fgets(ff_args, sizeof(ff_args), fp) ) {
-               if( *(ap=ff_args) == ';' ) continue;
-               if( *(ap=ff_args) == '#' ) ++ap;
+       while( fgets(ff_args, sizeof(ff_args), fp) ) {
+               char *cp = ff_args;
+               if( *cp == ';' ) continue;
+               if( *cp == '#' ) ++cp;
                char *bp = ff_plugin, *ep = bp + sizeof(ff_plugin)-1;
-               while( bp < ep && *ap && *ap != '\n' && *ap != ' ' ) *bp++ = *ap++;
+               while( bp < ep && *cp && *cp != '\n' && *cp != ' ' ) *bp++ = *cp++;
                *bp = 0;
-               if( strcmp(ff_plugin, name) ) ap = 0;
+               if( !strcmp(ff_plugin, name) ) { ap = cp;  break; }
        }
        fclose(fp);
        if( !ap ) return 0;
@@ -1058,17 +1089,33 @@ int PluginFFilter::init(const char *name, PluginFClientConfig *conf)
        static int inst = 0;
        char inst_name[BCSTRLEN];
        sprintf(inst_name,"%s_%d", name, ++inst);
-       graph->thread_type = 0;
-       graph->nb_threads  = 1;
+       if( conf && (filter->flags & AVFILTER_FLAG_SLICE_THREADS) != 0 ) {
+               graph->thread_type = AVFILTER_THREAD_SLICE;
+               graph->nb_threads  = atoi(conf->get("threads"));
+       }
+       else {
+               graph->thread_type = 0;
+               graph->nb_threads  = 0;
+       }
        fctx = avfilter_graph_alloc_filter(graph, filter, inst_name);
        if( !fctx ) return AVERROR(ENOMEM);
+       fctx->thread_type = graph->thread_type; // bug in avfilter
        if( conf ) {
                AVDictionary *opts = 0;
                for( int i=0; i<conf->size(); ++i ) {
                        PluginFClient_Opt *op = conf->get(i);
                        const char *name = op->opt->name;
                        char val[BCTEXTLEN], *vp = op->get(val, sizeof(val));
-                       if( vp ) av_dict_set(&opts, name, vp, 0);
+                       if( !vp ) continue;
+                       uint8_t *bp = 0;
+// unspecified opts cause a special behavior in some filters (lut3d)
+// so... if opt value is the default, skip it or no special behavior
+                       if( av_opt_get(filter_config(), name, 0, &bp) >= 0 ) {
+                               int result = strcmp((const char *)bp, vp);
+                               av_freep(&bp);
+                               if( !result ) continue;
+                       }
+                       av_dict_set(&opts, name, vp, 0);
                }
                ret = avfilter_init_dict(fctx, &opts);
                av_dict_free(&opts);
@@ -1104,7 +1151,7 @@ PluginFFilter *PluginFFilter::new_ffilter(const char *name, PluginFClientConfig
 
 PluginClient *PluginServer::new_ffmpeg_plugin()
 {
-       AVFilter *filter = avfilter_get_by_name(ff_name);
+       const AVFilter *filter = avfilter_get_by_name(ff_name);
        if( !filter ) return 0;
        PluginFClient *ffmpeg =
                PluginFClient::is_audio(filter) ?
@@ -1122,14 +1169,15 @@ PluginServer* MWindow::new_ffmpeg_server(MWindow *mwindow, const char *name)
        PluginFFilter *ffilt = PluginFFilter::new_ffilter(name);
        if( !ffilt ) return 0;
        delete ffilt;
-       return new PluginServer(mwindow, (char*)name, PLUGIN_TYPE_FFMPEG);
+       return new PluginServer(mwindow, name, PLUGIN_TYPE_FFMPEG);
 }
 
 void MWindow::init_ffmpeg_index(MWindow *mwindow, Preferences *preferences, FILE *fp)
 {
        PluginFLogLevel errs(AV_LOG_ERROR);
-       const AVFilter *filter = 0;
-       while( (filter=avfilter_next(filter)) != 0 ) {
+       const AVFilter *filter = 0;  void *idx = 0;
+       while( (filter=av_filter_iterate(&idx)) != 0 ) {
+//printf("%s\n",filter->name);
                PluginServer *server = new_ffmpeg_server(mwindow, filter->name);
                if( server ) {
                        int result = server->open_plugin(1, preferences, 0, 0);
@@ -1145,7 +1193,5 @@ void MWindow::init_ffmpeg_index(MWindow *mwindow, Preferences *preferences, FILE
 
 void MWindow::init_ffmpeg()
 {
-       av_register_all();
-       avfilter_register_all();
 }