upgrade to ffmpeg-4.0, findobj upgrades, rework plugin visibility
authorGood Guy <[email protected]>
Wed, 25 Apr 2018 23:08:30 +0000 (17:08 -0600)
committerGood Guy <[email protected]>
Wed, 25 Apr 2018 23:08:30 +0000 (17:08 -0600)
29 files changed:
cinelerra-5.1/bld.sh
cinelerra-5.1/cinelerra/bdwrite.C
cinelerra-5.1/cinelerra/dragcheckbox.C
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/fileac3.C
cinelerra-5.1/cinelerra/fileffmpeg.C
cinelerra-5.1/cinelerra/pluginfclient.C
cinelerra-5.1/cinelerra/pluginfclient.h
cinelerra-5.1/configure.ac
cinelerra-5.1/ffmpeg/plugin.opts
cinelerra-5.1/plugin_defs
cinelerra-5.1/plugins/findobj/findobj.C
cinelerra-5.1/plugins/findobj/findobj.h
cinelerra-5.1/plugins/findobj/findobjwindow.C
cinelerra-5.1/plugins/findobj/findobjwindow.h
cinelerra-5.1/thirdparty/Makefile
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch1 [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch2 [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch3 [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch4 [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch5 [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch1 [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch2 [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch3 [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/ffmpeg-4.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/ffmpeg.git.patch1
cinelerra-5.1/thirdparty/src/ffmpeg.git.patch2
cinelerra-5.1/thirdparty/src/ffmpeg.git.patch3

index a9b6e46c5d5bc7ae36510d3de26621b43f3de2fa..d0f8b71b0b36879b1910ad30d21f557c143d8170 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 ./autogen.sh
-./configure --with-single-user
+./configure --with-single-user --with-opencv=sta,tar=http://192.168.1.8/opencv-20180401.tgz
 make 2>&1 | tee log
 make install
 mv Makefile Makefile.cfg
index 5ce6a8be5aac15cbeb5c729f106720e393301c41..6a2b4ca3cb4b9bcec54d7b8620a74b51cafd7395 100644 (file)
@@ -3139,7 +3139,6 @@ main(int ac, char **av)
 {
   char *path = av[1];
   if( mkbdmv(path) ) return 1;
-  av_register_all();
   av_log_set_level(AV_LOG_FATAL);
   //av_log_set_level(AV_LOG_VERBOSE);
   //av_log_set_level(AV_LOG_DEBUG);
index c38963997c96a100988a8092784d17488022dd63..8db8ac35953e37985657630f02f0fbd838da239f 100644 (file)
@@ -288,5 +288,6 @@ void DragCheckBox::draw_boundary(VFrame *out,
                out->draw_line(x2,y2-r, x2-r,y2);
                out->draw_line(x0,y2-r, x0+r,y2);
        }
+       out->set_stiple(0);
 }
 
index 2ed6c4a5316878ef7091c22fc92fadcb530e0a24..ac85cccde78fd3e12d881517040888835ea56734 100644 (file)
@@ -322,7 +322,7 @@ int FFStream::decode_activate()
                int ret = 0;
                // this should be avformat_copy_context(), but no copy avail
                ret = avformat_open_input(&fmt_ctx,
-                       ffmpeg->fmt_ctx->filename, ffmpeg->fmt_ctx->iformat, &copts);
+                       ffmpeg->fmt_ctx->url, ffmpeg->fmt_ctx->iformat, &copts);
                if( ret >= 0 ) {
                        ret = avformat_find_stream_info(fmt_ctx, 0);
                        st = fmt_ctx->streams[fidx];
@@ -337,9 +337,6 @@ int FFStream::decode_activate()
                                ret = AVERROR(ENOMEM);
                        }
                        if( ret >= 0 ) {
-                               av_codec_set_pkt_timebase(avctx, st->time_base);
-                               if( decoder->capabilities & AV_CODEC_CAP_DR1 )
-                                       avctx->flags |= CODEC_FLAG_EMU_EDGE;
                                avcodec_parameters_to_context(avctx, st->codecpar);
                                if( !av_dict_get(copts, "threads", NULL, 0) )
                                        avctx->thread_count = ffmpeg->ff_cpus();
@@ -762,7 +759,7 @@ int FFAudioStream::decode_frame(AVFrame *frame)
                ff_err(ret, "FFAudioStream::decode_frame: Could not read audio frame\n");
                return -1;
        }
-       int64_t pkt_ts = av_frame_get_best_effort_timestamp(frame);
+       int64_t pkt_ts = frame->best_effort_timestamp;
        if( pkt_ts != AV_NOPTS_VALUE )
                curr_pos = ffmpeg->to_secs(pkt_ts - nudge, st->time_base) * sample_rate + 0.5;
        return 1;
@@ -772,7 +769,7 @@ int FFAudioStream::encode_activate()
 {
        if( writing >= 0 ) return writing;
        if( !avctx->codec ) return writing = 0;
-       frame_sz = avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE ?
+       frame_sz = avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE ?
                10000 : avctx->frame_size;
        return FFStream::encode_activate();
 }
@@ -936,7 +933,7 @@ int FFVideoStream::decode_frame(AVFrame *frame)
                ff_err(ret, "FFVideoStream::decode_frame: Could not read video frame\n");
                return -1;
        }
-       int64_t pkt_ts = av_frame_get_best_effort_timestamp(frame);
+       int64_t pkt_ts = frame->best_effort_timestamp;
        if( pkt_ts != AV_NOPTS_VALUE )
                curr_pos = ffmpeg->to_secs(pkt_ts - nudge, st->time_base) * frame_rate + 0.5;
        return 1;
@@ -1174,7 +1171,7 @@ int FFVideoConvert::transfer_cmodel(VFrame *frame, AVFrame *ifp)
 {
        int ret = convert_cmodel(frame, ifp);
        if( ret > 0 ) {
-               const AVDictionary *src = av_frame_get_metadata(ifp);
+               const AVDictionary *src = ifp->metadata;
                AVDictionaryEntry *t = NULL;
                BC_Hash *hp = frame->get_params();
                //hp->clear();
@@ -1271,7 +1268,7 @@ int FFVideoConvert::transfer_pixfmt(VFrame *frame, AVFrame *ofp)
        int ret = convert_pixfmt(frame, ofp);
        if( ret > 0 ) {
                BC_Hash *hp = frame->get_params();
-               AVDictionary **dict = avpriv_frame_get_metadatap(ofp);
+               AVDictionary **dict = &ofp->metadata;
                //av_dict_free(dict);
                for( int i=0; i<hp->size(); ++i ) {
                        char *key = hp->get_key(i), *val = hp->get_value(i);
@@ -1928,7 +1925,6 @@ int FFMPEG::info(char *text, int len)
 int FFMPEG::init_decoder(const char *filename)
 {
        ff_lock("FFMPEG::init_decoder");
-       av_register_all();
        char file_opts[BCTEXTLEN];
        char *bp = strrchr(strcpy(file_opts, filename), '/');
        char *sp = strrchr(!bp ? file_opts : bp, '.');
@@ -1965,8 +1961,8 @@ int FFMPEG::init_decoder(const char *filename)
 int FFMPEG::open_decoder()
 {
        struct stat st;
-       if( stat(fmt_ctx->filename, &st) < 0 ) {
-               eprintf(_("can't stat file: %s\n"), fmt_ctx->filename);
+       if( stat(fmt_ctx->url, &st) < 0 ) {
+               eprintf(_("can't stat file: %s\n"), fmt_ctx->url);
                return 1;
        }
 
@@ -2074,7 +2070,6 @@ int FFMPEG::init_encoder(const char *filename)
                return 1;
        }
        ff_lock("FFMPEG::init_encoder");
-       av_register_all();
        char format[BCSTRLEN];
        if( get_format(format, "format", file_format) )
                strcpy(format, file_format);
@@ -2164,7 +2159,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                                ctx->qmin    = ctx->qmax =  asset->ff_audio_quality;
                                ctx->mb_lmin = ctx->qmin * FF_QP2LAMBDA;
                                ctx->mb_lmax = ctx->qmax * FF_QP2LAMBDA;
-                               ctx->flags |= CODEC_FLAG_QSCALE;
+                               ctx->flags |= AV_CODEC_FLAG_QSCALE;
                                char arg[BCSTRLEN];
                                av_dict_set(&sopts, "flags", "+qscale", 0);
                                sprintf(arg, "%d", asset->ff_audio_quality);
@@ -2224,7 +2219,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                                ctx->qmin    = ctx->qmax =  asset->ff_video_quality;
                                ctx->mb_lmin = ctx->qmin * FF_QP2LAMBDA;
                                ctx->mb_lmax = ctx->qmax * FF_QP2LAMBDA;
-                               ctx->flags |= CODEC_FLAG_QSCALE;
+                               ctx->flags |= AV_CODEC_FLAG_QSCALE;
                                char arg[BCSTRLEN];
                                av_dict_set(&sopts, "flags", "+qscale", 0);
                                sprintf(arg, "%d", asset->ff_video_quality);
@@ -2305,7 +2300,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
        }
        if( !ret ) {
                if( fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER )
-                       ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+                       ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
                if( fst->stats_filename && (ret=fst->init_stats_file()) )
                        eprintf(_("error: stats file = %s\n"), fst->stats_filename);
        }
@@ -2474,9 +2469,9 @@ int FFMPEG::encode_activate()
        if( encoding < 0 ) {
                encoding = 0;
                if( !(fmt_ctx->flags & AVFMT_NOFILE) &&
-                   (ret=avio_open(&fmt_ctx->pb, fmt_ctx->filename, AVIO_FLAG_WRITE)) < 0 ) {
+                   (ret=avio_open(&fmt_ctx->pb, fmt_ctx->url, AVIO_FLAG_WRITE)) < 0 ) {
                        ff_err(ret, "FFMPEG::encode_activate: err opening : %s\n",
-                               fmt_ctx->filename);
+                               fmt_ctx->url);
                        return -1;
                }
 
@@ -2490,7 +2485,7 @@ int FFMPEG::encode_activate()
                while(  --pi >= 0 && fmt_ctx->programs[pi]->id != prog_id );
                AVDictionary **meta = &prog->metadata;
                av_dict_set(meta, "service_provider", "cin5", 0);
-               const char *path = fmt_ctx->filename, *bp = strrchr(path,'/');
+               const char *path = fmt_ctx->url, *bp = strrchr(path,'/');
                if( bp ) path = bp + 1;
                av_dict_set(meta, "title", path, 0);
 
@@ -2522,7 +2517,7 @@ int FFMPEG::encode_activate()
                ret = avformat_write_header(fmt_ctx, &fopts);
                if( ret < 0 ) {
                        ff_err(ret, "FFMPEG::encode_activate: write header failed %s\n",
-                               fmt_ctx->filename);
+                               fmt_ctx->url);
                        return -1;
                }
                av_dict_free(&fopts);
@@ -2861,20 +2856,19 @@ int FFMPEG::ff_cpus()
 
 int FFVideoStream::create_filter(const char *filter_spec, AVCodecParameters *avpar)
 {
-       avfilter_register_all();
        const char *sp = filter_spec;
        char filter_name[BCSTRLEN], *np = filter_name;
        int i = sizeof(filter_name);
        while( --i>=0 && *sp!=0 && !strchr(" \t:=,",*sp) ) *np++ = *sp++;
        *np = 0;
-       AVFilter *filter = !filter_name[0] ? 0 : avfilter_get_by_name(filter_name);
+       const AVFilter *filter = !filter_name[0] ? 0 : avfilter_get_by_name(filter_name);
        if( !filter || avfilter_pad_get_type(filter->inputs,0) != AVMEDIA_TYPE_VIDEO ) {
                ff_err(AVERROR(EINVAL), "FFVideoStream::create_filter: %s\n", filter_spec);
                return -1;
        }
        filter_graph = avfilter_graph_alloc();
-       AVFilter *buffersrc = avfilter_get_by_name("buffer");
-       AVFilter *buffersink = avfilter_get_by_name("buffersink");
+       const AVFilter *buffersrc = avfilter_get_by_name("buffer");
+       const AVFilter *buffersink = avfilter_get_by_name("buffersink");
 
        int ret = 0;  char args[BCTEXTLEN];
        AVPixelFormat pix_fmt = (AVPixelFormat)avpar->format;
@@ -2902,20 +2896,19 @@ int FFVideoStream::create_filter(const char *filter_spec, AVCodecParameters *avp
 
 int FFAudioStream::create_filter(const char *filter_spec, AVCodecParameters *avpar)
 {
-       avfilter_register_all();
        const char *sp = filter_spec;
        char filter_name[BCSTRLEN], *np = filter_name;
        int i = sizeof(filter_name);
        while( --i>=0 && *sp!=0 && !strchr(" \t:=,",*sp) ) *np++ = *sp++;
        *np = 0;
-       AVFilter *filter = !filter_name[0] ? 0 : avfilter_get_by_name(filter_name);
+       const AVFilter *filter = !filter_name[0] ? 0 : avfilter_get_by_name(filter_name);
        if( !filter || avfilter_pad_get_type(filter->inputs,0) != AVMEDIA_TYPE_AUDIO ) {
                ff_err(AVERROR(EINVAL), "FFAudioStream::create_filter: %s\n", filter_spec);
                return -1;
        }
        filter_graph = avfilter_graph_alloc();
-       AVFilter *buffersrc = avfilter_get_by_name("abuffer");
-       AVFilter *buffersink = avfilter_get_by_name("abuffersink");
+       const AVFilter *buffersrc = avfilter_get_by_name("abuffer");
+       const AVFilter *buffersink = avfilter_get_by_name("abuffersink");
        int ret = 0;  char args[BCTEXTLEN];
        AVSampleFormat sample_fmt = (AVSampleFormat)avpar->format;
        snprintf(args, sizeof(args),
index c573e38797ab5fb654b6e632fd64f8795abfcda1..3b9810e99114b796ce1bf47e93b2aad1b5d14f80 100644 (file)
@@ -126,8 +126,6 @@ int FileAC3::open_file(int rd, int wr)
 
        if( !result && wr )
        {
-               //avcodec_init();
-               avcodec_register_all();
                codec = avcodec_find_encoder(AV_CODEC_ID_AC3);
                if(!codec)
                {
index 6cc3f58886c5a7887fe77d0229e218cc11dc19c1..6f4db28f0bb231ac780376bdbcd79e19c1495cf7 100644 (file)
@@ -836,7 +836,7 @@ int FileFFMPEG::get_index(IndexFile *index_file, MainProgressBar *progress_bar)
        }
 
        FileSystem fs;
-       int64_t file_bytes = fs.get_size(ff->fmt_ctx->filename);
+       int64_t file_bytes = fs.get_size(ff->fmt_ctx->url);
        char *index_path = index_file->index_filename;
 
        int canceled = 0;
index 3edc9f6777fa520df7e3455cdd6b0d0577b858ef..9f570526ec4fe4f6cef91035ad7746fe13d414c7 100644 (file)
@@ -532,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;
@@ -544,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;
@@ -805,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)
@@ -1151,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) ?
@@ -1175,8 +1175,9 @@ PluginServer* MWindow::new_ffmpeg_server(MWindow *mwindow, const char *name)
 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);
@@ -1192,7 +1193,5 @@ void MWindow::init_ffmpeg_index(MWindow *mwindow, Preferences *preferences, FILE
 
 void MWindow::init_ffmpeg()
 {
-       av_register_all();
-       avfilter_register_all();
 }
 
index 0768d0beb556ec4699a6a44449710f86ceeb0386..4d63b697c33fa168770b1ce14dc51da8b6791847 100644 (file)
@@ -70,7 +70,7 @@ public:
 class PluginFFilter {
        PluginFFilter(PluginFFilter &that) {} //disable assign/copy
 public:
-       AVFilter *filter;
+       const AVFilter *filter;
        AVFilterGraph *graph;
        AVFilterContext *fctx;
 
@@ -211,8 +211,8 @@ public:
 
        PluginFClient(PluginClient *plugin, const char *name);
         ~PluginFClient();
-       static bool is_audio(AVFilter *fp);
-       static bool is_video(AVFilter *fp);
+       static bool is_audio(const AVFilter *fp);
+       static bool is_video(const AVFilter *fp);
 
        int64_t get_source_position() {
                return plugin->get_source_position();
index 9e98a90fd63cf3ccc66777a9bfb41f22110fb9f5..f9dd58c440d21691f35f159822abf0ed0015d764 100644 (file)
@@ -12,7 +12,6 @@ CFG_CFLAGS+=" -fno-omit-frame-pointer -fno-math-errno -fno-signed-zeros"
 CFG_CFLAGS+=" -pthread -Wall"
 # misguided pedantic warnings
 CFG_CFLAGS+=" -Wno-unused-result"
-CFG_CFLAGS+=" -Wno-stringop-truncation"
 CFG_CFLAGS+=" -Wno-stringop-overflow"
 CFG_CFLAGS+=" -Wno-format-truncation"
 CFG_CFLAGS+=" -Wno-format-overflow"
@@ -132,7 +131,7 @@ PKG_3RD([fdk],[auto],
   [ libAACdec/include libAACenc/include libSYS/include ])
 
 PKG_3RD([ffmpeg],[yes],
-  [ffmpeg-3.4.2],
+  [ffmpeg-4.0],
   [ libavutil/libavutil.a \
     libavcodec/libavcodec.a \
     libpostproc/libpostproc.a \
index b62fa85fb2b113bedc41fc6a5c68d899a95d9697..ee455d7706b9defda57a0465433b479a3ac6a638 100644 (file)
@@ -101,7 +101,7 @@ deband
 #decimate
 deflate
 dejudder
-delogo x=1:y=1:w=1:h=1:band=1:show=0
+delogo x=10:y=10:w=10:h=10:show=1
 deshake
 #detelecine
 dilation
@@ -297,7 +297,6 @@ zoompan
 ; new in 3.4.1
 #acopy
 bitplanenoise
-boxblur
 ciescope
 crossfeed
 deflicker
@@ -312,14 +311,25 @@ oscilloscope
 pixscope
 pseudocolor
 roberts
-smartblur
 #superequalizer
 #surround
 tlut2
 #tonemap
 #vmafmotion
-; in git
+; new in 4.0
+acontrast
 #afir
-#headphone
+#aiir
 #convolve
+#deconvolve
+drmeter
+entropy
+fillborders
+#headphone
+hilbert
+mcompand
+#mix
+normalize
+setrange
 #unpremultiply
+vfrdet
index 8f6e6c4cc7e3b5188f1a6f801eff3210f24adccf..b5f2615d977279b5bc3d9715f133b41981afc7b4 100644 (file)
@@ -4,51 +4,160 @@ include $(TOPDIR)/global_config
 # plugin_dirs is translated in awindowgui.C, update if changed.
 
 plugin_dirs := themes
-themes := theme_bright theme_suv theme_blond theme_blue theme_blue_dot \
-       theme_hulk theme_pinklady theme_unflat theme_blond_cv
+themes := \
+       theme_blond \
+       theme_blond_cv \
+       theme_blue \
+       theme_blue_dot \
+       theme_bright \
+       theme_hulk \
+       theme_pinklady \
+       theme_suv \
+       theme_unflat \
 
-plugin_dirs += audio_transitions
-audio_transitions := crossfade
+plugin_dirs += video
+video := \
+       1080to480 \
+       1080to540 \
+       720to480 \
+       aging \
+       bandslide \
+       bandwipe \
+       bluebanana \
+       blur \
+       brightness \
+       burn \
+       C41 \
+       chromakey \
+       chromakeyhsv \
+       color3way \
+       colorbalance \
+       crikey \
+       crossfade \
+       decimate \
+       deinterlace \
+       deinterlace-cv \
+       delayvideo \
+       denoisemjpeg \
+       denoisevideo \
+       descratch \
+       diffkey \
+       dissolve \
+       dot \
+       downsample \
+       edge \
+       fieldframe \
+       flash \
+       flip \
+       framefield \
+       freezeframe \
+       gamma \
+       gradient \
+       greycstoration \
+       histeq \
+       histogram \
+       histogram_bezier \
+       holo \
+       huesaturation \
+       interpolatepixels \
+       interpolatevideo \
+       invertvideo \
+       irissquare \
+       ivtc \
+       lens \
+       linearblur \
+       liveaudio \
+       livevideo \
+       loopvideo \
+       motion \
+       motion2 \
+       motion51 \
+       motionblur \
+       motion-cv \
+       motion-hv \
+       oil \
+       overlay \
+       perspective \
+       photoscale \
+       polar \
+       radialblur \
+       reframe \
+       reframert \
+       reroute \
+       reversevideo \
+       rgb601 \
+       rgbshift \
+       rotate \
+       rumbler \
+       scale \
+       scaleratio \
+       seltempavg \
+       shapewipe \
+       sharpen \
+       shiftinterlace \
+       slide \
+       spherecam \
+       svg \
+       swapchannels \
+       swapframes \
+       threshold \
+       timeavg \
+       timefront \
+       titler \
+       translate \
+       unsharp \
+       videoscope \
+       wave \
+       whirl \
+       wipe \
+       yuv \
+       yuv411 \
+       yuvshift \
+       zoom \
+       zoomblur \
 
-plugin_dirs += video_transitions
-video_transitions := bandslide bandwipe dissolve flip irissquare \
-       shapewipe slide wipe zoom
+plugin_dirs += audio
+audio := \
+       audioscope \
+       cdripper \
+       compressor \
+       dcoffset \
+       delayaudio \
+       denoise \
+       denoisefft \
+       despike \
+       echo \
+       echocancel \
+       freeverb \
+       gain \
+       graphic \
+       interpolateaudio \
+       invertaudio \
+       leveleffect \
+       loopaudio \
+       normalize \
+       overlayaudio \
+       parametric \
+       pitch \
+       removegaps \
+       resample \
+       resamplert \
+       reverb \
+       reverseaudio \
+       spectrogram \
+       synthesizer \
+       timestretch \
+       timestretchrt \
+       vocoder \
 
-plugin_dirs += transforms
-transforms := 1080to480 1080to540 720to480 lens perspective photoscale \
-       polar rotate scale translate whirl scaleratio
-
-plugin_dirs += colors
-colors := brightness bluebanana C41 color3way colorbalance huesaturation \
-       gamma gradient histeq histogram histogram_bezier threshold
-
-plugin_dirs += exotic
-exotic := aging burn dot holo oil edge spherecam \
-        findobj flowobj gaborobj moveobj stylizeobj puzzleobj
-
-plugin_dirs += audio_tools
-audio_tools := audioscope cdripper compressor dcoffset delayaudio \
-       denoisefft denoise despike echocancel echo freeverb \
-       gain graphic interpolateaudio invertaudio leveleffect loopaudio \
-       normalize overlayaudio parametric pitch removegaps resample \
-       resamplert reverb reverseaudio synthesizer timestretch timestretchrt \
-       spectrogram vocoder
-
-plugin_dirs += video_tools
-video_tools := blur decimate delayvideo denoisemjpeg denoisevideo downsample \
-       fieldframe flash framefield freezeframe greycstoration interpolatepixels \
-       interpolatevideo invertvideo linearblur loopvideo \
-       motion2 motionblur motion motion-cv motion-hv motion51 \
-       overlay radialblur reframe reframert reroute reversevideo \
-       rumbler seltempavg sharpen svg titler timeavg timefront \
-       unsharp videoscope wave zoomblur descratch
-
-plugin_dirs += blending
-blending := crikey chromakeyhsv chromakey diffkey
-
-plugin_dirs += tv_effects
-tv_effects := deinterlace-cv deinterlace ivtc liveaudio livevideo rgb601 \
-       rgbshift shiftinterlace swapchannels swapframes yuv yuv411 yuvshift
+plugin_dirs += opencv
+opencv := \
+       findobj \
+       flowobj \
+       gaborobj \
+       moveobj \
+       puzzleobj \
+       stylizeobj \
 
 $(foreach dir,$(plugin_dirs),$(foreach plugin,$($(dir)), $(eval $(plugin):=$(dir))))
 
index 24c67cf80abb7f5a0afa6e773c8d9423e3a814b1..737601e2d204198b36bf711311a92ff7837145bd 100644 (file)
@@ -47,6 +47,8 @@ void FindObjConfig::reset()
        algorithm = NO_ALGORITHM;
        use_flann = 1;
        mode = MODE_QUADRILATERAL;
+       draw_match = 0;
+       aspect = 1;
        scale = 1;
        translate = 1;
        rotate = 1;
@@ -89,10 +91,12 @@ int FindObjConfig::equivalent(FindObjConfig &that)
                algorithm == that.algorithm &&
                use_flann == that.use_flann &&
                mode == that.mode &&
+               aspect == that.aspect &&
                scale == that.scale &&
                translate == that.translate &&
                rotate == that.rotate &&
                draw_keypoints == that.draw_keypoints &&
+               draw_match == that.draw_match &&
                draw_scene_border == that.draw_scene_border &&
                replace_object == that.replace_object &&
                draw_object_border == that.draw_object_border &&
@@ -119,10 +123,12 @@ void FindObjConfig::copy_from(FindObjConfig &that)
        algorithm = that.algorithm;
        use_flann = that.use_flann;
        mode = that.mode;
+       aspect = that.aspect;
        scale = that.scale;
        translate = that.translate;
        rotate = that.rotate;
        draw_keypoints = that.draw_keypoints;
+       draw_match = that.draw_match;
        draw_scene_border = that.draw_scene_border;
        replace_object = that.replace_object;
        draw_object_border = that.draw_object_border;
@@ -167,15 +173,18 @@ FindObjMain::FindObjMain(PluginServer *server)
        scene_layer = 1;
        replace_layer = 2;
 
-       border_x1 = 0;  border_y1 = 0;
-       border_x2 = 0;  border_y2 = 0;
-       border_x3 = 0;  border_y3 = 0;
-       border_x4 = 0;  border_y4 = 0;
-
-       obj_x1 = 0;     obj_y1 = 0;
-       obj_x2 = 0;     obj_y2 = 0;
-       obj_x3 = 0;     obj_y3 = 0;
-       obj_x4 = 0;     obj_y4 = 0;
+       match_x1 = 0;  match_y1 = 0;
+       match_x2 = 0;  match_y2 = 0;
+       match_x3 = 0;  match_y3 = 0;
+       match_x4 = 0;  match_y4 = 0;
+       shape_x1 = 0;  shape_y1 = 0;
+       shape_x2 = 0;  shape_y2 = 0;
+       shape_x3 = 0;  shape_y3 = 0;
+       shape_x4 = 0;  shape_y4 = 0;
+       out_x1 = 0;    out_y1 = 0;
+       out_x2 = 0;    out_y2 = 0;
+       out_x3 = 0;    out_y3 = 0;
+       out_x4 = 0;    out_y4 = 0;
 
         init_border = 1;
 }
@@ -214,6 +223,7 @@ void FindObjMain::save_data(KeyFrame *keyframe)
        output.tag.set_property("ALGORITHM", config.algorithm);
        output.tag.set_property("USE_FLANN", config.use_flann);
        output.tag.set_property("MODE", config.mode);
+       output.tag.set_property("ASPECT", config.aspect);
        output.tag.set_property("SCALE", config.scale);
        output.tag.set_property("TRANSLATE", config.translate);
        output.tag.set_property("ROTATE", config.rotate);
@@ -235,6 +245,7 @@ void FindObjMain::save_data(KeyFrame *keyframe)
        output.tag.set_property("REPLACE_DX", config.replace_dx);
        output.tag.set_property("REPLACE_DY", config.replace_dy);
        output.tag.set_property("DRAW_KEYPOINTS", config.draw_keypoints);
+       output.tag.set_property("DRAW_MATCH", config.draw_match);
        output.tag.set_property("DRAW_SCENE_BORDER", config.draw_scene_border);
        output.tag.set_property("REPLACE_OBJECT", config.replace_object);
        output.tag.set_property("DRAW_OBJECT_BORDER", config.draw_object_border);
@@ -263,6 +274,7 @@ void FindObjMain::read_data(KeyFrame *keyframe)
                        config.algorithm = input.tag.get_property("ALGORITHM", config.algorithm);
                        config.use_flann = input.tag.get_property("USE_FLANN", config.use_flann);
                        config.mode = input.tag.get_property("MODE", config.mode);
+                       config.aspect = input.tag.get_property("ASPECT", config.aspect);
                        config.scale = input.tag.get_property("SCALE", config.scale);
                        config.translate = input.tag.get_property("TRANSLATE", config.translate);
                        config.rotate = input.tag.get_property("ROTATE", config.rotate);
@@ -284,6 +296,7 @@ void FindObjMain::read_data(KeyFrame *keyframe)
                        config.replace_dy = input.tag.get_property("REPLACE_DY", config.replace_dy);
                        config.drag_replace = input.tag.get_property("DRAG_REPLACE", config.drag_replace);
                        config.draw_keypoints = input.tag.get_property("DRAW_KEYPOINTS", config.draw_keypoints);
+                       config.draw_match = input.tag.get_property("DRAW_MATCH", config.draw_match);
                        config.draw_scene_border = input.tag.get_property("DRAW_SCENE_BORDER", config.draw_scene_border);
                        config.replace_object = input.tag.get_property("REPLACE_OBJECT", config.replace_object);
                        config.draw_object_border = input.tag.get_property("DRAW_OBJECT_BORDER", config.draw_object_border);
@@ -303,13 +316,40 @@ void FindObjMain::draw_line(VFrame *vframe, int x1, int y1, int x2, int y2)
        vframe->draw_line(x1, y1, x2, y2);
 }
 
+void FindObjMain::draw_quad(VFrame *vframe,
+               int x1, int y1, int x2, int y2,
+               int x3, int y3, int x4, int y4)
+{
+       int r = bmin(vframe->get_w(), vframe->get_h()) / 200 + 1;
+       for( int i=r; --i>0; ) {
+               draw_line(vframe, x1+i, y1+i, x2, y2);
+               draw_line(vframe, x1-i, y1-i, x2, y2);
+               draw_line(vframe, x2+i, y2+i, x3, y3);
+               draw_line(vframe, x2-i, y2-i, x3, y3);
+               draw_line(vframe, x3+i, y3+i, x4, y4);
+               draw_line(vframe, x3-i, y3-i, x4, y4);
+               draw_line(vframe, x4+i, y4+i, x1, y1);
+               draw_line(vframe, x4-i, y4-i, x1, y1);
+       }
+       draw_line(vframe, x1, y1, x2, y2);
+       draw_line(vframe, x2, y2, x3, y3);
+       draw_line(vframe, x3, y3, x4, y4);
+       draw_line(vframe, x4, y4, x1, y1);
+       for( int i=r; --i>0; )
+               draw_circle(vframe, x1, y1, i);
+}
+
 void FindObjMain::draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2)
 {
-       --x2;  --y2;
-       draw_line(vframe, x1, y1, x2, y1);
-       draw_line(vframe, x2, y1, x2, y2);
-       draw_line(vframe, x2, y2, x1, y2);
-       draw_line(vframe, x1, y2, x1, y1);
+       int r = bmin(vframe->get_w(), vframe->get_h()) / 200 + 1;
+       for( int i=r; --i>0; ) {
+               --x2;  --y2;
+               draw_line(vframe, x1, y1, x2, y1);
+               draw_line(vframe, x2, y1, x2, y2);
+               draw_line(vframe, x2, y2, x1, y2);
+               draw_line(vframe, x1, y2, x1, y1);
+               ++x1;  ++y1;
+       }
 }
 
 void FindObjMain::draw_circle(VFrame *vframe, int x, int y, int r)
@@ -492,32 +532,47 @@ void FindObjMain::process_match()
        }
 
        ptV src, dst;
-       float obj_x1 = 0, obj_x2 = object_w;
-       float obj_y1 = 0, obj_y2 = object_h;
-       src.push_back(Point2f(obj_x1,obj_y1));
-       src.push_back(Point2f(obj_x2,obj_y1));
-       src.push_back(Point2f(obj_x2,obj_y2));
-       src.push_back(Point2f(obj_x1,obj_y2));
+       float out_x1 = 0, out_x2 = object_w;
+       float out_y1 = 0, out_y2 = object_h;
+       src.push_back(Point2f(out_x1,out_y1));
+       src.push_back(Point2f(out_x2,out_y1));
+       src.push_back(Point2f(out_x2,out_y2));
+       src.push_back(Point2f(out_x1,out_y2));
        perspectiveTransform(src, dst, H);
 
-       border_x1 = dst[0].x;  border_y1 = dst[0].y;
-       border_x2 = dst[1].x;  border_y2 = dst[1].y;
-       border_x3 = dst[2].x;  border_y3 = dst[2].y;
-       border_x4 = dst[3].x;  border_y4 = dst[3].y;
+       match_x1 = dst[0].x + scene_x;  match_y1 = dst[0].y + scene_y;
+       match_x2 = dst[1].x + scene_x;  match_y2 = dst[1].y + scene_y;
+       match_x3 = dst[2].x + scene_x;  match_y3 = dst[2].y + scene_y;
+       match_x4 = dst[3].x + scene_x;  match_y4 = dst[3].y + scene_y;
 }
 
 
-static double area(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
-{ // quadrelateral area
+static double area(float x1, float y1, float x2, float y2,
+               float x3, float y3, float x4, float y4)
+{ // quadrelateral area, sign is +ccw,-cw, use abs
        double dx1 = x3-x1, dy1 = y3-y1;
        double dx2 = x4-x2, dy2 = y4-y2;
-       return 0.5 * abs(dx1 * dy2 - dx2 * dy1);
+       return 0.5 * (dx1 * dy2 - dx2 * dy1);
 }
 static double dist(float x1,float y1, float x2, float y2)
 {
        double dx = x2-x1, dy = y2-y1;
        return sqrt(dx*dx + dy*dy);
 }
+static int intersects(double x1, double y1, double x2, double y2,
+               double x3, double y3, double x4, double y4)
+{
+       double dx12 = x2 - x1, dy12 = y2 - y1;
+       double dx34 = x4 - x3, dy34 = y4 - y3;
+       double d = dx12*dy34 - dx34*dy12;
+       if( !d ) return 0; // parallel
+       double dx13 = x3 - x1, dy13 = y3 - y1;
+       double u = (dx13*dy34 - dx34*dy13) / d;
+       if( u < 0 || u > 1 ) return 0;
+       double v = (dx13*dy12 - dx12*dy13) / d;
+       if( v < 0 || v > 1 ) return 0;
+       return 1;
+}
 
 /*
  * 4---------3    1---------2
@@ -531,19 +586,32 @@ void FindObjMain::reshape()
 {
        if( config.mode == MODE_NONE ) return;
        const double pi = M_PI;
-       double x1 = border_x1, y1 = border_y1;
-       double x2 = border_x2, y2 = border_y2;
-       double x3 = border_x3, y3 = border_y3;
-       double x4 = border_x4, y4 = border_y4;
+       double x1 = match_x1, y1 = match_y1;
+       double x2 = match_x2, y2 = match_y2;
+       double x3 = match_x3, y3 = match_y3;
+       double x4 = match_x4, y4 = match_y4;
+       double ia = area(x1,y1, x2,y2, x3,y3, x4,y4);
 // centroid
        double cx = (x1 + x2 + x3 + x4) / 4;
        double cy = (y1 + y2 + y3 + y4) / 4;
 // centered
        x1 -= cx;  x2 -= cx;  x3 -= cx;  x4 -= cx;
        y1 -= cy;  y2 -= cy;  y3 -= cy;  y4 -= cy;
+// bowtied
+       if( intersects(x1,y1, x2,y2, x3,y3, x4,y4) ) {
+               double x = x2, y = y2;
+               x2 = x3;  y2 = y3;
+               x3 = x;   y3 = y;
+       }
+       else if( intersects(x1,y1, x4,y4, x3,y3, x2,y2) ) {
+               double x = x4, y = y4;
+               x4 = x3;  y4 = y3;
+               x3 = x;   y3 = y;
+       }
+
 // rotation, if mode is quad: reverse rotate
        double r = 0;
-       if( (config.mode == MODE_QUADRILATERAL) ^ config.rotate ) {
+       if( (config.mode == MODE_QUADRILATERAL) ^ (config.rotate != 0) ) {
 // edge centers
                double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2;
                double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2;
@@ -570,6 +638,8 @@ void FindObjMain::reshape()
        double a12 = a2 - a1, a23 = a3 - a2;
        double a34 = a4 - a3, a41 = a1 - a4;
        double dt = (a12 - a23 + a34 - a41)/4;
+// mirrored
+       if( ia < 0 ) { ia = -ia;  dt = -dt;  r = -r; }
        switch( config.mode ) {
        case MODE_SQUARE:
        case MODE_RHOMBUS:
@@ -584,6 +654,20 @@ void FindObjMain::reshape()
        case MODE_QUADRILATERAL:
                break;
        }
+// aspect
+       if( !config.aspect ) {
+               double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2;
+               double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2;
+               double cx34 = (x3 + x4) / 2, cy34 = (y3 + y4) / 2;
+               double cx41 = (x4 + x1) / 2, cy41 = (y4 + y1) / 2;
+               double iw = dist(cx41,cy41, cx23,cy23);
+               double ih = dist(cx12,cy12, cx34,cy34);
+               double ow = object_w, oh = object_h;
+               double sx = iw && ih ? sqrt((ih*ow)/(iw*oh)) : 1;
+               double sy = sx ? 1 / sx : 1;
+               x1 *= sx;  x2 *= sx;  x3 *= sx;  x4 *= sx;
+               y1 *= sy;  y2 *= sy;  y3 *= sy;  y4 *= sy;
+       }
 // rotation
        if( r ) {
                double ct = cos(r), st = sin(r), x, y;
@@ -593,10 +677,8 @@ void FindObjMain::reshape()
                x = x4*ct + y4*st;  y = y4*ct - x4*st;  x4 = x;  y4 = y;
        }
 // scaling
-       double ia = !config.scale ? object_w * object_h :
-                       area(border_x1,border_y1, border_x2,border_y2,
-                            border_x3,border_y3, border_x4,border_y4);
-       double oa = area(x1,y1, x2,y2, x3,y3, x4,y4);
+       ia = !config.scale ? object_w * object_h : ia;
+       double oa = abs(area(x1,y1, x2,y2, x3,y3, x4,y4));
        double sf =  oa ? sqrt(ia / oa) : 0;
        x1 *= sf;  x2 *= sf;  x3 *= sf;  x4 *= sf;
        y1 *= sf;  y2 *= sf;  y3 *= sf;  y4 *= sf;
@@ -606,10 +688,10 @@ void FindObjMain::reshape()
        x1 += ox;  x2 += ox;  x3 += ox;  x4 += ox;
        y1 += oy;  y2 += oy;  y3 += oy;  y4 += oy;
 
-       border_x1 = x1;  border_y1 = y1;
-       border_x2 = x2;  border_y2 = y2;
-       border_x3 = x3;  border_y3 = y3;
-       border_x4 = x4;  border_y4 = y4;
+       shape_x1 = x1;  shape_y1 = y1;
+       shape_x2 = x2;  shape_y2 = y2;
+       shape_x3 = x3;  shape_y3 = y3;
+       shape_x4 = x4;  shape_y4 = y4;
 }
 
 int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate)
@@ -685,10 +767,10 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f
        scene = frame[scene_layer];
        replace = frame[replace_layer];
 
-       border_x1 = obj_x1;  border_y1 = obj_y1;
-       border_x2 = obj_x2;  border_y2 = obj_y2;
-       border_x3 = obj_x3;  border_y3 = obj_y3;
-       border_x4 = obj_x4;  border_y4 = obj_y4;
+       shape_x1 = out_x1;  shape_y1 = out_y1;
+       shape_x2 = out_x2;  shape_y2 = out_y2;
+       shape_x3 = out_x3;  shape_y3 = out_y3;
+       shape_x4 = out_x4;  shape_y4 = out_y4;
 
        if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) {
                process_match();
@@ -697,10 +779,10 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f
 
        double w0 = init_border ? 1. : config.blend/100., w1 = 1. - w0;
        init_border = 0;
-       obj_x1 = border_x1*w0 + obj_x1*w1;  obj_y1 = border_y1*w0 + obj_y1*w1;
-       obj_x2 = border_x2*w0 + obj_x2*w1;  obj_y2 = border_y2*w0 + obj_y2*w1;
-       obj_x3 = border_x3*w0 + obj_x3*w1;  obj_y3 = border_y3*w0 + obj_y3*w1;
-       obj_x4 = border_x4*w0 + obj_x4*w1;  obj_y4 = border_y4*w0 + obj_y4*w1;
+       out_x1 = shape_x1*w0 + out_x1*w1;  out_y1 = shape_y1*w0 + out_y1*w1;
+       out_x2 = shape_x2*w0 + out_x2*w1;  out_y2 = shape_y2*w0 + out_y2*w1;
+       out_x3 = shape_x3*w0 + out_x3*w1;  out_y3 = shape_y3*w0 + out_y3*w1;
+       out_x4 = shape_x4*w0 + out_x4*w1;  out_y4 = shape_y4*w0 + out_y4*w1;
 // Replace object in the scene layer
        if( config.replace_object ) {
                int cpus1 = get_project_smp() + 1;
@@ -711,12 +793,12 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f
                VFrame *temp = new_temp(w, h, scene->get_color_model());
                temp->clear_frame();
                affine->set_in_viewport(replace_x, replace_y, replace_w, replace_h);
+               float ix1 = replace_x, ix2 = ix1 + replace_w;
+               float iy1 = replace_y, iy2 = iy1 + replace_h;
                float dx = replace_dx, dy = replace_dy;
-               float x1 = obj_x1+dx, x2 = obj_x2+dx, x3 = obj_x3+dx, x4 = obj_x4+dx;
-               float y1 = obj_y1-dy, y2 = obj_y2-dy, y3 = obj_y3-dy, y4 = obj_y4-dy;
-               affine->set_matrix(
-                       replace_x, replace_y, replace_x+replace_w, replace_y+replace_h,
-                       x1,y1, x2,y2, x4,y4, x3,y3);
+               float ox1 = out_x1+dx, ox2 = out_x2+dx, ox3 = out_x3+dx, ox4 = out_x4+dx;
+               float oy1 = out_y1-dy, oy2 = out_y2-dy, oy3 = out_y3-dy, oy4 = out_y4-dy;
+               affine->set_matrix(ix1,iy1, ix2,iy2, ox1,oy1, ox2,oy2, ox4,oy4, ox3,oy3);
                affine->process(temp, replace, 0,
                        AffineEngine::TRANSFORM, 0,0, 100,0, 100,100, 0,100, 1);
                overlayer->overlay(scene, temp,  0,0, w,h,  0,0, w,h,
@@ -724,30 +806,32 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f
 
        }
 
+       int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
        if( config.draw_scene_border ) {
-               int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
-               scene->set_pixel_color(WHITE);  scene->set_stiple(ss*2);
+               scene->set_stiple(ss*2);
+               scene->set_pixel_color(WHITE);
                draw_rect(scene, scene_x, scene_y, scene_x+scene_w, scene_y+scene_h);
        }
        if( config.draw_object_border ) {
-               int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
-               scene->set_pixel_color(YELLOW);  scene->set_stiple(ss*3);
+               scene->set_stiple(ss*3);
+               scene->set_pixel_color(YELLOW); 
                draw_rect(scene, object_x, object_y, object_x+object_w, object_y+object_h);
        }
        if( config.draw_replace_border ) {
-               int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
-               scene->set_pixel_color(GREEN);  scene->set_stiple(ss*3);
+               scene->set_stiple(ss*3);
+               scene->set_pixel_color(GREEN);
                draw_rect(scene, replace_x, replace_y, replace_x+replace_w, replace_y+replace_h);
        }
+       scene->set_stiple(0);
        if( config.draw_keypoints ) {
-               scene->set_pixel_color(GREEN);  scene->set_stiple(0);
+               scene->set_pixel_color(GREEN);
                for( int i=0,n=obj_keypts.size(); i<n; ++i ) {
                        Point2f &pt = obj_keypts[i].pt;
                        int r = obj_keypts[i].size * 1.2/9 * 2;
                        int x = pt.x + object_x, y = pt.y + object_y;
                        draw_circle(scene, x, y, r);
                }
-               scene->set_pixel_color(RED);  scene->set_stiple(0);
+               scene->set_pixel_color(RED);
                for( int i=0,n=scn_keypts.size(); i<n; ++i ) {
                        Point2f &pt = scn_keypts[i].pt;
                        int r = scn_keypts[i].size * 1.2/9 * 2;
@@ -755,6 +839,11 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f
                        draw_circle(scene, x, y, r);
                }
        }
+       if( config.draw_match ) {
+               scene->set_pixel_color(BLUE);
+               draw_quad(scene, match_x1, match_y1, match_x2, match_y2,
+                               match_x3, match_y3, match_x4, match_y4);
+       }
 
        if( gui_open() ) {
                if( config.drag_scene ) {
index 7396f31b92b091f80563f9d7631fe790ab8a7c62..75a80fb262a4ec53009fd2fddec961a6f1df94ae 100644 (file)
@@ -110,15 +110,15 @@ public:
                int64_t prev_frame, int64_t next_frame, int64_t current_frame);
        void boundaries();
 
-       int algorithm, use_flann;
+       int algorithm, use_flann, mode;
        int drag_object, drag_scene, drag_replace;
        float object_x, object_y, object_w, object_h;
        float scene_x, scene_y, scene_w, scene_h;
        float replace_x, replace_y, replace_w, replace_h;
        float replace_dx, replace_dy;
 
-       int mode, scale, translate, rotate;
-       int draw_keypoints;
+       int aspect, scale, translate, rotate;
+       int draw_keypoints, draw_match;
        int draw_scene_border;
        int replace_object;
        int draw_object_border;
@@ -169,6 +169,9 @@ public:
        VFrame *object, *scene, *replace;
 
        static void draw_line(VFrame *vframe, int x1, int y1, int x2, int y2);
+       void draw_quad(VFrame *vframe,
+                       int x1, int y1, int x2, int y2,
+                       int x3, int y3, int x4, int y4);
        static void draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2);
        static void draw_circle(VFrame *vframe, int x, int y, int r);
 
@@ -182,16 +185,12 @@ public:
        int scene_layer;
        int replace_layer;
 
-// Latest coordinates of object in scene
-       float border_x1, border_y1;
-       float border_x2, border_y2;
-       float border_x3, border_y3;
-       float border_x4, border_y4;
+// Latest coordinates of match / shape / object in scene
+       float match_x1, match_y1, shape_x1, shape_y1, out_x1, out_y1;
+       float match_x2, match_y2, shape_x2, shape_y2, out_x2, out_y2;
+       float match_x3, match_y3, shape_x3, shape_y3, out_x3, out_y3;
+       float match_x4, match_y4, shape_x4, shape_y4, out_x4, out_y4;
 // Coordinates of object in scene with blending
-       float obj_x1, obj_y1;
-       float obj_x2, obj_y2;
-       float obj_x3, obj_y3;
-       float obj_x4, obj_y4;
        int init_border;
 
 //opencv
index 87d3dbd0e4f4451a3b45966bd670a9d97643ebb5..2f5cd7a2b4725b482e1c6a396de81a5a1630b250 100644 (file)
@@ -32,7 +32,7 @@
 
 
 FindObjWindow::FindObjWindow(FindObjMain *plugin)
- : PluginClientWindow(plugin, 500, 660, 500, 660, 0)
+ : PluginClientWindow(plugin, 500, 700, 500, 700, 0)
 {
        this->plugin = plugin;
 }
@@ -47,32 +47,35 @@ void FindObjWindow::create_objects()
        plugin->load_configuration();
 
        BC_Title *title;
+       add_subwindow(title = new BC_Title(x1, y, _("Mode:")));
+       add_subwindow(mode = new FindObjMode(plugin, this,
+               x1 + 100, y));
+       add_subwindow(reset = new FindObjReset(plugin, this, get_w()-15, y));
+       mode->create_objects();
+       y += mode->get_h() + 10;
+       int y0 = y;
        add_subwindow(title = new BC_Title(x1, y, _("Algorithm:")));
        add_subwindow(algorithm = new FindObjAlgorithm(plugin, this,
-               x1 + title->get_w() + 10, y));
+               x1 + 100, y));
        algorithm->create_objects();
-       int x0 = get_w() - 15;
-       add_subwindow(reset = new FindObjReset(plugin, this, x0, y));
        y += algorithm->get_h() + plugin->get_theme()->widget_border;
-
        add_subwindow(use_flann = new FindObjUseFlann(plugin, this, x, y));
-       x0 -= FindObjMode::calculate_w(this) + 30;
-       add_subwindow(mode = new FindObjMode(plugin, this, x0, y));
-       mode->create_objects();
-       x0 -= BC_Title::calculate_w(this, _("Mode:")) + 10;
-       add_subwindow(title = new BC_Title(x0, y, _("Mode:")));
-       y += use_flann->get_h() + plugin->get_theme()->widget_border + 10;
+       y += use_flann->get_h() + 10;
 
-       int y1 = y;
+       int y1 = y;  y = y0;
+       add_subwindow(replace_object = new FindObjReplace(plugin, this,x3, y));
+       y += replace_object->get_h() + 10;
+       add_subwindow(draw_match = new FindObjDrawMatch(plugin, this, x3, y));
+       y += draw_match->get_h() + 10;
+       add_subwindow(aspect = new FindObjAspect(plugin, this, x3, y));
+       y += aspect->get_h() + 10;
        add_subwindow(scale = new FindObjScale(plugin, this, x3, y));
        y += scale->get_h() + 10;
        add_subwindow(rotate = new FindObjRotate(plugin, this, x3, y));
        y += rotate->get_h() + 10;
        add_subwindow(translate = new FindObjTranslate(plugin, this, x3, y));
-       y += translate->get_h() + 10;
-       add_subwindow(replace_object = new FindObjReplace(plugin, this,x3, y));
 
-       x0 = x + 200;  y = y1 + 10;
+       int x0 = x + 200;  y = y1 + 10;
        add_subwindow(title = new BC_Title(x, y, _("Output/scene layer:")));
        scene_layer = new FindObjLayer(plugin, this, x0, y,
                &plugin->config.scene_layer);
@@ -91,6 +94,7 @@ void FindObjWindow::create_objects()
        replace_layer->create_objects();
        y += replace_layer->get_h() + plugin->get_theme()->widget_border + 10;
 
+       y += 10;
        add_subwindow(title = new BC_Title(x+15, y, _("Units: 0 to 100 percent")));
        y += title->get_h();
 
@@ -334,6 +338,8 @@ void FindObjWindow::update_gui()
        FindObjConfig &conf = plugin->config;
        algorithm->update(conf.algorithm);
        use_flann->update(conf.use_flann);
+       draw_match->update(conf.draw_match);
+       aspect->update(conf.aspect);
        scale->update(conf.scale);
        rotate->update(conf.rotate);
        translate->update(conf.translate);
@@ -747,6 +753,36 @@ int FindObjUseFlann::handle_event()
        return 1;
 }
 
+FindObjDrawMatch::FindObjDrawMatch(FindObjMain *plugin, FindObjWindow *gui,
+       int x, int y)
+ : BC_CheckBox(x, y, plugin->config.draw_match, _("Draw match"))
+{
+       this->gui = gui;
+       this->plugin = plugin;
+}
+
+int FindObjDrawMatch::handle_event()
+{
+       plugin->config.draw_match = get_value();
+       plugin->send_configure_change();
+       return 1;
+}
+
+FindObjAspect::FindObjAspect(FindObjMain *plugin, FindObjWindow *gui,
+       int x, int y)
+ : BC_CheckBox(x, y, plugin->config.aspect, _("Aspect"))
+{
+       this->gui = gui;
+       this->plugin = plugin;
+}
+
+int FindObjAspect::handle_event()
+{
+       plugin->config.aspect = get_value();
+       plugin->send_configure_change();
+       return 1;
+}
+
 FindObjScale::FindObjScale(FindObjMain *plugin, FindObjWindow *gui,
        int x, int y)
  : BC_CheckBox(x, y, plugin->config.scale, _("Scale"))
index 02feee23bd21941503372df59e011acc8b7634d8..a856d0735de0dc72162d10f0b38a5ae72efca763 100644 (file)
 #include "findobj.inc"
 #include "guicast.h"
 
+
 class FindObjReset;
 class FindObjLayer;
 class FindObjScanFloat;
 class FindObjScanFloatText;
 class FindObjDrawSceneBorder;
-class FindObjDrawKeypoints;
-class FindObjReplace;
 class FindObjDrawObjectBorder;
 class FindObjDrawReplaceBorder;
-class FindObjDragObject;
+class FindObjDrawKeypoints;
+class FindObjReplace;
 class FindObjDragScene;
+class FindObjDragObject;
 class FindObjDragReplace;
 class FindObjAlgorithm;
-class FindObjMode;
+class FindObjUseFlann;
+class FindObjDrawMatch;
+class FindObjAspect;
 class FindObjScale;
 class FindObjRotate;
 class FindObjTranslate;
+class FindObjMode;
 class FindObjBlend;
 class FindObjWindow;
 
@@ -209,6 +213,24 @@ public:
        FindObjWindow *gui;
 };
 
+class FindObjDrawMatch : public BC_CheckBox
+{
+public:
+       FindObjDrawMatch(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+       int handle_event();
+       FindObjMain *plugin;
+       FindObjWindow *gui;
+};
+
+class FindObjAspect : public BC_CheckBox
+{
+public:
+       FindObjAspect(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+       int handle_event();
+       FindObjMain *plugin;
+       FindObjWindow *gui;
+};
+
 class FindObjScale : public BC_CheckBox
 {
 public:
@@ -271,7 +293,9 @@ public:
        FindObjReset *reset;
        FindObjAlgorithm *algorithm;
        FindObjUseFlann *use_flann;
+       FindObjDrawMatch *draw_match;
        FindObjMode *mode;
+       FindObjAspect *aspect;
        FindObjScale *scale;
        FindObjRotate *rotate;
        FindObjTranslate *translate;
index 8faa94dd1f3f16da1aa5e505a23883ec6913d5c2..6e84efaa0b263290ec7179bf693a2984952e218b 100644 (file)
@@ -111,8 +111,7 @@ fdk.mak_params= ; for f in $(call bld_path,fdk,/lib*/include); do ln -s . $$$$f/
 fftw.cfg_params= --disable-fortran --enable-shared=no
 ffmpeg.cfg_params= \
        --enable-pthreads --enable-gpl \
-       --disable-ffserver --disable-ffplay \
-       --disable-vaapi \
+       --disable-ffplay --disable-vaapi \
        $(call if_pkg,fdk,--enable-libfdk-aac) \
        $(call if_pkg,twolame,--enable-libtwolame) \
        $(call if_pkg,openjpeg,--enable-libopenjpeg) \
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch1 b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch1
deleted file mode 100644 (file)
index daa9953..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -ru ffmpeg-3.0.orig/libavformat/bluray.c ffmpeg-3.0/libavformat/bluray.c
---- ffmpeg-3.0.orig/libavformat/bluray.c       2015-03-13 11:34:50.000000000 -0600
-+++ ffmpeg-3.0/libavformat/bluray.c    2016-05-09 14:07:34.758713307 -0600
-@@ -28,7 +28,7 @@
- #include "libavutil/opt.h"
- #define BLURAY_PROTO_PREFIX     "bluray:"
--#define MIN_PLAYLIST_LENGTH     180     /* 3 min */
-+#define MIN_PLAYLIST_LENGTH     0
- typedef struct {
-     const AVClass *class;
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch2 b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch2
deleted file mode 100644 (file)
index bb628d9..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-diff -ur a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
---- a/libavformat/mpegtsenc.c  2017-12-10 14:35:10.000000000 -0700
-+++ b/libavformat/mpegtsenc.c  2017-12-18 10:54:14.260167666 -0700
-@@ -56,9 +56,8 @@
-     int sid;           /* service ID */
-     char *name;
-     char *provider_name;
--    int pcr_pid;
--    int pcr_packet_count;
--    int pcr_packet_period;
-+    int64_t pcr, pcr_packet_timer, pcr_packet_period;
-+    int pcr_sid, pcr_pid;
-     AVProgram *program;
- } MpegTSService;
-@@ -78,14 +77,12 @@
-     MpegTSSection pat; /* MPEG-2 PAT table */
-     MpegTSSection sdt; /* MPEG-2 SDT table context */
-     MpegTSService **services;
--    int sdt_packet_count;
--    int sdt_packet_period;
--    int pat_packet_count;
--    int pat_packet_period;
-+    int64_t sdt_packet_timer, sdt_packet_period;
-+    int64_t pat_packet_timer, pat_packet_period;
-     int nb_services;
-     int onid;
-     int tsid;
--    int64_t first_pcr;
-+    int64_t pcr, first_pcr, delay;
-     int mux_rate; ///< set to 1 when VBR
-     int pes_payload_size;
-@@ -95,12 +92,14 @@
-     int service_type;
-     int pmt_start_pid;
-+    int pcr_start_pid;
-     int start_pid;
-     int m2ts_mode;
-+    int64_t ts_offset;
-     int reemit_pat_pmt; // backward compatibility
--    int pcr_period;
-+    double pcr_period;
- #define MPEGTS_FLAG_REEMIT_PAT_PMT  0x01
- #define MPEGTS_FLAG_AAC_LATM        0x02
- #define MPEGTS_FLAG_PAT_PMT_AT_FRAMES           0x04
-@@ -111,8 +110,6 @@
-     int tables_version;
-     double pat_period;
-     double sdt_period;
--    int64_t last_pat_ts;
--    int64_t last_sdt_ts;
-     int omit_video_pes_length;
- } MpegTSWrite;
-@@ -222,10 +219,10 @@
- #define DEFAULT_PROVIDER_NAME   "FFmpeg"
- #define DEFAULT_SERVICE_NAME    "Service01"
--/* we retransmit the SI info at this rate */
-+/* we retransmit the SI info at this rate (ms) */
- #define SDT_RETRANS_TIME 500
- #define PAT_RETRANS_TIME 100
--#define PCR_RETRANS_TIME 20
-+#define PCR_RETRANS_TIME 50
- typedef struct MpegTSWriteStream {
-     struct MpegTSService *service;
-@@ -721,6 +718,7 @@
-     service->pmt.pid       = ts->pmt_start_pid + ts->nb_services;
-     service->sid           = sid;
-     service->pcr_pid       = 0x1fff;
-+    service->pcr_sid       = 0x1fff;
-     service->provider_name = av_strdup(provider_name);
-     service->name          = av_strdup(name);
-     if (!service->provider_name || !service->name)
-@@ -736,18 +734,11 @@
-     return NULL;
- }
--static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
--{
--    return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
--           ts->first_pcr;
--}
--
- static void mpegts_prefix_m2ts_header(AVFormatContext *s)
- {
-     MpegTSWrite *ts = s->priv_data;
-     if (ts->m2ts_mode) {
--        int64_t pcr = get_pcr(s->priv_data, s->pb);
--        uint32_t tp_extra_header = pcr % 0x3fffffff;
-+        uint32_t tp_extra_header = ts->pcr % 0x3fffffff;
-         tp_extra_header = AV_RB32(&tp_extra_header);
-         avio_write(s->pb, (unsigned char *) &tp_extra_header,
-                    sizeof(tp_extra_header));
-@@ -768,6 +759,7 @@
-     MpegTSService *service;
-     AVStream *st, *pcr_st = NULL;
-     AVDictionaryEntry *title, *provider;
-+    double clk_rate;
-     int i, j;
-     const char *service_name;
-     const char *provider_name;
-@@ -776,6 +768,15 @@
-     if (s->max_delay < 0) /* Not set by the caller */
-         s->max_delay = 0;
-+    ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
-+
-+    if (ts->m2ts_mode == -1) {
-+        if (av_match_ext(s->filename, "m2ts")) {
-+            ts->m2ts_mode = 1;
-+        } else {
-+            ts->m2ts_mode = 0;
-+        }
-+    }
-     // round up to a whole number of TS packets
-     ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
-@@ -822,6 +823,8 @@
-             service->program          = program;
-         }
-     }
-+    if (ts->m2ts_mode > 1)
-+        service->pmt.pid = 0x00ff + ts->service_id;
-     ts->pat.pid          = PAT_PID;
-     /* Initialize at 15 so that it wraps and is equal to 0 for the
-@@ -907,10 +910,9 @@
-         ts_st->discontinuity   = ts->flags & MPEGTS_FLAG_DISCONT;
-         /* update PCR pid by using the first video stream */
-         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
--            service->pcr_pid == 0x1fff) {
--            service->pcr_pid = ts_st->pid;
-+            service->pcr_sid == 0x1fff)
-             pcr_st           = st;
--        }
-+
-         if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
-             st->codecpar->extradata_size > 0) {
-             AVStream *ast;
-@@ -946,78 +948,47 @@
-     av_freep(&pids);
-     /* if no video stream, use the first stream as PCR */
--    if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
--        pcr_st           = s->streams[0];
--        ts_st            = pcr_st->priv_data;
--        service->pcr_pid = ts_st->pid;
--    } else
--        ts_st = pcr_st->priv_data;
--
--    if (ts->mux_rate > 1) {
--        service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
--                                     (TS_PACKET_SIZE * 8 * 1000);
--        ts->sdt_packet_period      = (int64_t)ts->mux_rate * SDT_RETRANS_TIME /
--                                     (TS_PACKET_SIZE * 8 * 1000);
--        ts->pat_packet_period      = (int64_t)ts->mux_rate * PAT_RETRANS_TIME /
--                                     (TS_PACKET_SIZE * 8 * 1000);
--
--        if (ts->copyts < 1)
--            ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
--    } else {
--        /* Arbitrary values, PAT/PMT will also be written on video key frames */
--        ts->sdt_packet_period = 200;
--        ts->pat_packet_period = 40;
--        if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
--            int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0);
--            if (!frame_size) {
--                av_log(s, AV_LOG_WARNING, "frame size not set\n");
--                service->pcr_packet_period =
--                    pcr_st->codecpar->sample_rate / (10 * 512);
--            } else {
--                service->pcr_packet_period =
--                    pcr_st->codecpar->sample_rate / (10 * frame_size);
--            }
--        } else {
--            // max delta PCR 0.1s
--            // TODO: should be avg_frame_rate
--            service->pcr_packet_period =
--                ts_st->user_tb.den / (10 * ts_st->user_tb.num);
--        }
--        if (!service->pcr_packet_period)
--            service->pcr_packet_period = 1;
--    }
--
--    ts->last_pat_ts = AV_NOPTS_VALUE;
--    ts->last_sdt_ts = AV_NOPTS_VALUE;
--    // The user specified a period, use only it
--    if (ts->pat_period < INT_MAX/2) {
--        ts->pat_packet_period = INT_MAX;
-+    if (!pcr_st && s->nb_streams > 0)
-+        pcr_st = s->streams[0];
-+    if (!pcr_st) {
-+        av_log(s, AV_LOG_ERROR, "no streams\n");
-+        ret = AVERROR(EINVAL);
-+        goto fail;
-     }
--    if (ts->sdt_period < INT_MAX/2) {
--        ts->sdt_packet_period = INT_MAX;
-+    ts_st  = pcr_st->priv_data;
-+    if (service->pcr_sid == 0x1fff)
-+        service->pcr_sid   = ts_st->pid;
-+    if (service->pcr_pid == 0x1fff)
-+        service->pcr_pid   = ts->m2ts_mode > 1 ?
-+            0x1000 + ts->service_id : service->pcr_sid ;
-+    if (service->pmt.pid == service->pcr_pid) {
-+        av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", service->pcr_pid);
-+        ret = AVERROR(EINVAL);
-+        goto fail;
-     }
-+    clk_rate = ts->mux_rate > 1 ? ts->mux_rate : PCR_TIME_BASE;
-+    ts->sdt_packet_period      = ts->sdt_period < 0 ? -1 : ts->sdt_period/1000 * clk_rate;
-+    ts->pat_packet_period      = ts->pat_period/1000 * clk_rate;
-+    service->pcr_packet_period = ts->pcr_period/1000 * clk_rate;
-+    if (service->pcr_packet_period < (TS_PACKET_SIZE*8*10))
-+        service->pcr_packet_period = (TS_PACKET_SIZE*8*10);
-+    av_log(s, AV_LOG_VERBOSE, "clk_rate %f: ticks/pkt %d pcr, %d sdt, %d pmt\n", clk_rate,
-+        (int)service->pcr_packet_period, (int)ts->sdt_packet_period, (int)ts->pat_packet_period);
-+
-+    if (ts->copyts < 1)
-+        ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
-+
-     // output a PCR as soon as possible
--    service->pcr_packet_count = service->pcr_packet_period;
--    ts->pat_packet_count      = ts->pat_packet_period - 1;
--    ts->sdt_packet_count      = ts->sdt_packet_period - 1;
-+    ts->pcr = 0;
-+    service->pcr_packet_timer = 0;
-+    ts->pat_packet_timer      = 0;
-+    ts->sdt_packet_timer      = 0;
-     if (ts->mux_rate == 1)
-         av_log(s, AV_LOG_VERBOSE, "muxrate VBR, ");
-     else
-         av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
--    av_log(s, AV_LOG_VERBOSE,
--           "pcr every %d pkts, sdt every %d, pat/pmt every %d pkts\n",
--           service->pcr_packet_period,
--           ts->sdt_packet_period, ts->pat_packet_period);
--
--    if (ts->m2ts_mode == -1) {
--        if (av_match_ext(s->filename, "m2ts")) {
--            ts->m2ts_mode = 1;
--        } else {
--            ts->m2ts_mode = 0;
--        }
--    }
-     return 0;
-@@ -1032,22 +1003,12 @@
-     MpegTSWrite *ts = s->priv_data;
-     int i;
--    if (++ts->sdt_packet_count == ts->sdt_packet_period ||
--        (dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
--        (dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
--    ) {
--        ts->sdt_packet_count = 0;
--        if (dts != AV_NOPTS_VALUE)
--            ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts);
-+    if ( ts->sdt_packet_period >= 0 && ts->pcr >= ts->sdt_packet_timer ) {
-+        ts->sdt_packet_timer = ts->pcr + ts->sdt_packet_period;
-         mpegts_write_sdt(s);
-     }
--    if (++ts->pat_packet_count == ts->pat_packet_period ||
--        (dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
--        (dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
--        force_pat) {
--        ts->pat_packet_count = 0;
--        if (dts != AV_NOPTS_VALUE)
--            ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
-+    if (ts->pcr >= ts->pat_packet_timer || force_pat) {
-+        ts->pat_packet_timer = ts->pcr + ts->pat_packet_period;
-         mpegts_write_pat(s);
-         for (i = 0; i < ts->nb_services; i++)
-             mpegts_write_pmt(s, ts->services[i]);
-@@ -1089,13 +1050,14 @@
- {
-     MpegTSWrite *ts = s->priv_data;
-     MpegTSWriteStream *ts_st = st->priv_data;
-+    uint32_t pcr_pid = ts_st->service->pcr_pid;
-     uint8_t *q;
-     uint8_t buf[TS_PACKET_SIZE];
-     q    = buf;
-     *q++ = 0x47;
--    *q++ = ts_st->pid >> 8;
--    *q++ = ts_st->pid;
-+    *q++ = pcr_pid >> 8;
-+    *q++ = pcr_pid;
-     *q++ = 0x20 | ts_st->cc;   /* Adaptation only */
-     /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
-     *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
-@@ -1106,7 +1068,7 @@
-     }
-     /* PCR coded into 6 bytes */
--    q += write_pcr_bits(q, get_pcr(ts, s->pb));
-+    q += write_pcr_bits(q, ts->pcr);
-     /* stuffing bytes */
-     memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
-@@ -1175,8 +1137,6 @@
-     uint8_t *q;
-     int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
-     int afc_len, stuffing_len;
--    int64_t pcr = -1; /* avoid warning */
--    int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
-     int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
-     av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
-@@ -1186,28 +1146,33 @@
-     is_start = 1;
-     while (payload_size > 0) {
-+        ts->pcr = ts->first_pcr + (ts->mux_rate == 1 ?
-+            (dts == AV_NOPTS_VALUE ? 0 : (dts - ts->delay) * 300) :
-+            // add 11, pcr references the last byte of program clock reference base
-+            av_rescale(avio_tell(s->pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate));
-+
-         retransmit_si_info(s, force_pat, dts);
-         force_pat = 0;
-         write_pcr = 0;
--        if (ts_st->pid == ts_st->service->pcr_pid) {
--            if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
--                ts_st->service->pcr_packet_count++;
--            if (ts_st->service->pcr_packet_count >=
--                ts_st->service->pcr_packet_period) {
--                ts_st->service->pcr_packet_count = 0;
-+        if (ts_st->pid == ts_st->service->pcr_sid) {
-+            if( ts->pcr >= ts_st->service->pcr_packet_timer ) {
-+                ts_st->service->pcr_packet_timer = ts->pcr + ts_st->service->pcr_packet_period;
-                 write_pcr = 1;
-             }
-         }
--
-+        if (write_pcr && ts_st->service->pcr_sid != ts_st->service->pcr_pid) {
-+           mpegts_insert_pcr_only(s, st);
-+           continue;
-+        }
-         if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
--            (dts - get_pcr(ts, s->pb) / 300) > delay) {
--            /* pcr insert gets priority over null packet insert */
--            if (write_pcr)
--                mpegts_insert_pcr_only(s, st);
-+               (dts - ts->pcr / 300) > ts->delay) {
-+           /* pcr insert gets priority over null packet insert */
-+           if (write_pcr)
-+               mpegts_insert_pcr_only(s, st);
-             else
--                mpegts_insert_null_packet(s);
--            /* recalculate write_pcr and possibly retransmit si_info */
-+               mpegts_insert_null_packet(s);
-+            /* recalculate write_pcr and possibly retransimit si_info */
-             continue;
-         }
-@@ -1217,6 +1182,10 @@
-         val  = ts_st->pid >> 8;
-         if (is_start)
-             val |= 0x40;
-+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
-+          st->codecpar->codec_id == AV_CODEC_ID_AC3 &&
-+          ts->m2ts_mode > 1)
-+            val |= 0x20;
-         *q++      = val;
-         *q++      = ts_st->pid;
-         ts_st->cc = ts_st->cc + 1 & 0xf;
-@@ -1228,7 +1197,7 @@
-         }
-         if (key && is_start && pts != AV_NOPTS_VALUE) {
-             // set Random Access for key frames
--            if (ts_st->pid == ts_st->service->pcr_pid)
-+            if (ts_st->pid == ts_st->service->pcr_sid)
-                 write_pcr = 1;
-             set_af_flag(buf, 0x40);
-             q = get_ts_payload_start(buf);
-@@ -1236,14 +1205,10 @@
-         if (write_pcr) {
-             set_af_flag(buf, 0x10);
-             q = get_ts_payload_start(buf);
--            // add 11, pcr references the last byte of program clock reference base
-             if (ts->mux_rate > 1)
--                pcr = get_pcr(ts, s->pb);
--            else
--                pcr = (dts - delay) * 300;
--            if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
-+            if (dts != AV_NOPTS_VALUE && dts < ts->pcr / 300)
-                 av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
--            extend_af(buf, write_pcr_bits(q, pcr));
-+            extend_af(buf, write_pcr_bits(q, ts->pcr));
-             q = get_ts_payload_start(buf);
-         }
-         if (is_start) {
-@@ -1344,11 +1309,13 @@
-             *q++ = flags;
-             *q++ = header_len;
-             if (pts != AV_NOPTS_VALUE) {
--                write_pts(q, flags >> 6, pts);
-+                int64_t ts_pts = pts + ts->ts_offset;
-+                write_pts(q, flags >> 6, ts_pts);
-                 q += 5;
-             }
-             if (dts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE && dts != pts) {
--                write_pts(q, 1, dts);
-+                int64_t ts_dts = dts + ts->ts_offset;
-+                write_pts(q, 1, ts_dts);
-                 q += 5;
-             }
-             if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) {
-@@ -1519,7 +1486,6 @@
-     uint8_t *data = NULL;
-     MpegTSWrite *ts = s->priv_data;
-     MpegTSWriteStream *ts_st = st->priv_data;
--    const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
-     int64_t dts = pkt->dts, pts = pkt->pts;
-     int opus_samples = 0;
-     int side_data_size;
-@@ -1540,16 +1506,15 @@
-     }
-     if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) {
--        ts->pat_packet_count = ts->pat_packet_period - 1;
--        ts->sdt_packet_count = ts->sdt_packet_period - 1;
-+        ts->pat_packet_timer = ts->sdt_packet_timer = 0;
-         ts->flags           &= ~MPEGTS_FLAG_REEMIT_PAT_PMT;
-     }
-     if (ts->copyts < 1) {
-         if (pts != AV_NOPTS_VALUE)
--            pts += delay;
-+            pts += 2*ts->delay;
-         if (dts != AV_NOPTS_VALUE)
--            dts += delay;
-+            dts += 2*ts->delay;
-     }
-     if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) {
-@@ -1737,7 +1702,7 @@
-             AVStream *st2 = s->streams[i];
-             MpegTSWriteStream *ts_st2 = st2->priv_data;
-             if (   ts_st2->payload_size
--               && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > delay/2)) {
-+               && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > ts->delay)) {
-                 mpegts_write_pes(s, st2, ts_st2->payload, ts_st2->payload_size,
-                                  ts_st2->payload_pts, ts_st2->payload_dts,
-                                  ts_st2->payload_flags & AV_PKT_FLAG_KEY, stream_id);
-@@ -1908,12 +1873,18 @@
-     { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
-       offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT,
-       { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
-+    { "mpegts_pcr_start_pid", "Set the first pid of the PCR.",
-+      offsetof(MpegTSWrite, pcr_start_pid), AV_OPT_TYPE_INT,
-+      { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
-     { "mpegts_start_pid", "Set the first pid.",
-       offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
-       { .i64 = 0x0100 }, 0x0010, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
-     { "mpegts_m2ts_mode", "Enable m2ts mode.",
-       offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_BOOL,
--      { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
-+      { .i64 = -1 }, -1, 2, AV_OPT_FLAG_ENCODING_PARAM },
-+    { "mpegts_pcr_offset", "clock offset.",
-+      offsetof(MpegTSWrite, ts_offset), AV_OPT_TYPE_BOOL,
-+      { .i64 = 0 }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-     { "muxrate", NULL,
-       offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
-       { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-@@ -1951,15 +1922,15 @@
-     { "omit_video_pes_length", "Omit the PES packet length for video packets",
-       offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL,
-       { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
--    { "pcr_period", "PCR retransmission time in milliseconds",
--      offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,
--      { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
--    { "pat_period", "PAT/PMT retransmission time limit in seconds",
-+    { "pcr_period", "PCR retransmission time limit in msecs",
-+      offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_DOUBLE,
-+      { .dbl = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-+    { "pat_period", "PAT/PMT retransmission time limit in msecs",
-       offsetof(MpegTSWrite, pat_period), AV_OPT_TYPE_DOUBLE,
--      { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
--    { "sdt_period", "SDT retransmission time limit in seconds",
-+      { .dbl = PAT_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-+    { "sdt_period", "SDT retransmission time limit in msecs",
-       offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE,
--      { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-+      { .dbl = SDT_RETRANS_TIME }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-     { NULL },
- };
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch3 b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch3
deleted file mode 100644 (file)
index 36699ee..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-diff -ur a/libavformat/avformat.h b/libavformat/avformat.h
---- a/libavformat/avformat.h   2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/avformat.h   2018-03-13 09:45:00.061310268 -0600
-@@ -504,6 +504,9 @@
-                                         The user or muxer can override this through
-                                         AVFormatContext.avoid_negative_ts
-                                         */
-+#define AVFMT_SEEK_NOSTREAMS  0x80000 /**< Stream index ignored by seek,
-+                                           or some streams fail to seek
-+                                           */
- #define AVFMT_SEEK_TO_PTS   0x4000000 /**< Seeking is based on PTS */
-@@ -664,7 +667,8 @@
-     /**
-      * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
-      * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
--     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
-+     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS,
-+     * AVFMT_SEEK_NOSTREAMS
-      */
-     int flags;
-diff -ur a/libavformat/dv.c b/ffmpeg-3.4.2/libavformat/dv.c
---- a/libavformat/dv.c 2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/dv.c 2018-03-13 09:45:00.061310268 -0600
-@@ -632,6 +632,7 @@
- AVInputFormat ff_dv_demuxer = {
-     .name           = "dv",
-     .long_name      = NULL_IF_CONFIG_SMALL("DV (Digital Video)"),
-+    .flags          = AVFMT_SEEK_NOSTREAMS,
-     .priv_data_size = sizeof(RawDVContext),
-     .read_probe     = dv_probe,
-     .read_header    = dv_read_header,
-diff -ur a/libavformat/matroskadec.c b/libavformat/matroskadec.c
---- a/libavformat/matroskadec.c        2018-02-11 17:29:18.000000000 -0700
-+++ b/libavformat/matroskadec.c        2018-03-13 09:45:00.061310268 -0600
-@@ -3992,6 +3992,7 @@
- AVInputFormat ff_matroska_demuxer = {
-     .name           = "matroska,webm",
-     .long_name      = NULL_IF_CONFIG_SMALL("Matroska / WebM"),
-+    .flags          = AVFMT_SEEK_NOSTREAMS,
-     .extensions     = "mkv,mk3d,mka,mks",
-     .priv_data_size = sizeof(MatroskaDemuxContext),
-     .read_probe     = matroska_probe,
-@@ -4005,6 +4006,7 @@
- AVInputFormat ff_webm_dash_manifest_demuxer = {
-     .name           = "webm_dash_manifest",
-     .long_name      = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"),
-+    .flags          = AVFMT_SEEK_NOSTREAMS,
-     .priv_data_size = sizeof(MatroskaDemuxContext),
-     .read_header    = webm_dash_manifest_read_header,
-     .read_packet    = webm_dash_manifest_read_packet,
-diff -ur a/libavformat/utils.c b/libavformat/utils.c
---- a/libavformat/utils.c      2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/utils.c      2018-03-13 09:45:00.062310270 -0600
-@@ -2416,6 +2416,13 @@
-         return seek_frame_byte(s, stream_index, timestamp, flags);
-     }
-+    if (stream_index != -1 && (s->iformat->flags & AVFMT_SEEK_NOSTREAMS)) {
-+            timestamp = av_rescale_q(timestamp,
-+                    s->streams[stream_index]->time_base,
-+                    AV_TIME_BASE_Q);
-+            stream_index = -1;
-+    }
-+
-     if (stream_index < 0) {
-         stream_index = av_find_default_stream_index(s);
-         if (stream_index < 0)
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch4 b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch4
deleted file mode 100644 (file)
index 8c7cddb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -ur a/libavcodec/libx264.c b/libavcodec/libx264.c
---- a/libavcodec/libx264.c     2018-02-11 17:29:18.000000000 -0700
-+++ b/libavcodec/libx264.c     2018-03-13 09:38:03.241861794 -0600
-@@ -280,7 +280,11 @@
-     x264_picture_init( &x4->pic );
-     x4->pic.img.i_csp   = x4->params.i_csp;
--    if (desc->comp[0].depth > 8)
-+#if X264_BUILD >= 153
-+    if (x4->params.i_bitdepth > 8)
-+#else
-+    if (x264_bit_depth > 8)
-+#endif
-         x4->pic.img.i_csp |= X264_CSP_HIGH_DEPTH;
-     x4->pic.img.i_plane = avfmt2_num_planes(ctx->pix_fmt);
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch5 b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.patch5
deleted file mode 100644 (file)
index f7db4c3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
---- a/libavcodec/libx265.c     2017-12-10 14:35:08.000000000 -0700
-+++ b/libavcodec/libx265.c     2018-02-08 16:57:46.028108824 -0700
-@@ -45,6 +45,7 @@
-     int   forced_idr;
-     char *preset;
-     char *tune;
-+    char *profile;
-     char *x265_opts;
- } libx265Context;
-@@ -114,11 +115,11 @@
-     ctx->params->sourceHeight    = avctx->height;
-     ctx->params->bEnablePsnr     = !!(avctx->flags & AV_CODEC_FLAG_PSNR);
--    if ((avctx->color_primaries <= AVCOL_PRI_BT2020 &&
-+    if ((avctx->color_primaries <= AVCOL_PRI_SMPTE432 &&
-          avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) ||
--        (avctx->color_trc <= AVCOL_TRC_BT2020_12 &&
-+        (avctx->color_trc <= AVCOL_TRC_ARIB_STD_B67 &&
-          avctx->color_trc != AVCOL_TRC_UNSPECIFIED) ||
--        (avctx->colorspace <= AVCOL_SPC_BT2020_CL &&
-+        (avctx->colorspace <= AVCOL_SPC_ICTCP &&
-          avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) {
-         ctx->params->vui.bEnableVideoSignalTypePresentFlag  = 1;
-@@ -220,6 +221,18 @@
-         }
-     }
-+    if (ctx->profile) {
-+        if (ctx->api->param_apply_profile(ctx->params, ctx->profile) < 0) {
-+            int i;
-+            av_log(avctx, AV_LOG_ERROR, "Invalid or incompatible profile set: %s.\n", ctx->profile);
-+            av_log(avctx, AV_LOG_INFO, "Possible profiles:");
-+            for (i = 0; x265_profile_names[i]; i++)
-+                av_log(avctx, AV_LOG_INFO, " %s", x265_profile_names[i]);
-+            av_log(avctx, AV_LOG_INFO, "\n");
-+            return AVERROR(EINVAL);
-+        }
-+    }
-+
-     ctx->encoder = ctx->api->encoder_open(ctx->params);
-     if (!ctx->encoder) {
-         av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
-@@ -294,7 +307,7 @@
-     for (i = 0; i < nnal; i++)
-         payload += nal[i].sizeBytes;
--    ret = ff_alloc_packet(pkt, payload);
-+    ret = ff_alloc_packet2(avctx, pkt, payload, payload);
-     if (ret < 0) {
-         av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
-         return ret;
-@@ -392,6 +412,7 @@
-     { "forced-idr",  "if forcing keyframes, force them as IDR frames",                              OFFSET(forced_idr),AV_OPT_TYPE_BOOL,   { .i64 =  0 },  0,       1, VE },
-     { "preset",      "set the x265 preset",                                                         OFFSET(preset),    AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
-     { "tune",        "set the x265 tune parameter",                                                 OFFSET(tune),      AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
-+    { "profile",     "set the x265 profile",                                                        OFFSET(profile),   AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
-     { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
-     { NULL }
- };
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.tar.xz b/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.tar.xz
deleted file mode 100644 (file)
index e1acc97..0000000
Binary files a/cinelerra-5.1/thirdparty/src/ffmpeg-3.4.2.tar.xz and /dev/null differ
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch1 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch1
new file mode 100644 (file)
index 0000000..831ea60
--- /dev/null
@@ -0,0 +1,12 @@
+diff -urN a/libavformat/bluray.c b/libavformat/bluray.c
+--- a/libavformat/bluray.c     2018-04-13 17:34:28.000000000 -0600
++++ b/libavformat/bluray.c     2018-04-24 11:02:19.724232178 -0600
+@@ -28,7 +28,7 @@
+ #include "libavutil/opt.h"
+ #define BLURAY_PROTO_PREFIX     "bluray:"
+-#define MIN_PLAYLIST_LENGTH     180     /* 3 min */
++#define MIN_PLAYLIST_LENGTH     0
+ typedef struct {
+     const AVClass *class;
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch2 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch2
new file mode 100644 (file)
index 0000000..e05f337
--- /dev/null
@@ -0,0 +1,498 @@
+diff -urN a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
+--- a/libavformat/mpegtsenc.c  2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/mpegtsenc.c  2018-04-24 10:27:57.193689213 -0600
+@@ -56,9 +56,8 @@
+     int sid;           /* service ID */
+     char *name;
+     char *provider_name;
+-    int pcr_pid;
+-    int pcr_packet_count;
+-    int pcr_packet_period;
++    int64_t pcr, pcr_packet_timer, pcr_packet_period;
++    int pcr_sid, pcr_pid;
+     AVProgram *program;
+ } MpegTSService;
+@@ -78,14 +77,12 @@
+     MpegTSSection pat; /* MPEG-2 PAT table */
+     MpegTSSection sdt; /* MPEG-2 SDT table context */
+     MpegTSService **services;
+-    int sdt_packet_count;
+-    int sdt_packet_period;
+-    int pat_packet_count;
+-    int pat_packet_period;
++    int64_t sdt_packet_timer, sdt_packet_period;
++    int64_t pat_packet_timer, pat_packet_period;
+     int nb_services;
+     int onid;
+     int tsid;
+-    int64_t first_pcr;
++    int64_t pcr, first_pcr, delay;
+     int mux_rate; ///< set to 1 when VBR
+     int pes_payload_size;
+@@ -95,12 +92,14 @@
+     int service_type;
+     int pmt_start_pid;
++    int pcr_start_pid;
+     int start_pid;
+     int m2ts_mode;
++    int64_t ts_offset;
+     int reemit_pat_pmt; // backward compatibility
+-    int pcr_period;
++    double pcr_period;
+ #define MPEGTS_FLAG_REEMIT_PAT_PMT  0x01
+ #define MPEGTS_FLAG_AAC_LATM        0x02
+ #define MPEGTS_FLAG_PAT_PMT_AT_FRAMES           0x04
+@@ -111,8 +110,6 @@
+     int tables_version;
+     double pat_period;
+     double sdt_period;
+-    int64_t last_pat_ts;
+-    int64_t last_sdt_ts;
+     int omit_video_pes_length;
+ } MpegTSWrite;
+@@ -222,10 +219,10 @@
+ #define DEFAULT_PROVIDER_NAME   "FFmpeg"
+ #define DEFAULT_SERVICE_NAME    "Service01"
+-/* we retransmit the SI info at this rate */
++/* we retransmit the SI info at this rate (ms) */
+ #define SDT_RETRANS_TIME 500
+ #define PAT_RETRANS_TIME 100
+-#define PCR_RETRANS_TIME 20
++#define PCR_RETRANS_TIME 50
+ typedef struct MpegTSWriteStream {
+     struct MpegTSService *service;
+@@ -721,6 +718,7 @@
+     service->pmt.pid       = ts->pmt_start_pid + ts->nb_services;
+     service->sid           = sid;
+     service->pcr_pid       = 0x1fff;
++    service->pcr_sid       = 0x1fff;
+     service->provider_name = av_strdup(provider_name);
+     service->name          = av_strdup(name);
+     if (!service->provider_name || !service->name)
+@@ -736,18 +734,11 @@
+     return NULL;
+ }
+-static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
+-{
+-    return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
+-           ts->first_pcr;
+-}
+-
+ static void mpegts_prefix_m2ts_header(AVFormatContext *s)
+ {
+     MpegTSWrite *ts = s->priv_data;
+     if (ts->m2ts_mode) {
+-        int64_t pcr = get_pcr(s->priv_data, s->pb);
+-        uint32_t tp_extra_header = pcr % 0x3fffffff;
++        uint32_t tp_extra_header = ts->pcr % 0x3fffffff;
+         tp_extra_header = AV_RB32(&tp_extra_header);
+         avio_write(s->pb, (unsigned char *) &tp_extra_header,
+                    sizeof(tp_extra_header));
+@@ -768,6 +759,7 @@
+     MpegTSService *service;
+     AVStream *st, *pcr_st = NULL;
+     AVDictionaryEntry *title, *provider;
++    double clk_rate;
+     int i, j;
+     const char *service_name;
+     const char *provider_name;
+@@ -776,6 +768,15 @@
+     if (s->max_delay < 0) /* Not set by the caller */
+         s->max_delay = 0;
++    ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
++
++    if (ts->m2ts_mode == -1) {
++        if (av_match_ext(s->url, "m2ts")) {
++            ts->m2ts_mode = 1;
++        } else {
++            ts->m2ts_mode = 0;
++        }
++    }
+     // round up to a whole number of TS packets
+     ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
+@@ -822,6 +823,8 @@
+             service->program          = program;
+         }
+     }
++    if (ts->m2ts_mode > 1)
++        service->pmt.pid = 0x00ff + ts->service_id;
+     ts->pat.pid          = PAT_PID;
+     /* Initialize at 15 so that it wraps and is equal to 0 for the
+@@ -907,10 +910,9 @@
+         ts_st->discontinuity   = ts->flags & MPEGTS_FLAG_DISCONT;
+         /* update PCR pid by using the first video stream */
+         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+-            service->pcr_pid == 0x1fff) {
+-            service->pcr_pid = ts_st->pid;
++            service->pcr_sid == 0x1fff)
+             pcr_st           = st;
+-        }
++
+         if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+             st->codecpar->extradata_size > 0) {
+             AVStream *ast;
+@@ -946,78 +948,47 @@
+     av_freep(&pids);
+     /* if no video stream, use the first stream as PCR */
+-    if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
+-        pcr_st           = s->streams[0];
+-        ts_st            = pcr_st->priv_data;
+-        service->pcr_pid = ts_st->pid;
+-    } else
+-        ts_st = pcr_st->priv_data;
+-
+-    if (ts->mux_rate > 1) {
+-        service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
+-                                     (TS_PACKET_SIZE * 8 * 1000);
+-        ts->sdt_packet_period      = (int64_t)ts->mux_rate * SDT_RETRANS_TIME /
+-                                     (TS_PACKET_SIZE * 8 * 1000);
+-        ts->pat_packet_period      = (int64_t)ts->mux_rate * PAT_RETRANS_TIME /
+-                                     (TS_PACKET_SIZE * 8 * 1000);
+-
+-        if (ts->copyts < 1)
+-            ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
+-    } else {
+-        /* Arbitrary values, PAT/PMT will also be written on video key frames */
+-        ts->sdt_packet_period = 200;
+-        ts->pat_packet_period = 40;
+-        if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+-            int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0);
+-            if (!frame_size) {
+-                av_log(s, AV_LOG_WARNING, "frame size not set\n");
+-                service->pcr_packet_period =
+-                    pcr_st->codecpar->sample_rate / (10 * 512);
+-            } else {
+-                service->pcr_packet_period =
+-                    pcr_st->codecpar->sample_rate / (10 * frame_size);
+-            }
+-        } else {
+-            // max delta PCR 0.1s
+-            // TODO: should be avg_frame_rate
+-            service->pcr_packet_period =
+-                ts_st->user_tb.den / (10 * ts_st->user_tb.num);
+-        }
+-        if (!service->pcr_packet_period)
+-            service->pcr_packet_period = 1;
+-    }
+-
+-    ts->last_pat_ts = AV_NOPTS_VALUE;
+-    ts->last_sdt_ts = AV_NOPTS_VALUE;
+-    // The user specified a period, use only it
+-    if (ts->pat_period < INT_MAX/2) {
+-        ts->pat_packet_period = INT_MAX;
++    if (!pcr_st && s->nb_streams > 0)
++        pcr_st = s->streams[0];
++    if (!pcr_st) {
++        av_log(s, AV_LOG_ERROR, "no streams\n");
++        ret = AVERROR(EINVAL);
++        goto fail;
+     }
+-    if (ts->sdt_period < INT_MAX/2) {
+-        ts->sdt_packet_period = INT_MAX;
++    ts_st  = pcr_st->priv_data;
++    if (service->pcr_sid == 0x1fff)
++        service->pcr_sid   = ts_st->pid;
++    if (service->pcr_pid == 0x1fff)
++        service->pcr_pid   = ts->m2ts_mode > 1 ?
++            0x1000 + ts->service_id : service->pcr_sid ;
++    if (service->pmt.pid == service->pcr_pid) {
++        av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", service->pcr_pid);
++        ret = AVERROR(EINVAL);
++        goto fail;
+     }
++    clk_rate = ts->mux_rate > 1 ? ts->mux_rate : PCR_TIME_BASE;
++    ts->sdt_packet_period      = ts->sdt_period < 0 ? -1 : ts->sdt_period/1000 * clk_rate;
++    ts->pat_packet_period      = ts->pat_period/1000 * clk_rate;
++    service->pcr_packet_period = ts->pcr_period/1000 * clk_rate;
++    if (service->pcr_packet_period < (TS_PACKET_SIZE*8*10))
++        service->pcr_packet_period = (TS_PACKET_SIZE*8*10);
++    av_log(s, AV_LOG_VERBOSE, "clk_rate %f: ticks/pkt %d pcr, %d sdt, %d pmt\n", clk_rate,
++        (int)service->pcr_packet_period, (int)ts->sdt_packet_period, (int)ts->pat_packet_period);
++
++    if (ts->copyts < 1)
++        ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
++
+     // output a PCR as soon as possible
+-    service->pcr_packet_count = service->pcr_packet_period;
+-    ts->pat_packet_count      = ts->pat_packet_period - 1;
+-    ts->sdt_packet_count      = ts->sdt_packet_period - 1;
++    ts->pcr = 0;
++    service->pcr_packet_timer = 0;
++    ts->pat_packet_timer      = 0;
++    ts->sdt_packet_timer      = 0;
+     if (ts->mux_rate == 1)
+         av_log(s, AV_LOG_VERBOSE, "muxrate VBR, ");
+     else
+         av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
+-    av_log(s, AV_LOG_VERBOSE,
+-           "pcr every %d pkts, sdt every %d, pat/pmt every %d pkts\n",
+-           service->pcr_packet_period,
+-           ts->sdt_packet_period, ts->pat_packet_period);
+-
+-    if (ts->m2ts_mode == -1) {
+-        if (av_match_ext(s->url, "m2ts")) {
+-            ts->m2ts_mode = 1;
+-        } else {
+-            ts->m2ts_mode = 0;
+-        }
+-    }
+     return 0;
+@@ -1032,22 +1003,12 @@
+     MpegTSWrite *ts = s->priv_data;
+     int i;
+-    if (++ts->sdt_packet_count == ts->sdt_packet_period ||
+-        (dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
+-        (dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
+-    ) {
+-        ts->sdt_packet_count = 0;
+-        if (dts != AV_NOPTS_VALUE)
+-            ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts);
++    if ( ts->sdt_packet_period >= 0 && ts->pcr >= ts->sdt_packet_timer ) {
++        ts->sdt_packet_timer = ts->pcr + ts->sdt_packet_period;
+         mpegts_write_sdt(s);
+     }
+-    if (++ts->pat_packet_count == ts->pat_packet_period ||
+-        (dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
+-        (dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
+-        force_pat) {
+-        ts->pat_packet_count = 0;
+-        if (dts != AV_NOPTS_VALUE)
+-            ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
++    if (ts->pcr >= ts->pat_packet_timer || force_pat) {
++        ts->pat_packet_timer = ts->pcr + ts->pat_packet_period;
+         mpegts_write_pat(s);
+         for (i = 0; i < ts->nb_services; i++)
+             mpegts_write_pmt(s, ts->services[i]);
+@@ -1089,13 +1050,14 @@
+ {
+     MpegTSWrite *ts = s->priv_data;
+     MpegTSWriteStream *ts_st = st->priv_data;
++    uint32_t pcr_pid = ts_st->service->pcr_pid;
+     uint8_t *q;
+     uint8_t buf[TS_PACKET_SIZE];
+     q    = buf;
+     *q++ = 0x47;
+-    *q++ = ts_st->pid >> 8;
+-    *q++ = ts_st->pid;
++    *q++ = pcr_pid >> 8;
++    *q++ = pcr_pid;
+     *q++ = 0x20 | ts_st->cc;   /* Adaptation only */
+     /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
+     *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
+@@ -1106,7 +1068,7 @@
+     }
+     /* PCR coded into 6 bytes */
+-    q += write_pcr_bits(q, get_pcr(ts, s->pb));
++    q += write_pcr_bits(q, ts->pcr);
+     /* stuffing bytes */
+     memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
+@@ -1175,8 +1137,6 @@
+     uint8_t *q;
+     int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
+     int afc_len, stuffing_len;
+-    int64_t pcr = -1; /* avoid warning */
+-    int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
+     int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
+     av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
+@@ -1186,28 +1146,33 @@
+     is_start = 1;
+     while (payload_size > 0) {
++        ts->pcr = ts->first_pcr + (ts->mux_rate == 1 ?
++            (dts == AV_NOPTS_VALUE ? 0 : (dts - ts->delay) * 300) :
++            // add 11, pcr references the last byte of program clock reference base
++            av_rescale(avio_tell(s->pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate));
++
+         retransmit_si_info(s, force_pat, dts);
+         force_pat = 0;
+         write_pcr = 0;
+-        if (ts_st->pid == ts_st->service->pcr_pid) {
+-            if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
+-                ts_st->service->pcr_packet_count++;
+-            if (ts_st->service->pcr_packet_count >=
+-                ts_st->service->pcr_packet_period) {
+-                ts_st->service->pcr_packet_count = 0;
++        if (ts_st->pid == ts_st->service->pcr_sid) {
++            if( ts->pcr >= ts_st->service->pcr_packet_timer ) {
++                ts_st->service->pcr_packet_timer = ts->pcr + ts_st->service->pcr_packet_period;
+                 write_pcr = 1;
+             }
+         }
+-
++        if (write_pcr && ts_st->service->pcr_sid != ts_st->service->pcr_pid) {
++           mpegts_insert_pcr_only(s, st);
++           continue;
++        }
+         if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
+-            (dts - get_pcr(ts, s->pb) / 300) > delay) {
+-            /* pcr insert gets priority over null packet insert */
+-            if (write_pcr)
+-                mpegts_insert_pcr_only(s, st);
++               (dts - ts->pcr / 300) > ts->delay) {
++           /* pcr insert gets priority over null packet insert */
++           if (write_pcr)
++               mpegts_insert_pcr_only(s, st);
+             else
+-                mpegts_insert_null_packet(s);
+-            /* recalculate write_pcr and possibly retransmit si_info */
++               mpegts_insert_null_packet(s);
++            /* recalculate write_pcr and possibly retransimit si_info */
+             continue;
+         }
+@@ -1217,6 +1182,10 @@
+         val  = ts_st->pid >> 8;
+         if (is_start)
+             val |= 0x40;
++        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
++          st->codecpar->codec_id == AV_CODEC_ID_AC3 &&
++          ts->m2ts_mode > 1)
++            val |= 0x20;
+         *q++      = val;
+         *q++      = ts_st->pid;
+         ts_st->cc = ts_st->cc + 1 & 0xf;
+@@ -1228,7 +1197,7 @@
+         }
+         if (key && is_start && pts != AV_NOPTS_VALUE) {
+             // set Random Access for key frames
+-            if (ts_st->pid == ts_st->service->pcr_pid)
++            if (ts_st->pid == ts_st->service->pcr_sid)
+                 write_pcr = 1;
+             set_af_flag(buf, 0x40);
+             q = get_ts_payload_start(buf);
+@@ -1236,14 +1205,10 @@
+         if (write_pcr) {
+             set_af_flag(buf, 0x10);
+             q = get_ts_payload_start(buf);
+-            // add 11, pcr references the last byte of program clock reference base
+             if (ts->mux_rate > 1)
+-                pcr = get_pcr(ts, s->pb);
+-            else
+-                pcr = (dts - delay) * 300;
+-            if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
++            if (dts != AV_NOPTS_VALUE && dts < ts->pcr / 300)
+                 av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
+-            extend_af(buf, write_pcr_bits(q, pcr));
++            extend_af(buf, write_pcr_bits(q, ts->pcr));
+             q = get_ts_payload_start(buf);
+         }
+         if (is_start) {
+@@ -1344,11 +1309,13 @@
+             *q++ = flags;
+             *q++ = header_len;
+             if (pts != AV_NOPTS_VALUE) {
+-                write_pts(q, flags >> 6, pts);
++                int64_t ts_pts = pts + ts->ts_offset;
++                write_pts(q, flags >> 6, ts_pts);
+                 q += 5;
+             }
+             if (dts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE && dts != pts) {
+-                write_pts(q, 1, dts);
++                int64_t ts_dts = dts + ts->ts_offset;
++                write_pts(q, 1, ts_dts);
+                 q += 5;
+             }
+             if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) {
+@@ -1519,7 +1486,6 @@
+     uint8_t *data = NULL;
+     MpegTSWrite *ts = s->priv_data;
+     MpegTSWriteStream *ts_st = st->priv_data;
+-    const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
+     int64_t dts = pkt->dts, pts = pkt->pts;
+     int opus_samples = 0;
+     int side_data_size;
+@@ -1540,16 +1506,15 @@
+     }
+     if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) {
+-        ts->pat_packet_count = ts->pat_packet_period - 1;
+-        ts->sdt_packet_count = ts->sdt_packet_period - 1;
++        ts->pat_packet_timer = ts->sdt_packet_timer = 0;
+         ts->flags           &= ~MPEGTS_FLAG_REEMIT_PAT_PMT;
+     }
+     if (ts->copyts < 1) {
+         if (pts != AV_NOPTS_VALUE)
+-            pts += delay;
++            pts += 2*ts->delay;
+         if (dts != AV_NOPTS_VALUE)
+-            dts += delay;
++            dts += 2*ts->delay;
+     }
+     if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) {
+@@ -1737,7 +1702,7 @@
+             AVStream *st2 = s->streams[i];
+             MpegTSWriteStream *ts_st2 = st2->priv_data;
+             if (   ts_st2->payload_size
+-               && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > delay/2)) {
++               && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > ts->delay)) {
+                 mpegts_write_pes(s, st2, ts_st2->payload, ts_st2->payload_size,
+                                  ts_st2->payload_pts, ts_st2->payload_dts,
+                                  ts_st2->payload_flags & AV_PKT_FLAG_KEY, stream_id);
+@@ -1908,12 +1873,18 @@
+     { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
+       offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT,
+       { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
++    { "mpegts_pcr_start_pid", "Set the first pid of the PCR.",
++      offsetof(MpegTSWrite, pcr_start_pid), AV_OPT_TYPE_INT,
++      { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
+     { "mpegts_start_pid", "Set the first pid.",
+       offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
+       { .i64 = 0x0100 }, 0x0010, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
+     { "mpegts_m2ts_mode", "Enable m2ts mode.",
+       offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_BOOL,
+-      { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
++      { .i64 = -1 }, -1, 2, AV_OPT_FLAG_ENCODING_PARAM },
++    { "mpegts_pcr_offset", "clock offset.",
++      offsetof(MpegTSWrite, ts_offset), AV_OPT_TYPE_BOOL,
++      { .i64 = 0 }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+     { "muxrate", NULL,
+       offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
+       { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+@@ -1951,15 +1922,15 @@
+     { "omit_video_pes_length", "Omit the PES packet length for video packets",
+       offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL,
+       { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+-    { "pcr_period", "PCR retransmission time in milliseconds",
+-      offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,
+-      { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+-    { "pat_period", "PAT/PMT retransmission time limit in seconds",
++    { "pcr_period", "PCR retransmission time limit in msecs",
++      offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_DOUBLE,
++      { .dbl = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
++    { "pat_period", "PAT/PMT retransmission time limit in msecs",
+       offsetof(MpegTSWrite, pat_period), AV_OPT_TYPE_DOUBLE,
+-      { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+-    { "sdt_period", "SDT retransmission time limit in seconds",
++      { .dbl = PAT_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
++    { "sdt_period", "SDT retransmission time limit in msecs",
+       offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE,
+-      { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
++      { .dbl = SDT_RETRANS_TIME }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+     { NULL },
+ };
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch3 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.patch3
new file mode 100644 (file)
index 0000000..3d64695
--- /dev/null
@@ -0,0 +1,70 @@
+diff -urN a/libavformat/avformat.h b/libavformat/avformat.h
+--- a/libavformat/avformat.h   2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/avformat.h   2018-04-24 11:02:20.777232001 -0600
+@@ -487,6 +487,9 @@
+                                         The user or muxer can override this through
+                                         AVFormatContext.avoid_negative_ts
+                                         */
++#define AVFMT_SEEK_NOSTREAMS  0x80000 /**< Stream index ignored by seek,
++                                           or some streams fail to seek
++                                           */
+ #define AVFMT_SEEK_TO_PTS   0x4000000 /**< Seeking is based on PTS */
+@@ -647,7 +650,8 @@
+     /**
+      * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
+      * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
+-     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
++     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS,
++     * AVFMT_SEEK_NOSTREAMS
+      */
+     int flags;
+diff -urN a/libavformat/dv.c b/libavformat/dv.c
+--- a/libavformat/dv.c 2018-04-13 17:34:28.000000000 -0600
++++ b/libavformat/dv.c 2018-04-24 11:02:20.778232001 -0600
+@@ -632,6 +632,7 @@
+ AVInputFormat ff_dv_demuxer = {
+     .name           = "dv",
+     .long_name      = NULL_IF_CONFIG_SMALL("DV (Digital Video)"),
++    .flags          = AVFMT_SEEK_NOSTREAMS,
+     .priv_data_size = sizeof(RawDVContext),
+     .read_probe     = dv_probe,
+     .read_header    = dv_read_header,
+diff -urN a/libavformat/matroskadec.c b/libavformat/matroskadec.c
+--- a/libavformat/matroskadec.c        2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/matroskadec.c        2018-04-24 11:02:20.779232001 -0600
+@@ -4026,6 +4026,7 @@
+ AVInputFormat ff_matroska_demuxer = {
+     .name           = "matroska,webm",
+     .long_name      = NULL_IF_CONFIG_SMALL("Matroska / WebM"),
++    .flags          = AVFMT_SEEK_NOSTREAMS,
+     .extensions     = "mkv,mk3d,mka,mks",
+     .priv_data_size = sizeof(MatroskaDemuxContext),
+     .read_probe     = matroska_probe,
+@@ -4039,6 +4040,7 @@
+ AVInputFormat ff_webm_dash_manifest_demuxer = {
+     .name           = "webm_dash_manifest",
+     .long_name      = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"),
++    .flags          = AVFMT_SEEK_NOSTREAMS,
+     .priv_data_size = sizeof(MatroskaDemuxContext),
+     .read_header    = webm_dash_manifest_read_header,
+     .read_packet    = webm_dash_manifest_read_packet,
+diff -urN a/libavformat/utils.c b/libavformat/utils.c
+--- a/libavformat/utils.c      2018-04-20 04:02:58.000000000 -0600
++++ b/libavformat/utils.c      2018-04-24 11:02:20.780232001 -0600
+@@ -2471,6 +2471,13 @@
+         return seek_frame_byte(s, stream_index, timestamp, flags);
+     }
++    if (stream_index != -1 && (s->iformat->flags & AVFMT_SEEK_NOSTREAMS)) {
++            timestamp = av_rescale_q(timestamp,
++                    s->streams[stream_index]->time_base,
++                    AV_TIME_BASE_Q);
++            stream_index = -1;
++    }
++
+     if (stream_index < 0) {
+         stream_index = av_find_default_stream_index(s);
+         if (stream_index < 0)
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.tar.xz b/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.tar.xz
new file mode 100644 (file)
index 0000000..38e95dc
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/ffmpeg-4.0.tar.xz differ
index daa9953880fd0b326f34cd17c68f50f0dcdc5a93..831ea60f690cae5dcb149d9b4e02795cd36970ab 100644 (file)
@@ -1,6 +1,6 @@
-diff -ru ffmpeg-3.0.orig/libavformat/bluray.c ffmpeg-3.0/libavformat/bluray.c
---- ffmpeg-3.0.orig/libavformat/bluray.c       2015-03-13 11:34:50.000000000 -0600
-+++ ffmpeg-3.0/libavformat/bluray.c    2016-05-09 14:07:34.758713307 -0600
+diff -urN a/libavformat/bluray.c b/libavformat/bluray.c
+--- a/libavformat/bluray.c     2018-04-13 17:34:28.000000000 -0600
++++ b/libavformat/bluray.c     2018-04-24 11:02:19.724232178 -0600
 @@ -28,7 +28,7 @@
  #include "libavutil/opt.h"
  
index bb628d933ab56c3644aacf12697c4272cb3ca767..e05f3372b15df8897a11cac48b667b2623393e48 100644 (file)
@@ -1,6 +1,6 @@
-diff -ur a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
---- a/libavformat/mpegtsenc.c  2017-12-10 14:35:10.000000000 -0700
-+++ b/libavformat/mpegtsenc.c  2017-12-18 10:54:14.260167666 -0700
+diff -urN a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
+--- a/libavformat/mpegtsenc.c  2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/mpegtsenc.c  2018-04-24 10:27:57.193689213 -0600
 @@ -56,9 +56,8 @@
      int sid;           /* service ID */
      char *name;
@@ -112,7 +112,7 @@ diff -ur a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
 +    ts->delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
 +
 +    if (ts->m2ts_mode == -1) {
-+        if (av_match_ext(s->filename, "m2ts")) {
++        if (av_match_ext(s->url, "m2ts")) {
 +            ts->m2ts_mode = 1;
 +        } else {
 +            ts->m2ts_mode = 0;
@@ -245,7 +245,7 @@ diff -ur a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
 -           ts->sdt_packet_period, ts->pat_packet_period);
 -
 -    if (ts->m2ts_mode == -1) {
--        if (av_match_ext(s->filename, "m2ts")) {
+-        if (av_match_ext(s->url, "m2ts")) {
 -            ts->m2ts_mode = 1;
 -        } else {
 -            ts->m2ts_mode = 0;
index 36699eea10294925b64d1535c27d52515cf13a8a..3d64695a357199150f6ee790baa8da79d75e1f99 100644 (file)
@@ -1,7 +1,7 @@
-diff -ur a/libavformat/avformat.h b/libavformat/avformat.h
---- a/libavformat/avformat.h   2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/avformat.h   2018-03-13 09:45:00.061310268 -0600
-@@ -504,6 +504,9 @@
+diff -urN a/libavformat/avformat.h b/libavformat/avformat.h
+--- a/libavformat/avformat.h   2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/avformat.h   2018-04-24 11:02:20.777232001 -0600
+@@ -487,6 +487,9 @@
                                          The user or muxer can override this through
                                          AVFormatContext.avoid_negative_ts
                                          */
@@ -11,7 +11,7 @@ diff -ur a/libavformat/avformat.h b/libavformat/avformat.h
  
  #define AVFMT_SEEK_TO_PTS   0x4000000 /**< Seeking is based on PTS */
  
-@@ -664,7 +667,8 @@
+@@ -647,7 +650,8 @@
      /**
       * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
       * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
@@ -21,9 +21,9 @@ diff -ur a/libavformat/avformat.h b/libavformat/avformat.h
       */
      int flags;
  
-diff -ur a/libavformat/dv.c b/ffmpeg-3.4.2/libavformat/dv.c
---- a/libavformat/dv.c 2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/dv.c 2018-03-13 09:45:00.061310268 -0600
+diff -urN a/libavformat/dv.c b/libavformat/dv.c
+--- a/libavformat/dv.c 2018-04-13 17:34:28.000000000 -0600
++++ b/libavformat/dv.c 2018-04-24 11:02:20.778232001 -0600
 @@ -632,6 +632,7 @@
  AVInputFormat ff_dv_demuxer = {
      .name           = "dv",
@@ -32,10 +32,10 @@ diff -ur a/libavformat/dv.c b/ffmpeg-3.4.2/libavformat/dv.c
      .priv_data_size = sizeof(RawDVContext),
      .read_probe     = dv_probe,
      .read_header    = dv_read_header,
-diff -ur a/libavformat/matroskadec.c b/libavformat/matroskadec.c
---- a/libavformat/matroskadec.c        2018-02-11 17:29:18.000000000 -0700
-+++ b/libavformat/matroskadec.c        2018-03-13 09:45:00.061310268 -0600
-@@ -3992,6 +3992,7 @@
+diff -urN a/libavformat/matroskadec.c b/libavformat/matroskadec.c
+--- a/libavformat/matroskadec.c        2018-04-20 04:02:57.000000000 -0600
++++ b/libavformat/matroskadec.c        2018-04-24 11:02:20.779232001 -0600
+@@ -4026,6 +4026,7 @@
  AVInputFormat ff_matroska_demuxer = {
      .name           = "matroska,webm",
      .long_name      = NULL_IF_CONFIG_SMALL("Matroska / WebM"),
@@ -43,7 +43,7 @@ diff -ur a/libavformat/matroskadec.c b/libavformat/matroskadec.c
      .extensions     = "mkv,mk3d,mka,mks",
      .priv_data_size = sizeof(MatroskaDemuxContext),
      .read_probe     = matroska_probe,
-@@ -4005,6 +4006,7 @@
+@@ -4039,6 +4040,7 @@
  AVInputFormat ff_webm_dash_manifest_demuxer = {
      .name           = "webm_dash_manifest",
      .long_name      = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"),
@@ -51,10 +51,10 @@ diff -ur a/libavformat/matroskadec.c b/libavformat/matroskadec.c
      .priv_data_size = sizeof(MatroskaDemuxContext),
      .read_header    = webm_dash_manifest_read_header,
      .read_packet    = webm_dash_manifest_read_packet,
-diff -ur a/libavformat/utils.c b/libavformat/utils.c
---- a/libavformat/utils.c      2018-02-11 17:29:06.000000000 -0700
-+++ b/libavformat/utils.c      2018-03-13 09:45:00.062310270 -0600
-@@ -2416,6 +2416,13 @@
+diff -urN a/libavformat/utils.c b/libavformat/utils.c
+--- a/libavformat/utils.c      2018-04-20 04:02:58.000000000 -0600
++++ b/libavformat/utils.c      2018-04-24 11:02:20.780232001 -0600
+@@ -2471,6 +2471,13 @@
          return seek_frame_byte(s, stream_index, timestamp, flags);
      }