Credit Andrew - updating patches for FFmpeg 7.0 as needed since 6.1, now at 7.0,...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / pluginfclient.C
index 03ad7e25df9f1e7e8cbe51f310a8c9a45a9e36a5..b8694b120e29ca26a36adde2e701094d99b86070 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2016-2020 William Morrow
+ *
+ * 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 <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -8,6 +28,7 @@
 #include "bcwindowbase.h"
 #include "bctitle.h"
 #include "cstrdup.h"
 #include "bcwindowbase.h"
 #include "bctitle.h"
 #include "cstrdup.h"
+#include "keys.h"
 #include "language.h"
 #include "mwindow.h"
 #include "pluginfclient.h"
 #include "language.h"
 #include "mwindow.h"
 #include "pluginfclient.h"
@@ -16,6 +37,8 @@
 #include "vframe.h"
 #include "filexml.h"
 
 #include "vframe.h"
 #include "filexml.h"
 
+#include "libavfilter/version.h"
+
 #ifdef FFMPEG3
 #define av_filter_iterate(p) ((*(const AVFilter**)(p))=avfilter_next(*(const AVFilter **)(p)))
 #endif
 #ifdef FFMPEG3
 #define av_filter_iterate(p) ((*(const AVFilter**)(p))=avfilter_next(*(const AVFilter **)(p)))
 #endif
@@ -186,6 +209,10 @@ PluginFClientText::
 
 int PluginFClientText::handle_event()
 {
 
 int PluginFClientText::handle_event()
 {
+       if( get_keypress() == RETURN ) {
+               fwin->update();
+               activate();
+       }
        return 0;
 }
 
        return 0;
 }
 
@@ -426,7 +453,7 @@ int PluginFClient_Opt::types(char *rp)
        case AV_OPT_TYPE_SAMPLE_FMT: cp = "<sample_fmt>"; break;
        case AV_OPT_TYPE_DURATION: cp = "<duration>"; break;
        case AV_OPT_TYPE_COLOR: cp = "<color>"; break;
        case AV_OPT_TYPE_SAMPLE_FMT: cp = "<sample_fmt>"; break;
        case AV_OPT_TYPE_DURATION: cp = "<duration>"; break;
        case AV_OPT_TYPE_COLOR: cp = "<color>"; break;
-       case AV_OPT_TYPE_CHANNEL_LAYOUT: cp = "<channel_layout>";  break;
+       case AV_OPT_TYPE_CHLAYOUT: cp = "<channel_layout>";  break;
        default: cp = "<undef>";  break;
        }
        return sprintf(rp, "%s", cp);
        default: cp = "<undef>";  break;
        }
        return sprintf(rp, "%s", cp);
@@ -637,11 +664,19 @@ PluginFClient::~PluginFClient()
 bool PluginFClient::is_audio(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
 bool PluginFClient::is_audio(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
+#if LIBAVFILTER_VERSION_MAJOR > 8
+       if( avfilter_filter_pad_count(fp, 1) > 1 ) return 0;
+#else
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
+#endif
        if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
        if( !fp->inputs ) return 1;
        if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
        if( !fp->inputs ) return 1;
+#if  LIBAVFILTER_VERSION_MAJOR > 8
+       if( avfilter_filter_pad_count(fp, 0) > 1 ) return 0;
+#else
        if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
        if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
+#endif
        if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
        return 1;
        if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
        return 1;
@@ -649,11 +684,19 @@ bool PluginFClient::is_audio(const AVFilter *fp)
 bool PluginFClient::is_video(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
 bool PluginFClient::is_video(const AVFilter *fp)
 {
        if( !fp->outputs ) return 0;
+#if  LIBAVFILTER_VERSION_MAJOR > 8 
+       if( avfilter_filter_pad_count(fp, 1) > 1 ) return 0;
+#else
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
        if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
+#endif
        if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
        if( !fp->inputs ) return 1;
        if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
        if( !fp->inputs ) return 1;
+#if  LIBAVFILTER_VERSION_MAJOR > 8
+       if( avfilter_filter_pad_count(fp, 0) > 1 ) return 0;
+#else
        if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
        if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
+#endif
        if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
        return 1;
        if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
        if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
        return 1;
@@ -802,16 +845,24 @@ int PluginFAClient::activate()
        }
        AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
        int channels = PluginClient::total_in_buffers;
        }
        AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
        int channels = PluginClient::total_in_buffers;
-       uint64_t layout = (((uint64_t)1)<<channels) - 1;
+       //uint64_t layout = (((uint64_t)1)<<channels) - 1;
+       AVChannelLayout layout;
+       
+       av_channel_layout_default(&layout, channels);
+       
+       char chLayoutDescription[128];
+       av_channel_layout_describe(&layout, chLayoutDescription, sizeof(chLayoutDescription));
+    
        AVFilterGraph *graph = !ffilt ? 0 : ffilt->graph;
        int ret = !graph ? -1 : 0;
        if( ret >= 0 && ffilt->filter->inputs ) {
                char args[BCTEXTLEN];
                snprintf(args, sizeof(args),
        AVFilterGraph *graph = !ffilt ? 0 : ffilt->graph;
        int ret = !graph ? -1 : 0;
        if( ret >= 0 && ffilt->filter->inputs ) {
                char args[BCTEXTLEN];
                snprintf(args, sizeof(args),
-                       "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%jx",
-                       1, sample_rate, sample_rate, av_get_sample_fmt_name(sample_fmt), layout);
+                       "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s:channels=%i",
+                       1, sample_rate, sample_rate, av_get_sample_fmt_name(sample_fmt), chLayoutDescription, channels);
                ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("abuffer"),
                        "in", args, NULL, graph);
                ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("abuffer"),
                        "in", args, NULL, graph);
+               if(ret <0) printf("abuffer failed!\n");
        }
        if( ret >= 0 )
                ret = avfilter_graph_create_filter(&fsink, avfilter_get_by_name("abuffersink"),
        }
        if( ret >= 0 )
                ret = avfilter_graph_create_filter(&fsink, avfilter_get_by_name("abuffersink"),
@@ -820,8 +871,8 @@ int PluginFAClient::activate()
                ret = av_opt_set_bin(fsink, "sample_fmts",
                        (uint8_t*)&sample_fmt, sizeof(sample_fmt), AV_OPT_SEARCH_CHILDREN);
        if( ret >= 0 )
                ret = av_opt_set_bin(fsink, "sample_fmts",
                        (uint8_t*)&sample_fmt, sizeof(sample_fmt), AV_OPT_SEARCH_CHILDREN);
        if( ret >= 0 )
-               ret = av_opt_set_bin(fsink, "channel_layouts",
-                       (uint8_t*)&layout, sizeof(layout), AV_OPT_SEARCH_CHILDREN);
+               ret = av_opt_set(fsink, "ch_layouts",
+                       chLayoutDescription, AV_OPT_SEARCH_CHILDREN);
        if( ret >= 0 )
                ret = av_opt_set_bin(fsink, "sample_rates",
                        (uint8_t*)&sample_rate, sizeof(sample_rate), AV_OPT_SEARCH_CHILDREN);
        if( ret >= 0 )
                ret = av_opt_set_bin(fsink, "sample_rates",
                        (uint8_t*)&sample_rate, sizeof(sample_rate), AV_OPT_SEARCH_CHILDREN);
@@ -840,7 +891,8 @@ static AVRational best_frame_rate(double frame_rate)
        static const int m1 = 1001*12, m2 = 1000*12;
        static const int freqs[] = {
                40*m1, 48*m1, 50*m1, 60*m1, 80*m1,120*m1, 240*m1,
        static const int m1 = 1001*12, m2 = 1000*12;
        static const int freqs[] = {
                40*m1, 48*m1, 50*m1, 60*m1, 80*m1,120*m1, 240*m1,
-               24*m2, 30*m2, 60*m2, 12*m2, 15*m2, 48*m2, 0,
+               24*m2, 30*m2, 60*m2, 12*m2, 15*m2, 48*m2, 90*m2,
+               100*m2, 120*m2, 144*m2, 72*m2, 0,
        };
        double max_err = 1.;
        int freq, best_freq = 0;
        };
        double max_err = 1.;
        int freq, best_freq = 0;
@@ -884,7 +936,7 @@ int PluginFVClient::activate(int width, int height, int color_model)
                char args[BCTEXTLEN];
                snprintf(args, sizeof(args),
                        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
                char args[BCTEXTLEN];
                snprintf(args, sizeof(args),
                        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
-                       width, height, pix_fmt, best_rate.num, best_rate.den, aspect_w, aspect_h);
+                       width, height, pix_fmt, best_rate.den, best_rate.num, aspect_w, aspect_h);
                ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("buffer"),
                        "in", args, NULL, graph);
        }
                ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("buffer"),
                        "in", args, NULL, graph);
        }
@@ -907,14 +959,22 @@ int PluginFAClient::get_inchannels()
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_inputs ? 0 : fctx->inputs;
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_inputs ? 0 : fctx->inputs;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59,24,100)
+       return !links ? 0 : links[0]->ch_layout.nb_channels;
+#else
        return !links ? 0 : links[0]->channels;
        return !links ? 0 : links[0]->channels;
+#endif
 }
 
 int PluginFAClient::get_outchannels()
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_outputs ? 0 : fctx->outputs;
 }
 
 int PluginFAClient::get_outchannels()
 {
        AVFilterContext *fctx = ffilt->fctx;
        AVFilterLink **links = !fctx->nb_outputs ? 0 : fctx->outputs;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59,24,100)
+       return !links ? 0 : links[0]->ch_layout.nb_channels;
+#else
        return !links ? 0 : links[0]->channels;
        return !links ? 0 : links[0]->channels;
+#endif
 }
 
 int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate)
 }
 
 int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate)
@@ -938,11 +998,21 @@ int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start
        if( ret >= 0 ) {
                in_channels = get_inchannels();
                out_channels = get_outchannels();
        if( ret >= 0 ) {
                in_channels = get_inchannels();
                out_channels = get_outchannels();
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59,24,100)
+               AVChannelLayout in_ch_layout;
+               AVFilterContext *fctx = ffilt->fctx;
+               AVFilterLink **links = !fctx->nb_outputs ? 0 : fctx->outputs;
+               av_channel_layout_copy(&in_ch_layout, &links[0]->ch_layout);
+#endif
                frame->nb_samples = size;
                frame->format = AV_SAMPLE_FMT_FLTP;
                frame->nb_samples = size;
                frame->format = AV_SAMPLE_FMT_FLTP;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61,3,100)
+               av_channel_layout_copy(&frame->ch_layout, &in_ch_layout);
+#else
                frame->channel_layout = (1<<in_channels)-1;
                frame->channel_layout = (1<<in_channels)-1;
+#endif
                frame->sample_rate = sample_rate;
                frame->sample_rate = sample_rate;
-               frame->pts = local_to_edl(filter_position);
+               frame->pts = filter_position;
        }
 
        int retry = 10;
        }
 
        int retry = 10;
@@ -1002,7 +1072,9 @@ int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start
 
 
 PluginFVClient::PluginFVClient(PluginServer *server, const char *name)
 
 
 PluginFVClient::PluginFVClient(PluginServer *server, const char *name)
- : PluginVClient(server), PluginFClient(this, name)
+ : PluginVClient(server),
+   PluginFClient(this, name),
+   FFVideoConvert(server->preferences)
 {
 }
 
 {
 }
 
@@ -1041,11 +1113,11 @@ 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; }
                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, 0);
+               read_frame(vframe, 0, filter_position, frame_rate, 0);
                frame->format = pix_fmt;
                frame->width  = width;
                frame->height = height;
                frame->format = pix_fmt;
                frame->width  = width;
                frame->height = height;
-               frame->pts = local_to_edl(position);
+               frame->pts = filter_position++;
                ret = av_frame_get_buffer(frame, 32);
                if( ret < 0 ) break;
                ret = transfer_pixfmt(vframe, frame);
                ret = av_frame_get_buffer(frame, 32);
                if( ret < 0 ) break;
                ret = transfer_pixfmt(vframe, frame);