From: Good Guy Date: Sat, 11 Jul 2020 00:58:35 +0000 (-0600) Subject: ffmpeg scan remap fix, configure.ac all or none fix, 3rd party libs: ffmpeg, turbo... X-Git-Tag: 2020-07~8 X-Git-Url: https://cinelerra-gg.org/git/?a=commitdiff_plain;h=d830901b11606a7838791bc45e39130329db99f0;p=goodguy%2Fcinelerra.git ffmpeg scan remap fix, configure.ac all or none fix, 3rd party libs: ffmpeg, turbo-jpeg, vorbis, x265, vpx, lv2, aom, dav1d, ffnvcodec --- diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 23549f9a..5ff87abc 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -3541,7 +3541,25 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) av_dict_copy(&copts, opts, 0); AVStream *st = fmt_ctx->streams[i]; AVCodecID codec_id = st->codecpar->codec_id; - AVCodec *decoder = avcodec_find_decoder(codec_id); + AVCodec *decoder = 0; + switch( st->codecpar->codec_type ) { + case AVMEDIA_TYPE_VIDEO: + if( opt_video_decoder ) + decoder = avcodec_find_decoder_by_name(opt_video_decoder); + else + video_codec_remaps.update(codec_id, decoder); + break; + case AVMEDIA_TYPE_AUDIO: + if( opt_audio_decoder ) + decoder = avcodec_find_decoder_by_name(opt_audio_decoder); + else + audio_codec_remaps.update(codec_id, decoder); + break; + default: + continue; + } + if( !decoder && !(decoder = avcodec_find_decoder(codec_id)) ) + continue; AVCodecContext *avctx = avcodec_alloc_context3(decoder); if( !avctx ) { eprintf(_("cant allocate codec context\n")); @@ -3622,8 +3640,8 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) if( vidx < 0 ) break; FFVideoStream *vid = ffvideo[vidx]; if( !vid->avctx ) break; - int64_t tstmp = pkt.dts; - if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.pts; + int64_t tstmp = pkt.pts; + if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.dts; if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) { if( vid->nudge != AV_NOPTS_VALUE ) tstmp -= vid->nudge; double secs = to_secs(tstmp, st->time_base); diff --git a/cinelerra-5.1/configure.ac b/cinelerra-5.1/configure.ac index daa267f0..1d00a435 100644 --- a/cinelerra-5.1/configure.ac +++ b/cinelerra-5.1/configure.ac @@ -189,7 +189,7 @@ PKG_3RD([esound],[no], [ . ]) PKG_3RD([ffmpeg],[yes], - [ffmpeg-4.2], + [ffmpeg-4.3], [ libavutil/libavutil.a \ libavcodec/libavcodec.a \ libpostproc/libpostproc.a \ @@ -270,7 +270,7 @@ PKG_3RD([libdv],[auto], [ . ]) PKG_3RD([libjpeg],[auto], - [libjpeg-turbo-2.0.4], + [libjpeg-turbo-2.0.5], [ build/libjpeg.a \ build/libturbojpeg.a ], [ opt/libjpeg-turbo/include ]) @@ -311,7 +311,7 @@ PKG_3RD([libuuid],[yes], [ . ]) PKG_3RD([libvorbis],[auto], - [libvorbis-1.3.6], + [libvorbis-1.3.7], [ lib/.libs/libvorbis.a \ lib/.libs/libvorbisenc.a \ lib/.libs/libvorbisfile.a ], @@ -369,17 +369,17 @@ PKG_3RD([x264],[auto], [ . ]) PKG_3RD([x265],[auto], - [x265_3.2.1], + [x265_3.4], [ libx265.a ], [ . source ]) PKG_3RD([libvpx],[auto], - [libvpx-1.8.1], + [libvpx-1.8.2], [ libvpx.a ], [ . ]) PKG_3RD([lv2],[auto], - [lv2-1.16.0], + [lv2-1.18.0], [ ], [ usr/local/include usr/local/lib64/lv2 usr/local/lib/lv2 ]) @@ -389,7 +389,7 @@ PKG_3RD([sratom],[auto], [ usr/local/include ]) PKG_3RD([serd],[auto], - [serd-0.30.2], + [serd-0.30.4], [ usr/local/lib/libserd-0.a ], [ usr/local/include ]) @@ -399,7 +399,7 @@ PKG_3RD([sord],[auto], [ usr/local/include ]) PKG_3RD([lilv],[auto], - [lilv-0.24.6], + [lilv-0.24.8], [ usr/local/lib/liblilv-0.a ], [ usr/local/include ]) @@ -409,12 +409,12 @@ PKG_3RD([suil],[auto], [ usr/local/include ]) PKG_3RD([libaom],[auto], - [libaom-v1.0.0], + [libaom-v3.0.0], [ usr/local/lib*/libaom*.a ], [ usr/local/include ]) PKG_3RD([dav1d],[auto], - [dav1d-0.5.1], + [dav1d-0.7.1], [ usr/local/lib*/libdav1d*.a ], [ usr/local/include ]) @@ -673,9 +673,9 @@ test "x$HAVE_libavc1394" = "xyes" && \ test "x$HAVE_libiec61883" = "xyes" && \ test "x$HAVE_libraw1394" = "xyes" && \ HAVE_FIREWIRE=yes || \ -HAVE_libavc1394=no && \ -HAVE_libiec61883=no && \ -HAVE_libraw1394=no && \ +HAVE_libavc1394=no \ +HAVE_libiec61883=no \ +HAVE_libraw1394=no \ HAVE_FIREWIRE=no CHECK_WANT([DV], [auto], [use dv], [ @@ -700,8 +700,8 @@ CHECK_WANT([ESOUND], [no], [use esd], [ test "x$HAVE_esound" = "xyes" && \ test "x$HAVE_audiofile" = "xyes" && \ HAVE_ESOUND=yes || \ -HAVE_esound=no && \ -HAVE_audiofile=no && \ +HAVE_esound=no \ +HAVE_audiofile=no \ HAVE_ESOUND=no CHECK_WANT([PULSE], [auto], [use pulseaudio], [ @@ -749,12 +749,12 @@ test "x$HAVE_serd" = "xyes" && \ test "x$HAVE_sratom" = "xyes" && \ test "x$HAVE_suil" = "xyes" && \ HAVE_LV2=yes || \ -HAVE_lv2=no && \ -HAVE_lilv=no && \ -HAVE_sord=no && \ -HAVE_serd=no && \ -HAVE_sratom=no && \ -HAVE_suil=no && \ +HAVE_lv2=no \ +HAVE_lilv=no \ +HAVE_sord=no \ +HAVE_serd=no \ +HAVE_sratom=no \ +HAVE_suil=no \ HAVE_LV2=no CHECK_WANT([CUDA], [auto], [build cuda plugins], [ @@ -813,8 +813,8 @@ AC_SUBST([HAVE_OPENEXR]) test "x$HAVE_openexr" = "xyes" && \ test "x$HAVE_ilmbase" = "xyes" && \ HAVE_OPENEXR=yes || \ -HAVE_openexr=no && \ -HAVE_ilmbase=no && +HAVE_openexr=no \ +HAVE_ilmbase=no \ HAVE_OPENEXR=no # build global_config diff --git a/cinelerra-5.1/ffmpeg/plugin.opts b/cinelerra-5.1/ffmpeg/plugin.opts index 20041941..ae5822d8 100644 --- a/cinelerra-5.1/ffmpeg/plugin.opts +++ b/cinelerra-5.1/ffmpeg/plugin.opts @@ -376,7 +376,18 @@ vibrance #sr ###Input/output error #xstack ###Operation not permitted #agraphmonitor ###Input/output error -; the ffmpeg system library on Arch has these errors: +; broken in 4.3 +#anlms ###Input/output error +#axcorrelate ###Input/output error +#freezeframes ###Input/output error +#maskedmax ###Input/output error +#maskedmin ###Input/output error +#maskedthreshold ###Input/output error +#overlay_cuda ###Input/output error +#xfade ###Input/output error +#arnndn ###Invalid argument +#dnn_processing ###Invalid argument +#; the ffmpeg system library on Arch has these errors: #ladspa #ass #drawtext diff --git a/cinelerra-5.1/thirdparty/Makefile b/cinelerra-5.1/thirdparty/Makefile index 0be2898e..17603e1a 100644 --- a/cinelerra-5.1/thirdparty/Makefile +++ b/cinelerra-5.1/thirdparty/Makefile @@ -198,10 +198,10 @@ giflib.cfg_params=echo "exec true" > ./configure; chmod +x ./configure; lame.cfg_vars?= CFLAGS+=" -O" lame.cfg_params?=--enable-shared=no lame.mak_params?= ; cd $(call bld_path,lame,include); ln -sf . lame -libaom.cfg_vars?=$(call cmake_config,aom-master) +libaom.cfg_vars?= mkdir aom.build && cd aom.build && $(call cmake_config,..) libaom.cfg_params?= -DENABLE_SHARED=no -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_INSTALL_PREFIX=$(call bld_path,libaom)/usr/local -libaom.mak_params?= ; $(MAKE) -C libaom* install +libaom.mak_params?= ; $(MAKE) -C libaom*/aom.build install dav1d.cfg_vars?=echo "echo dav1d custom make" >> configure; chmod +x ./configure; dav1d.mak_params?=; $(MAKE) -C dav1d* install DESTDIR="$(call bld_path,dav1d)" libwebp.cfg_vars?= mkdir build && cd build && $(call cmake_config,..) diff --git a/cinelerra-5.1/thirdparty/downloads.txt b/cinelerra-5.1/thirdparty/downloads.txt index cb23cf27..45102d69 100644 --- a/cinelerra-5.1/thirdparty/downloads.txt +++ b/cinelerra-5.1/thirdparty/downloads.txt @@ -2,8 +2,8 @@ https://www.dechifro.org/dcraw/dcraw.c http://download-mirror.savannah.gnu.org/releases//openexr/ilmbase-2.2.1.tar.gz http://gnu.mirrors.pair.com/savannah/savannah//openexr/openexr-2.2.1.tar.gz -https://sourceforge.net/projects/opencvlibrary/files/ -https://github.com/opencv/opencv_contrib/archive/ +https://sourceforge.net/projects/opencvlibrary/files/ 4.3.0 +https://github.com/opencv/opencv_contrib/releases 4.3.0 #https://sourceforge.net/projects/opencore-amr/files/fdk-aac/fdk-aac-2.2.0.tar.gz/download http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.28.tar.gz https://ieee1394.wiki.kernel.org/index.php/Libraries @@ -14,7 +14,7 @@ https://sourceforge.net/projects/libdv/files/latest/download?source=directory = https://sourceforge.net/projects/giflib/files/latest/download = 5.2.1 https://sourceforge.net/projects/flac/files/latest/download?source=directory = 1.3.2 https://github.com/uclouvain/openjpeg/ = Releases=sourcefiles openjpeg-2.3.1.tar.gz -https://sourceforge.net/projects/libjpeg-turbo/ = Code (GitHub)=sourcefiles/2.0.4/libjpeg-turbo-2.0.4.tar.gz +https://sourceforge.net/projects/libjpeg-turbo/ = Code (GitHub)=sourcefiles/2.0.5/libjpeg-turbo-2.0.5.tar.gz http://www.fftw.org/fftw-3.3.8.tar.gz http://festvox.org/packed/festival/2.4/festival-2.4-release.tar.gz http://festvox.org/packed/festival/2.4/speech_tools-2.4-release.tar.gz @@ -24,28 +24,28 @@ http://festvox.org/packed/festival/2.4/voices/festvox_cmu_us_ahw_cg.tar.gz #http://ftp.gnome.org/pub/gnome/sources/esound/0.2/esound-0.2.41.tar.bz2 http://audiofile.68k.org/audiofile-0.3.6.tar.gz https://sourceforge.net/projects/twolame/ = GitHub / Releases = Source Code=twolame-0.4.0.tar.gz -http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.tar.xz +http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz http://downloads.xiph.org/releases/ogg/libogg-1.3.4.tar.gz http://downloads.xiph.org/releases/theora/libtheora-1.1.1.tar.bz2 https://sourceforge.net/projects/lame/files/latest/download?source=directory = 3.100 https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz https://sourceforge.net/projects/libuuid/files/latest/download?source=directory - 1.0.3 ftp://ftp.videolan.org/pub/x264/snapshots/x264-snapshot-20191217-2245-stable.tar.bz2 -https://bitbucket.org/multicoreware/x265/downloads/x265_3.2.1.tar.gz -https://ffmpeg.org/releases/ffmpeg-4.2.tar.bz2 -https://github.com/webmproject/libvpx/archive/v1.8.1.tar.gz -https://code.videolan.org/videolan/dav1d/-/archive/0.5.1/dav1d-0.5.1.tar.gz +https://bitbucket.org/multicoreware/x265/downloads/x265_3.4.tar.gz +https://ffmpeg.org/releases/ffmpeg-4.3.tar.bz2 +https://github.com/webmproject/libvpx/archive/v1.8.2.tar.gz +https://code.videolan.org/videolan/dav1d/-/archive/0.7.1/dav1d-0.7.1.tar.gz https://github.com/swh/ladspa/releases/tag/v0.4.17, plugin.org.uk https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz https://github.com/webmproject/libwebp = libwebp-1.1.0 -https://github.com/mozilla/aom = libaom-v1.0.0 +https://github.com/mozilla/aom = libaom-v2.0.0 git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git ?? -https://github.com/FFmpeg/nv-codec-headers/releases/download/n9.1.23.1/nv-codec-headers-9.1.23.1.tar.gz +https://github.com/FFmpeg/nv-codec-headers/releases/download/n10.0.26.0/nv-codec-headers-10.0.26.0.tar.gz -https://gitlab.com/drobilla/lv2/-/archive/v1.16.0/lv2-v1.16.0.tar.gz +https://gitlab.com/drobilla/lv2/-/archive/v1.18.0/lv2-v1.18.0.tar.gz http://download.drobilla.net/suil-0.10.6.tar.bz2 http://download.drobilla.net/sratom-0.6.4.tar.bz2 -http://download.drobilla.net/lilv-0.24.6.tar.bz2 +http://download.drobilla.net/lilv-0.24.8.tar.bz2 http://download.drobilla.net/sord-0.16.4.tar.bz2 -http://download.drobilla.net/serd-0.30.2.tar.bz2 +http://download.drobilla.net/serd-0.30.4.tar.bz2 http://download.drobilla.net/jalv-1.6.4.tar.bz2 diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz deleted file mode 100644 index 805f750d..00000000 Binary files a/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 b/cinelerra-5.1/thirdparty/src/dav1d-0.7.1.patch1 similarity index 92% rename from cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 rename to cinelerra-5.1/thirdparty/src/dav1d-0.7.1.patch1 index d4f2b835..67142170 100644 --- a/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 +++ b/cinelerra-5.1/thirdparty/src/dav1d-0.7.1.patch1 @@ -1,7 +1,7 @@ -diff -urN a/Makefile b/Makefile ---- a/Makefile 1969-12-31 17:00:00.000000000 -0700 -+++ b/Makefile 2019-10-14 10:54:47.354841430 -0600 -@@ -0,0 +1,363 @@ +diff -ruN dav1d-0.7.1.orig/Makefile dav1d-0.7.1/Makefile +--- dav1d-0.7.1.orig/Makefile 1969-12-31 17:00:00.000000000 -0700 ++++ dav1d-0.7.1/Makefile 2020-07-09 20:10:47.066626832 -0600 +@@ -0,0 +1,371 @@ + +_ARCH := $(shell uname -m) +ARCH_I32 := $(shell expr "x$(_ARCH)" : 'xi[346]86.*') @@ -36,7 +36,7 @@ diff -urN a/Makefile b/Makefile + +STATIC_LIB=$(BUILD)/src/libdav1d.a +SHARED_LIB=$(BUILD)/src/libdav1d.so -+DEFS= -DNDEBUG -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200112L ++DEFS= -DNDEBUG -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE +FUZZ= -DDAV1D_MT_FUZZING + +BLD_INCL= $(DEFS) -I. -Isrc -Iinclude/dav1d -Iinclude \ @@ -78,7 +78,7 @@ diff -urN a/Makefile b/Makefile + -fomit-frame-pointer \ + -ffast-math \ + -fPIC \ -+ -mpreferred-stack-boundary=5 \ ++ -mpreferred-stack-boundary=6 \ + -MD -MQ $@ -MF $@.d \ + +SHA_OPTS=\ @@ -88,9 +88,9 @@ diff -urN a/Makefile b/Makefile + -shared \ + -fPIC \ + -Wl,--start-group \ -+ -Wl,-soname,libdav1d.so.2 \ ++ -Wl,-soname,libdav1d.so.3 \ + -Wl,--end-group \ -+ -pthread \ ++ -pthread -ldl \ + +CC_CC=$(Q)cc $(CC_OPTS) $(CFLAGS) +NASM=$(Q)/usr/bin/nasm @@ -98,11 +98,13 @@ diff -urN a/Makefile b/Makefile + +# nasm +NASM_OBJS=$(call any,$(NASM_BLD), \ -+ cdef.obj \ ++ cdef_avx512.obj \ ++ cdef_avx2.obj \ + film_grain.obj \ + ipred.obj \ + itx.obj \ + cdef_sse.obj \ ++ film_grain_ssse3.obj \ + ipred_ssse3.obj \ + loopfilter.obj \ + looprestoration.obj \ @@ -110,7 +112,7 @@ diff -urN a/Makefile b/Makefile + itx_ssse3.obj \ + looprestoration_ssse3.obj \ + loopfilter_ssse3.obj \ -+ mc_ssse3.obj \ ++ mc_sse.obj \ + cpuid.obj \ + msac.obj ) + @@ -136,6 +138,7 @@ diff -urN a/Makefile b/Makefile + dequant_tables.o \ + getbits.o \ + intra_edge.o \ ++ itx_1d.o \ + lf_mask.o \ + log.o \ + msac.o \ @@ -143,12 +146,13 @@ diff -urN a/Makefile b/Makefile + picture.o \ + qm.o \ + ref.o \ -+ ref_mvs.o \ ++ refmvs.o \ + scan.o \ + tables.o \ + warpmv.o \ + wedge.o \ -+ x86/cpu.c.o) ++ x86/cpu.c.o \ ++ x86/msac_init.c.o) +$(SRC_BLD)/%.o: src/%.c + $(CC_CC) $(BLD_INCL) -pthread -o $@ -c $< +$(SRC_BLD)/x86/%.c.o: src/x86/%.c @@ -202,6 +206,9 @@ diff -urN a/Makefile b/Makefile + echo >> $@ "#define CONFIG_LOG 1" + echo >> $@ "#define ENDIANNESS_BIG 0" + echo >> $@ "#define HAVE_ASM 1" ++ echo >> $@ "#define HAVE_AVX512ICL 1" ++ echo >> $@ "#define HAVE_CLOCK_GETTIME 1" ++ echo >> $@ "#define HAVE_DLSYM 1" + echo >> $@ "#define HAVE_POSIX_MEMALIGN 1" + echo >> $@ "#define HAVE_UNISTD_H 1" + echo >> $@ "#define STACK_ALIGNMENT 32" @@ -211,16 +218,17 @@ diff -urN a/Makefile b/Makefile + echo >> $@ "%define ARCH_X86_64 $(ARCH_X86_64)" + echo >> $@ "%define PIC 1" + echo >> $@ "%define STACK_ALIGNMENT 32" ++ echo >> $@ "%define HAVE_AVX512ICL 1" + +$(BUILD)/include/vcs_version.h: + mkdir -p $(BUILD)/include -+ echo > $@ "#define DAV1D_VERSION \"0.5.0\"" ++ echo > $@ "#define DAV1D_VERSION \"0.7.1\"" + +$(BUILD)/include/dav1d/version.h: + mkdir -p $(BUILD)/include/dav1d + echo > $@ "#ifndef DAV1D_VERSION_H" + echo >> $@ "#define DAV1D_VERSION_H" -+ echo >> $@ "#define DAV1D_API_VERSION_MAJOR 2" ++ echo >> $@ "#define DAV1D_API_VERSION_MAJOR 3" + echo >> $@ "#define DAV1D_API_VERSION_MINOR 0" + echo >> $@ "#define DAV1D_API_VERSION_PATCH 0" + echo >> $@ "#endif /* DAV1D_VERSION_H */" diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.7.1.tar.xz b/cinelerra-5.1/thirdparty/src/dav1d-0.7.1.tar.xz new file mode 100644 index 00000000..04cf8d60 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/dav1d-0.7.1.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch0 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch0 deleted file mode 100644 index 1a2cacbe..00000000 --- a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch0 +++ /dev/null @@ -1,11 +0,0 @@ -diff -ru a/fftools/cmdutils.c b/fftools/cmdutils.c ---- a/fftools/cmdutils.c 2019-07-08 11:45:25.000000000 -0600 -+++ b/fftools/cmdutils.c 2019-08-08 17:19:36.357374727 -0600 -@@ -1179,6 +1179,7 @@ - - void show_banner(int argc, char **argv, const OptionDef *options) - { -+ return; - int idx = locate_option(argc, argv, options, "version"); - if (hide_banner || idx) - return; diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch2 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch2 deleted file mode 100644 index 1862e19c..00000000 --- a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch2 +++ /dev/null @@ -1,498 +0,0 @@ -diff -ru a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c ---- a/libavformat/mpegtsenc.c 2019-08-05 14:52:21.000000000 -0600 -+++ b/libavformat/mpegtsenc.c 2019-08-08 17:22:07.392150886 -0600 -@@ -56,9 +56,8 @@ - int sid; /* service ID */ - uint8_t name[256]; - uint8_t provider_name[256]; -- 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; -@@ -730,6 +727,7 @@ - service->pmt.pid = ts->pmt_start_pid + ts->nb_services; - service->sid = sid; - service->pcr_pid = 0x1fff; -+ service->pcr_sid = 0x1fff; - if (encode_str8(service->provider_name, provider_name) < 0 || - encode_str8(service->name, name) < 0) { - av_log(s, AV_LOG_ERROR, "Too long service or provider name\n"); -@@ -744,18 +742,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)); -@@ -776,6 +767,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; -@@ -784,6 +776,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; -@@ -830,6 +831,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 -@@ -915,10 +918,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; -@@ -954,78 +956,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; - -@@ -1040,22 +1011,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]); -@@ -1097,13 +1058,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 */ -@@ -1114,7 +1076,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)); -@@ -1183,8 +1145,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); -@@ -1194,28 +1154,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; - } - -@@ -1225,6 +1190,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; -@@ -1236,7 +1205,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); -@@ -1244,14 +1213,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) { -@@ -1352,11 +1317,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) { -@@ -1527,7 +1494,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; -@@ -1548,16 +1514,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) { -@@ -1745,7 +1710,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); -@@ -1914,12 +1879,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 }, -@@ -1957,15 +1928,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.3.patch0 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch0 new file mode 100644 index 00000000..a8e05fc5 --- /dev/null +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch0 @@ -0,0 +1,11 @@ +diff -ruN a/fftools/cmdutils.c b/fftools/cmdutils.c +--- a/fftools/cmdutils.c 2020-06-15 12:54:23.000000000 -0600 ++++ b/fftools/cmdutils.c 2020-07-10 09:18:59.703677305 -0600 +@@ -1183,6 +1183,7 @@ + + void show_banner(int argc, char **argv, const OptionDef *options) + { ++ return; + int idx = locate_option(argc, argv, options, "version"); + if (hide_banner || idx) + return; diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch1 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch1 similarity index 100% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch1 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch1 diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch2 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch2 new file mode 100644 index 00000000..81cae5e6 --- /dev/null +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch2 @@ -0,0 +1,1335 @@ +diff -u a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c +--- a/libavformat/mpegtsenc.c 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavformat/mpegtsenc.c 2020-07-10 11:21:45.303839343 -0600 +@@ -56,7 +56,8 @@ + int sid; /* service ID */ + uint8_t name[256]; + uint8_t provider_name[256]; +- int pcr_pid; ++ int64_t pcr, pcr_packet_timer, pcr_packet_period; ++ int pcr_sid, pcr_pid; + AVProgram *program; + } MpegTSService; + +@@ -76,11 +77,12 @@ + MpegTSSection pat; /* MPEG-2 PAT table */ + MpegTSSection sdt; /* MPEG-2 SDT table context */ + MpegTSService **services; +- int64_t sdt_period; /* SDT period in PCR time base */ +- int64_t pat_period; /* PAT/PMT period in PCR time base */ ++ int64_t sdt_packet_timer, sdt_packet_period; ++ int64_t pat_packet_timer, pat_packet_period; + int nb_services; +- int64_t first_pcr; +- int64_t next_pcr; ++ int onid; ++ int tsid; ++ int64_t pcr, first_pcr, delay; + int mux_rate; ///< set to 1 when VBR + int pes_payload_size; + +@@ -90,14 +92,14 @@ + int service_type; + + int pmt_start_pid; ++ int pcr_start_pid; + int start_pid; + int m2ts_mode; +- int m2ts_video_pid; +- int m2ts_audio_pid; +- int m2ts_pgssub_pid; +- int m2ts_textsub_pid; ++ int64_t ts_offset; + +- int pcr_period_ms; ++ int reemit_pat_pmt; // backward compatibility ++ ++ double pcr_period; + #define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01 + #define MPEGTS_FLAG_AAC_LATM 0x02 + #define MPEGTS_FLAG_PAT_PMT_AT_FRAMES 0x04 +@@ -106,10 +108,8 @@ + int flags; + int copyts; + int tables_version; +- int64_t pat_period_us; +- int64_t sdt_period_us; +- int64_t last_pat_ts; +- int64_t last_sdt_ts; ++ double pat_period; ++ double sdt_period; + + int omit_video_pes_length; + } MpegTSWrite; +@@ -217,14 +217,15 @@ + /* mpegts writer */ + + #define DEFAULT_PROVIDER_NAME "FFmpeg" +-#define DEFAULT_SERVICE_NAME "Service" ++#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; + int pid; /* stream associated pid */ + int cc; + int discontinuity; +@@ -236,10 +237,7 @@ + int payload_flags; + uint8_t *payload; + AVFormatContext *amux; +- int data_st_warning; +- +- int64_t pcr_period; /* PCR period in PCR time base */ +- int64_t last_pcr; ++ AVRational user_tb; + + /* For Opus */ + int opus_queued_samples; +@@ -259,7 +257,7 @@ + put16(&q, service->sid); + put16(&q, 0xe000 | service->pmt.pid); + } +- mpegts_write_section1(&ts->pat, PAT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, ++ mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, ts->tables_version, 0, 0, + data, q - data); + } + +@@ -281,148 +279,6 @@ + *q_ptr = q; + } + +-static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) +-{ +- MpegTSWrite *ts = s->priv_data; +- MpegTSWriteStream *ts_st = st->priv_data; +- int stream_type; +- +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_MPEG1VIDEO: +- case AV_CODEC_ID_MPEG2VIDEO: +- stream_type = STREAM_TYPE_VIDEO_MPEG2; +- break; +- case AV_CODEC_ID_MPEG4: +- stream_type = STREAM_TYPE_VIDEO_MPEG4; +- break; +- case AV_CODEC_ID_H264: +- stream_type = STREAM_TYPE_VIDEO_H264; +- break; +- case AV_CODEC_ID_HEVC: +- stream_type = STREAM_TYPE_VIDEO_HEVC; +- break; +- case AV_CODEC_ID_CAVS: +- stream_type = STREAM_TYPE_VIDEO_CAVS; +- break; +- case AV_CODEC_ID_DIRAC: +- stream_type = STREAM_TYPE_VIDEO_DIRAC; +- break; +- case AV_CODEC_ID_VC1: +- stream_type = STREAM_TYPE_VIDEO_VC1; +- break; +- case AV_CODEC_ID_MP2: +- case AV_CODEC_ID_MP3: +- if ( st->codecpar->sample_rate > 0 +- && st->codecpar->sample_rate < 32000) { +- stream_type = STREAM_TYPE_AUDIO_MPEG2; +- } else { +- stream_type = STREAM_TYPE_AUDIO_MPEG1; +- } +- break; +- case AV_CODEC_ID_AAC: +- stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) +- ? STREAM_TYPE_AUDIO_AAC_LATM +- : STREAM_TYPE_AUDIO_AAC; +- break; +- case AV_CODEC_ID_AAC_LATM: +- stream_type = STREAM_TYPE_AUDIO_AAC_LATM; +- break; +- case AV_CODEC_ID_AC3: +- stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) +- ? STREAM_TYPE_PRIVATE_DATA +- : STREAM_TYPE_AUDIO_AC3; +- break; +- case AV_CODEC_ID_EAC3: +- stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) +- ? STREAM_TYPE_PRIVATE_DATA +- : STREAM_TYPE_AUDIO_EAC3; +- break; +- case AV_CODEC_ID_DTS: +- stream_type = STREAM_TYPE_AUDIO_DTS; +- break; +- case AV_CODEC_ID_TRUEHD: +- stream_type = STREAM_TYPE_AUDIO_TRUEHD; +- break; +- case AV_CODEC_ID_OPUS: +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- case AV_CODEC_ID_TIMED_ID3: +- stream_type = STREAM_TYPE_METADATA; +- break; +- case AV_CODEC_ID_DVB_SUBTITLE: +- case AV_CODEC_ID_DVB_TELETEXT: +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- case AV_CODEC_ID_SMPTE_KLV: +- if (st->codecpar->profile == FF_PROFILE_KLVA_SYNC) { +- stream_type = STREAM_TYPE_METADATA; +- } else { +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- } +- break; +- default: +- av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, +- "Stream %d, codec %s, is muxed as a private data stream " +- "and may not be recognized upon reading.\n", st->index, +- avcodec_get_name(st->codecpar->codec_id)); +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- } +- +- return stream_type; +-} +- +-static int get_m2ts_stream_type(AVFormatContext *s, AVStream *st) +-{ +- int stream_type; +- MpegTSWriteStream *ts_st = st->priv_data; +- +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_MPEG2VIDEO: +- stream_type = STREAM_TYPE_VIDEO_MPEG2; +- break; +- case AV_CODEC_ID_H264: +- stream_type = STREAM_TYPE_VIDEO_H264; +- break; +- case AV_CODEC_ID_VC1: +- stream_type = STREAM_TYPE_VIDEO_VC1; +- break; +- case AV_CODEC_ID_HEVC: +- stream_type = STREAM_TYPE_VIDEO_HEVC; +- break; +- case AV_CODEC_ID_PCM_BLURAY: +- stream_type = 0x80; +- break; +- case AV_CODEC_ID_AC3: +- stream_type = 0x81; +- break; +- case AV_CODEC_ID_DTS: +- stream_type = (st->codecpar->channels > 6) ? 0x85 : 0x82; +- break; +- case AV_CODEC_ID_TRUEHD: +- stream_type = 0x83; +- break; +- case AV_CODEC_ID_EAC3: +- stream_type = 0x84; +- break; +- case AV_CODEC_ID_HDMV_PGS_SUBTITLE: +- stream_type = 0x90; +- break; +- case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: +- stream_type = 0x92; +- break; +- default: +- av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, +- "Stream %d, codec %s, is muxed as a private data stream " +- "and may not be recognized upon reading.\n", st->index, +- avcodec_get_name(st->codecpar->codec_id)); +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- } +- +- return stream_type; +-} +- + static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) + { + MpegTSWrite *ts = s->priv_data; +@@ -436,14 +292,6 @@ + q += 2; /* patched after */ + + /* put program info here */ +- if (ts->m2ts_mode) { +- put_registration_descriptor(&q, MKTAG('H', 'D', 'M', 'V')); +- *q++ = 0x88; // descriptor_tag - hdmv_copy_control_descriptor +- *q++ = 0x04; // descriptor_length +- put16(&q, 0x0fff); // CA_System_ID +- *q++ = 0xfc; // private_data_byte +- *q++ = 0xfc; // private_data_byte +- } + + val = 0xf000 | (q - program_info_length_ptr - 2); + program_info_length_ptr[0] = val >> 8; +@@ -472,8 +320,72 @@ + err = 1; + break; + } +- +- stream_type = ts->m2ts_mode ? get_m2ts_stream_type(s, st) : get_dvb_stream_type(s, st); ++ switch (st->codecpar->codec_id) { ++ case AV_CODEC_ID_MPEG1VIDEO: ++ case AV_CODEC_ID_MPEG2VIDEO: ++ stream_type = STREAM_TYPE_VIDEO_MPEG2; ++ break; ++ case AV_CODEC_ID_MPEG4: ++ stream_type = STREAM_TYPE_VIDEO_MPEG4; ++ break; ++ case AV_CODEC_ID_H264: ++ stream_type = STREAM_TYPE_VIDEO_H264; ++ break; ++ case AV_CODEC_ID_HEVC: ++ stream_type = STREAM_TYPE_VIDEO_HEVC; ++ break; ++ case AV_CODEC_ID_CAVS: ++ stream_type = STREAM_TYPE_VIDEO_CAVS; ++ break; ++ case AV_CODEC_ID_DIRAC: ++ stream_type = STREAM_TYPE_VIDEO_DIRAC; ++ break; ++ case AV_CODEC_ID_VC1: ++ stream_type = STREAM_TYPE_VIDEO_VC1; ++ break; ++ case AV_CODEC_ID_MP2: ++ case AV_CODEC_ID_MP3: ++ if ( st->codecpar->sample_rate > 0 ++ && st->codecpar->sample_rate < 32000) { ++ stream_type = STREAM_TYPE_AUDIO_MPEG2; ++ } else { ++ stream_type = STREAM_TYPE_AUDIO_MPEG1; ++ } ++ break; ++ case AV_CODEC_ID_AAC: ++ stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) ++ ? STREAM_TYPE_AUDIO_AAC_LATM ++ : STREAM_TYPE_AUDIO_AAC; ++ break; ++ case AV_CODEC_ID_AAC_LATM: ++ stream_type = STREAM_TYPE_AUDIO_AAC_LATM; ++ break; ++ case AV_CODEC_ID_AC3: ++ stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) ++ ? STREAM_TYPE_PRIVATE_DATA ++ : STREAM_TYPE_AUDIO_AC3; ++ break; ++ case AV_CODEC_ID_EAC3: ++ stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) ++ ? STREAM_TYPE_PRIVATE_DATA ++ : STREAM_TYPE_AUDIO_EAC3; ++ break; ++ case AV_CODEC_ID_DTS: ++ stream_type = STREAM_TYPE_AUDIO_DTS; ++ break; ++ case AV_CODEC_ID_TRUEHD: ++ stream_type = STREAM_TYPE_AUDIO_TRUEHD; ++ break; ++ case AV_CODEC_ID_OPUS: ++ stream_type = STREAM_TYPE_PRIVATE_DATA; ++ break; ++ case AV_CODEC_ID_TIMED_ID3: ++ stream_type = STREAM_TYPE_METADATA; ++ break; ++ default: ++ stream_type = STREAM_TYPE_PRIVATE_DATA; ++ break; ++ } + + *q++ = stream_type; + put16(&q, 0xe000 | ts_st->pid); +@@ -736,7 +648,7 @@ + int i, running_status, free_ca_mode, val; + + q = data; +- put16(&q, ts->original_network_id); ++ put16(&q, ts->onid); + *q++ = 0xff; + for (i = 0; i < ts->nb_services; i++) { + service = ts->services[i]; +@@ -762,7 +674,7 @@ + desc_list_len_ptr[0] = val >> 8; + desc_list_len_ptr[1] = val; + } +- mpegts_write_section1(&ts->sdt, SDT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, ++ mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, ts->tables_version, 0, 0, + data, q - data); + } + +@@ -802,49 +714,12 @@ + return 0; + } + +-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 write_packet(AVFormatContext *s, const uint8_t *packet) +-{ +- 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; +- tp_extra_header = AV_RB32(&tp_extra_header); +- avio_write(s->pb, (unsigned char *) &tp_extra_header, +- sizeof(tp_extra_header)); +- } +- avio_write(s->pb, packet, TS_PACKET_SIZE); +-} +- +-static void section_write_packet(MpegTSSection *s, const uint8_t *packet) +-{ +- AVFormatContext *ctx = s->opaque; +- write_packet(ctx, packet); +-} +- + static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid, +- const AVDictionary *metadata, +- AVProgram *program) ++ const char *provider_name, ++ const char *name) + { + MpegTSWrite *ts = s->priv_data; + MpegTSService *service; +- AVDictionaryEntry *title, *provider; +- char default_service_name[32]; +- const char *service_name; +- const char *provider_name; +- +- title = av_dict_get(metadata, "service_name", NULL, 0); +- if (!title) +- title = av_dict_get(metadata, "title", NULL, 0); +- snprintf(default_service_name, sizeof(default_service_name), "%s%02d", DEFAULT_SERVICE_NAME, ts->nb_services + 1); +- service_name = title ? title->value : default_service_name; +- provider = av_dict_get(metadata, "service_provider", NULL, 0); +- provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; + + service = av_mallocz(sizeof(MpegTSService)); + if (!service) +@@ -852,92 +727,57 @@ + service->pmt.pid = ts->pmt_start_pid + ts->nb_services; + service->sid = sid; + service->pcr_pid = 0x1fff; ++ service->pcr_sid = 0x1fff; + if (encode_str8(service->provider_name, provider_name) < 0 || +- encode_str8(service->name, service_name) < 0) { ++ encode_str8(service->name, name) < 0) { + av_log(s, AV_LOG_ERROR, "Too long service or provider name\n"); + goto fail; + } + if (av_dynarray_add_nofree(&ts->services, &ts->nb_services, service) < 0) + goto fail; + +- service->pmt.write_packet = section_write_packet; +- service->pmt.opaque = s; +- service->pmt.cc = 15; +- service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; +- service->program = program; +- + return service; + fail: + av_free(service); + return NULL; + } + +-static void enable_pcr_generation_for_stream(AVFormatContext *s, AVStream *pcr_st) ++static void mpegts_prefix_m2ts_header(AVFormatContext *s) + { + MpegTSWrite *ts = s->priv_data; +- MpegTSWriteStream *ts_st = pcr_st->priv_data; +- +- if (ts->mux_rate > 1 || ts->pcr_period_ms >= 0) { +- int pcr_period_ms = ts->pcr_period_ms == -1 ? PCR_RETRANS_TIME : ts->pcr_period_ms; +- ts_st->pcr_period = av_rescale(pcr_period_ms, PCR_TIME_BASE, 1000); +- } else { +- /* By default, for VBR we select the highest multiple of frame duration which is less than 100 ms. */ +- int64_t frame_period = 0; +- 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"); +- frame_size = 512; +- } +- frame_period = av_rescale_rnd(frame_size, PCR_TIME_BASE, pcr_st->codecpar->sample_rate, AV_ROUND_UP); +- } else if (pcr_st->avg_frame_rate.num) { +- frame_period = av_rescale_rnd(pcr_st->avg_frame_rate.den, PCR_TIME_BASE, pcr_st->avg_frame_rate.num, AV_ROUND_UP); +- } +- if (frame_period > 0 && frame_period <= PCR_TIME_BASE / 10) +- ts_st->pcr_period = frame_period * (PCR_TIME_BASE / 10 / frame_period); +- else +- ts_st->pcr_period = 1; ++ if (ts->m2ts_mode) { ++ 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)); + } +- +- // output a PCR as soon as possible +- ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period; + } + +-static void select_pcr_streams(AVFormatContext *s) ++static void section_write_packet(MpegTSSection *s, const uint8_t *packet) + { +- MpegTSWrite *ts = s->priv_data; +- +- for (int i = 0; i < ts->nb_services; i++) { +- MpegTSService *service = ts->services[i]; +- AVStream *pcr_st = NULL; +- AVProgram *program = service->program; +- int nb_streams = program ? program->nb_stream_indexes : s->nb_streams; +- +- for (int j = 0; j < nb_streams; j++) { +- AVStream *st = s->streams[program ? program->stream_index[j] : j]; +- if (!pcr_st || +- pcr_st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) +- { +- pcr_st = st; +- } +- } +- +- if (pcr_st) { +- MpegTSWriteStream *ts_st = pcr_st->priv_data; +- service->pcr_pid = ts_st->pid; +- enable_pcr_generation_for_stream(s, pcr_st); +- av_log(s, AV_LOG_VERBOSE, "service %i using PCR in pid=%i, pcr_period=%"PRId64"ms\n", +- service->sid, service->pcr_pid, av_rescale(ts_st->pcr_period, 1000, PCR_TIME_BASE)); +- } +- } ++ AVFormatContext *ctx = s->opaque; ++ mpegts_prefix_m2ts_header(ctx); ++ avio_write(ctx->pb, packet, TS_PACKET_SIZE); + } + + static int mpegts_init(AVFormatContext *s) + { + MpegTSWrite *ts = s->priv_data; ++ MpegTSWriteStream *ts_st; ++ MpegTSService *service; ++ AVStream *st, *pcr_st = NULL; ++ AVDictionaryEntry *title, *provider; ++ double clk_rate; + int i, j; ++ const char *service_name; ++ const char *provider_name; ++ int *pids; + int ret; + ++ 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; +@@ -946,36 +786,53 @@ + } + } + +- ts->m2ts_video_pid = M2TS_VIDEO_PID; +- ts->m2ts_audio_pid = M2TS_AUDIO_START_PID; +- ts->m2ts_pgssub_pid = M2TS_PGSSUB_START_PID; +- ts->m2ts_textsub_pid = M2TS_TEXTSUB_PID; +- +- if (ts->m2ts_mode) { +- ts->pmt_start_pid = M2TS_PMT_PID; +- if (s->nb_programs > 1) { +- av_log(s, AV_LOG_ERROR, "Only one program is allowed in m2ts mode!\n"); +- return AVERROR(EINVAL); +- } +- } +- +- if (s->max_delay < 0) /* Not set by the caller */ +- s->max_delay = 0; +- + // round up to a whole number of TS packets + ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14; + ++ ts->tsid = ts->transport_stream_id; ++ ts->onid = ts->original_network_id; + if (!s->nb_programs) { + /* allocate a single DVB service */ +- if (!mpegts_add_service(s, ts->service_id, s->metadata, NULL)) ++ title = av_dict_get(s->metadata, "service_name", NULL, 0); ++ if (!title) ++ title = av_dict_get(s->metadata, "title", NULL, 0); ++ service_name = title ? title->value : DEFAULT_SERVICE_NAME; ++ provider = av_dict_get(s->metadata, "service_provider", NULL, 0); ++ provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; ++ service = mpegts_add_service(s, ts->service_id, ++ provider_name, service_name); ++ ++ if (!service) + return AVERROR(ENOMEM); ++ ++ service->pmt.write_packet = section_write_packet; ++ service->pmt.opaque = s; ++ service->pmt.cc = 15; ++ service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; + } else { + for (i = 0; i < s->nb_programs; i++) { + AVProgram *program = s->programs[i]; +- if (!mpegts_add_service(s, program->id, program->metadata, program)) ++ title = av_dict_get(program->metadata, "service_name", NULL, 0); ++ if (!title) ++ title = av_dict_get(program->metadata, "title", NULL, 0); ++ service_name = title ? title->value : DEFAULT_SERVICE_NAME; ++ provider = av_dict_get(program->metadata, "service_provider", NULL, 0); ++ provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; ++ service = mpegts_add_service(s, program->id, ++ provider_name, service_name); ++ ++ if (!service) + return AVERROR(ENOMEM); ++ ++ service->pmt.write_packet = section_write_packet; ++ service->pmt.opaque = s; ++ service->pmt.cc = 15; ++ service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; ++ 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 +@@ -991,158 +848,175 @@ + ts->sdt.write_packet = section_write_packet; + ts->sdt.opaque = s; + ++ pids = av_malloc_array(s->nb_streams, sizeof(*pids)); ++ if (!pids) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ + /* assign pids to each stream */ + for (i = 0; i < s->nb_streams; i++) { +- AVStream *st = s->streams[i]; +- MpegTSWriteStream *ts_st; ++ AVProgram *program; ++ st = s->streams[i]; + + ts_st = av_mallocz(sizeof(MpegTSWriteStream)); + if (!ts_st) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + st->priv_data = ts_st; + ++ ts_st->user_tb = st->time_base; + avpriv_set_pts_info(st, 33, 1, 90000); + + ts_st->payload = av_mallocz(ts->pes_payload_size); + if (!ts_st->payload) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + +- /* MPEG pid values < 16 are reserved. Applications which set st->id in +- * this range are assigned a calculated pid. */ +- if (st->id < 16) { +- if (ts->m2ts_mode) { +- switch (st->codecpar->codec_type) { +- case AVMEDIA_TYPE_VIDEO: +- ts_st->pid = ts->m2ts_video_pid++; ++ program = av_find_program_from_stream(s, NULL, i); ++ if (program) { ++ for (j = 0; j < ts->nb_services; j++) { ++ if (ts->services[j]->program == program) { ++ service = ts->services[j]; + break; +- case AVMEDIA_TYPE_AUDIO: +- ts_st->pid = ts->m2ts_audio_pid++; +- break; +- case AVMEDIA_TYPE_SUBTITLE: +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_HDMV_PGS_SUBTITLE: +- ts_st->pid = ts->m2ts_pgssub_pid++; +- break; +- case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: +- ts_st->pid = ts->m2ts_textsub_pid++; +- break; +- } +- break; +- } +- if (ts->m2ts_video_pid > M2TS_VIDEO_PID + 1 || +- ts->m2ts_audio_pid > M2TS_AUDIO_START_PID + 32 || +- ts->m2ts_pgssub_pid > M2TS_PGSSUB_START_PID + 32 || +- ts->m2ts_textsub_pid > M2TS_TEXTSUB_PID + 1 || +- ts_st->pid < 16) { +- av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index); +- return AVERROR(EINVAL); + } +- } else { +- ts_st->pid = ts->start_pid + i; + } +- } else { +- ts_st->pid = st->id; + } +- if (ts_st->pid >= 0x1FFF) { ++ ++ ts_st->service = service; ++ /* MPEG pid values < 16 are reserved. Applications which set st->id in ++ * this range are assigned a calculated pid. */ ++ if (st->id < 16) { ++ ts_st->pid = ts->start_pid + i; ++ } else if (st->id < 0x1FFF) { ++ ts_st->pid = st->id; ++ } else { + av_log(s, AV_LOG_ERROR, + "Invalid stream id %d, must be less than 8191\n", st->id); +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } +- for (j = 0; j < ts->nb_services; j++) { +- if (ts->services[j]->pmt.pid > LAST_OTHER_PID) { +- av_log(s, AV_LOG_ERROR, +- "Invalid PMT PID %d, must be less than %d\n", ts->services[j]->pmt.pid, LAST_OTHER_PID + 1); +- return AVERROR(EINVAL); +- } +- if (ts_st->pid == ts->services[j]->pmt.pid) { +- av_log(s, AV_LOG_ERROR, "PID %d cannot be both elementary and PMT PID\n", ts_st->pid); +- return AVERROR(EINVAL); +- } ++ if (ts_st->pid == service->pmt.pid) { ++ av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); ++ ret = AVERROR(EINVAL); ++ goto fail; + } + for (j = 0; j < i; j++) { +- MpegTSWriteStream *ts_st_prev = s->streams[j]->priv_data; +- if (ts_st_prev->pid == ts_st->pid) { ++ if (pids[j] == ts_st->pid) { + av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } + } ++ pids[i] = ts_st->pid; + ts_st->payload_pts = AV_NOPTS_VALUE; + ts_st->payload_dts = AV_NOPTS_VALUE; + ts_st->first_pts_check = 1; + ts_st->cc = 15; + 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_sid == 0x1fff) ++ pcr_st = st; ++ + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) { + AVStream *ast; + ts_st->amux = avformat_alloc_context(); + if (!ts_st->amux) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + ts_st->amux->oformat = + av_guess_format((ts->flags & MPEGTS_FLAG_AAC_LATM) ? "latm" : "adts", + NULL, NULL); + if (!ts_st->amux->oformat) { +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } + if (!(ast = avformat_new_stream(ts_st->amux, NULL))) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + ret = avcodec_parameters_copy(ast->codecpar, st->codecpar); + if (ret != 0) +- return ret; ++ goto fail; + ast->time_base = st->time_base; + ret = avformat_write_header(ts_st->amux, NULL); + if (ret < 0) +- return ret; ++ goto fail; + } + if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { + ts_st->opus_pending_trim_start = st->codecpar->initial_padding * 48000 / st->codecpar->sample_rate; + } + } + ++ av_freep(&pids); ++ ++ /* if no video stream, use the first stream as PCR */ ++ 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; ++ } ++ 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); + +- select_pcr_streams(s); +- +- ts->last_pat_ts = AV_NOPTS_VALUE; +- ts->last_sdt_ts = AV_NOPTS_VALUE; +- ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE); +- ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE); ++ // output a PCR as soon as possible ++ 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, +- "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms\n", +- av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE), +- av_rescale(ts->pat_period, 1000, PCR_TIME_BASE)); + + return 0; ++ ++fail: ++ av_freep(&pids); ++ return ret; + } + + /* send SDT, PAT and PMT tables regularly */ +-static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int64_t pcr) ++static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts) + { + MpegTSWrite *ts = s->priv_data; + int i; + +- if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) || +- (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) || +- force_sdt +- ) { +- if (pcr != AV_NOPTS_VALUE) +- ts->last_sdt_ts = FFMAX(pcr, 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 ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) || +- (pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) || +- force_pat) { +- if (pcr != AV_NOPTS_VALUE) +- ts->last_pat_ts = FFMAX(pcr, 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]); +@@ -1175,7 +1049,8 @@ + *q++ = 0xff; + *q++ = 0x10; + memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf)); +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + + /* Write a single transport stream packet with a PCR and no payload */ +@@ -1183,13 +1058,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 */ +@@ -1200,11 +1076,12 @@ + } + + /* 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)); +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + + static void write_pts(uint8_t *q, int fourbits, int64_t pts) +@@ -1268,84 +1145,55 @@ + 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 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; +- int force_sdt = 0; + + av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO); + if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + force_pat = 1; + } + +- if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { +- force_pat = 1; +- force_sdt = 1; +- ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT; +- } +- + is_start = 1; + while (payload_size > 0) { +- int64_t pcr = AV_NOPTS_VALUE; +- if (ts->mux_rate > 1) +- pcr = get_pcr(ts, s->pb); +- else if (dts != AV_NOPTS_VALUE) +- pcr = (dts - delay) * 300; ++ 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, force_sdt, pcr); ++ retransmit_si_info(s, force_pat, dts); + force_pat = 0; +- force_sdt = 0; + + write_pcr = 0; +- if (ts->mux_rate > 1) { +- /* Send PCR packets for all PCR streams if needed */ +- pcr = get_pcr(ts, s->pb); +- if (pcr >= ts->next_pcr) { +- int64_t next_pcr = INT64_MAX; +- for (int i = 0; i < s->nb_streams; i++) { +- /* Make the current stream the last, because for that we +- * can insert the pcr into the payload later */ +- int st2_index = i < st->index ? i : (i + 1 == s->nb_streams ? st->index : i + 1); +- AVStream *st2 = s->streams[st2_index]; +- MpegTSWriteStream *ts_st2 = st2->priv_data; +- if (ts_st2->pcr_period) { +- if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) { +- ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period); +- if (st2 != st) { +- mpegts_insert_pcr_only(s, st2); +- pcr = get_pcr(ts, s->pb); +- } else { +- write_pcr = 1; +- } +- } +- next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period); +- } +- } +- ts->next_pcr = next_pcr; +- } +- if (dts != AV_NOPTS_VALUE && (dts - pcr / 300) > 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 */ +- continue; +- } +- } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) { +- if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) { +- ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period); ++ 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 - 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 retransimit si_info */ ++ continue; ++ } + + /* prepare packet header */ + q = buf; + *q++ = 0x47; + val = ts_st->pid >> 8; +- if (ts->m2ts_mode && st->codecpar->codec_id == AV_CODEC_ID_AC3) +- val |= 0x20; + 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; +@@ -1357,7 +1205,7 @@ + } + if (key && is_start && pts != AV_NOPTS_VALUE) { + // set Random Access for key frames +- if (ts_st->pcr_period) ++ if (ts_st->pid == ts_st->service->pcr_sid) + write_pcr = 1; + set_af_flag(buf, 0x40); + q = get_ts_payload_start(buf); +@@ -1365,10 +1213,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 (dts != AV_NOPTS_VALUE && dts < pcr / 300) ++ if (ts->mux_rate > 1) ++ 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) { +@@ -1439,10 +1287,10 @@ + if (ts->m2ts_mode && + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->codec_id == AV_CODEC_ID_AC3) { +- /* set PES_extension_flag */ +- pes_extension = 1; +- flags |= 0x01; +- header_len += 3; ++ /* set PES_extension_flag */ ++ pes_extension = 1; ++ flags |= 0x01; ++ header_len += 3; + } + if (is_dvb_teletext) { + pes_header_stuffing_bytes = 0x24 - header_len; +@@ -1469,11 +1317,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) { +@@ -1485,14 +1335,14 @@ + *q++ = 0x00 | 0x60; + } + /* For Blu-ray AC3 Audio Setting extended flags */ +- if (ts->m2ts_mode && +- pes_extension && +- st->codecpar->codec_id == AV_CODEC_ID_AC3) { +- flags = 0x01; /* set PES_extension_flag_2 */ +- *q++ = flags; +- *q++ = 0x80 | 0x01; /* marker bit + extension length */ +- *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ +- } ++ if (ts->m2ts_mode && ++ pes_extension && ++ st->codecpar->codec_id == AV_CODEC_ID_AC3) { ++ flags = 0x01; /* set PES_extension_flag_2 */ ++ *q++ = flags; ++ *q++ = 0x80 | 0x01; /* marker bit + extension length */ ++ *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ ++ } + + + if (is_dvb_subtitle) { +@@ -1546,7 +1396,8 @@ + + payload += len; + payload_size -= len; +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + ts_st->prev_payload_key = key; + } +@@ -1643,8 +1494,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; +- const int64_t max_audio_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; +@@ -1657,11 +1506,23 @@ + if (side_data) + stream_id = side_data[0]; + ++ if (ts->reemit_pat_pmt) { ++ av_log(s, AV_LOG_WARNING, ++ "resend_headers option is deprecated, use -mpegts_flags resend_headers\n"); ++ ts->reemit_pat_pmt = 0; ++ ts->flags |= MPEGTS_FLAG_REEMIT_PAT_PMT; ++ } ++ ++ if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { ++ 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) { +@@ -1724,7 +1585,7 @@ + + ret = avio_open_dyn_buf(&ts_st->amux->pb); + if (ret < 0) +- return ret; ++ return AVERROR(ENOMEM); + + ret = av_write_frame(ts_st->amux, &pkt2); + if (ret < 0) { +@@ -1755,7 +1616,7 @@ + } while (p < buf_end && (state & 0x7e) != 2*35 && + (state & 0x7e) >= 2*32); + +- if ((state & 0x7e) < 2*16 || (state & 0x7e) >= 2*24) ++ if ((state & 0x7e) < 2*16 && (state & 0x7e) >= 2*24) + extradd = 0; + if ((state & 0x7e) != 2*35) { // AUD NAL + data = av_malloc(pkt->size + 7 + extradd); +@@ -1843,9 +1704,25 @@ + } + } + ++ if (pkt->dts != AV_NOPTS_VALUE) { ++ int i; ++ for(i=0; inb_streams; i++) { ++ 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 > 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); ++ ts_st2->payload_size = 0; ++ } ++ } ++ } ++ + if (ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size || + (dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE && +- dts - ts_st->payload_dts >= max_audio_delay) || ++ av_compare_ts(dts - ts_st->payload_dts, st->time_base, ++ s->max_delay, AV_TIME_BASE_Q) >= 0) || + ts_st->opus_queued_samples + opus_samples >= 5760 /* 120ms */)) { + mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size, + ts_st->payload_pts, ts_st->payload_dts, +@@ -1881,7 +1758,6 @@ + + static void mpegts_write_flush(AVFormatContext *s) + { +- MpegTSWrite *ts = s->priv_data; + int i; + + /* flush current packets */ +@@ -1896,12 +1772,6 @@ + ts_st->opus_queued_samples = 0; + } + } +- +- if (ts->m2ts_mode) { +- int packets = (avio_tell(s->pb) / (TS_PACKET_SIZE + 4)) % 32; +- while (packets++ < 32) +- mpegts_insert_null_packet(s); +- } + } + + static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) +@@ -1969,62 +1839,104 @@ + return ret; + } + +-#define OFFSET(x) offsetof(MpegTSWrite, x) +-#define ENC AV_OPT_FLAG_ENCODING_PARAM + static const AVOption options[] = { + { "mpegts_transport_stream_id", "Set transport_stream_id field.", +- OFFSET(transport_stream_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, ++ { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_original_network_id", "Set original_network_id field.", +- OFFSET(original_network_id), AV_OPT_TYPE_INT, { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, original_network_id), AV_OPT_TYPE_INT, ++ { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_service_id", "Set service_id field.", +- OFFSET(service_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, ++ { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_service_type", "Set service_type field.", +- OFFSET(service_type), AV_OPT_TYPE_INT, { .i64 = 0x01 }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ offsetof(MpegTSWrite, service_type), AV_OPT_TYPE_INT, ++ { .i64 = 0x01 }, 0x01, 0xff, AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "digital_tv", "Digital Television.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "digital_radio", "Digital Radio.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "teletext", "Teletext.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_radio", "Advanced Codec Digital Radio.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "mpeg2_digital_hdtv", "MPEG2 Digital HDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_sdtv", "Advanced Codec Digital SDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_hdtv", "Advanced Codec Digital HDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "hevc_digital_hdtv", "HEVC Digital Television Service.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "mpegts_pmt_start_pid", "Set the first pid of the PMT.", +- OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, ++ 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.", +- OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, +- { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, +- { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, ++ 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, 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 }, + { "pes_payload_size", "Minimum PES packet payload in bytes", +- OFFSET(pes_payload_size), AV_OPT_TYPE_INT, { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, ENC }, +- { "mpegts_flags", "MPEG-TS muxing flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, ++ { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "mpegts_flags", "MPEG-TS muxing flags", ++ offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "resend_headers", "Reemit PAT/PMT before writing the next packet", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "latm", "Use LATM packetization for AAC", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "pat_pmt_at_frames", "Reemit PAT and PMT at each video frame", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "system_b", "Conform to System B (DVB) instead of System A (ATSC)", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "initial_discontinuity", "Mark initial packets as discontinuous", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, ENC, "mpegts_flags" }, +- { "mpegts_copyts", "don't offset dts/pts", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, +- { "tables_version", "set PAT, PMT and SDT version", OFFSET(tables_version), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 31, ENC }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, ++ // backward compatibility ++ { "resend_headers", "Reemit PAT/PMT before writing the next packet", ++ offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, ++ { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "mpegts_copyts", "don't offset dts/pts", ++ offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_BOOL, ++ { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "tables_version", "set PAT, PMT and SDT version", ++ offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, ++ { .i64 = 0 }, 0, 31, AV_OPT_FLAG_ENCODING_PARAM }, + { "omit_video_pes_length", "Omit the PES packet length for video packets", +- OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, +- { "pcr_period", "PCR retransmission time in milliseconds", +- OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC }, +- { "pat_period", "PAT/PMT retransmission time limit in seconds", +- OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, +- { "sdt_period", "SDT retransmission time limit in seconds", +- OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, ++ offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL, ++ { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "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 = 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 = SDT_RETRANS_TIME }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { NULL }, + }; + diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch3 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch3 similarity index 70% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch3 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch3 index cd284388..e8689455 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch3 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch3 @@ -1,7 +1,7 @@ -diff -ru a/libavformat/avformat.h b/libavformat/avformat.h ---- a/libavformat/avformat.h 2019-08-05 14:52:21.000000000 -0600 -+++ b/libavformat/avformat.h 2019-08-08 17:26:45.869297510 -0600 -@@ -485,6 +485,9 @@ +diff -ruN a/libavformat/avformat.h b/libavformat/avformat.h +--- a/libavformat/avformat.h 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavformat/avformat.h 2020-07-10 09:22:38.176711618 -0600 +@@ -480,6 +480,9 @@ The user or muxer can override this through AVFormatContext.avoid_negative_ts */ @@ -11,7 +11,7 @@ diff -ru a/libavformat/avformat.h b/libavformat/avformat.h #define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ -@@ -654,7 +657,8 @@ +@@ -650,7 +653,8 @@ /** * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, @@ -21,12 +21,10 @@ diff -ru a/libavformat/avformat.h b/libavformat/avformat.h */ int flags; -Only in b/libavformat: avformat.h.orig -Only in b/libavformat: avformat.h.rej -diff -ru a/libavformat/dv.c b/libavformat/dv.c ---- a/libavformat/dv.c 2019-08-05 14:52:21.000000000 -0600 -+++ b/libavformat/dv.c 2019-08-08 17:23:57.558692650 -0600 -@@ -632,6 +632,7 @@ +diff -ruN a/libavformat/dv.c b/libavformat/dv.c +--- a/libavformat/dv.c 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavformat/dv.c 2020-07-10 09:22:38.177711618 -0600 +@@ -642,6 +642,7 @@ AVInputFormat ff_dv_demuxer = { .name = "dv", .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), @@ -34,10 +32,10 @@ diff -ru a/libavformat/dv.c b/libavformat/dv.c .priv_data_size = sizeof(RawDVContext), .read_probe = dv_probe, .read_header = dv_read_header, -diff -ru a/libavformat/matroskadec.c b/libavformat/matroskadec.c ---- a/libavformat/matroskadec.c 2019-08-05 14:52:21.000000000 -0600 -+++ b/libavformat/matroskadec.c 2019-08-08 17:23:57.559692582 -0600 -@@ -4229,6 +4229,7 @@ +diff -ruN a/libavformat/matroskadec.c b/libavformat/matroskadec.c +--- a/libavformat/matroskadec.c 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavformat/matroskadec.c 2020-07-10 09:22:38.178711618 -0600 +@@ -4251,6 +4251,7 @@ AVInputFormat ff_matroska_demuxer = { .name = "matroska,webm", .long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), @@ -45,7 +43,7 @@ diff -ru a/libavformat/matroskadec.c b/libavformat/matroskadec.c .extensions = "mkv,mk3d,mka,mks", .priv_data_size = sizeof(MatroskaDemuxContext), .read_probe = matroska_probe, -@@ -4242,6 +4243,7 @@ +@@ -4264,6 +4265,7 @@ AVInputFormat ff_webm_dash_manifest_demuxer = { .name = "webm_dash_manifest", .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), @@ -53,11 +51,10 @@ diff -ru 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, -Only in b/libavformat: matroskadec.c.orig -diff -ru a/libavformat/utils.c b/libavformat/utils.c ---- a/libavformat/utils.c 2019-08-05 14:52:21.000000000 -0600 -+++ b/libavformat/utils.c 2019-08-08 17:23:57.560692514 -0600 -@@ -2472,6 +2472,13 @@ +diff -ruN a/libavformat/utils.c b/libavformat/utils.c +--- a/libavformat/utils.c 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavformat/utils.c 2020-07-10 09:22:38.179711619 -0600 +@@ -2486,6 +2486,13 @@ return seek_frame_byte(s, stream_index, timestamp, flags); } diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch4 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch4 similarity index 76% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch4 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch4 index 87a2d41b..681dd822 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch4 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch4 @@ -1,7 +1,7 @@ -diff -ru a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c ---- a/libavfilter/af_aformat.c 2018-07-17 03:27:41.000000000 -0600 -+++ b/libavfilter/af_aformat.c 2019-08-08 18:20:22.150540943 -0600 -@@ -109,6 +109,16 @@ +diff -ruN a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c +--- a/libavfilter/af_aformat.c 2020-06-15 12:54:24.000000000 -0600 ++++ b/libavfilter/af_aformat.c 2020-07-10 09:24:01.659724729 -0600 +@@ -112,6 +112,16 @@ return 0; } @@ -18,7 +18,7 @@ diff -ru a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c static int query_formats(AVFilterContext *ctx) { AFormatContext *s = ctx->priv; -@@ -146,6 +156,7 @@ +@@ -149,6 +159,7 @@ .name = "aformat", .description = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."), .init = init, diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch5 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch5 similarity index 100% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch5 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch5 diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch6 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch6 similarity index 100% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch6 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch6 diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch7 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch7 similarity index 100% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch7 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch7 diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch8 b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch8 similarity index 73% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch8 rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch8 index 9518ad75..83729627 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patch8 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patch8 @@ -1,6 +1,7 @@ ---- a/libavformat/mpegenc.c 2019-08-05 14:52:21.000000000 -0600 -+++ /blibavformat/mpegenc.c 2019-11-14 14:07:57.407883232 -0700 -@@ -981,9 +981,9 @@ +diff -ruN a/libavformat/mpegenc.c b/libavformat/mpegenc.c +--- a/libavformat/mpegenc.c 2020-07-10 09:26:57.257744879 -0600 ++++ b/libavformat/mpegenc.c 2020-07-10 09:27:14.528745779 -0600 +@@ -976,9 +976,9 @@ PacketDesc *pkt_desc; while ((pkt_desc = stream->predecode_packet) && diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patchA b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchA similarity index 100% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.patchA rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.patchA diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.tar.xz b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.tar.xz similarity index 53% rename from cinelerra-5.1/thirdparty/src/ffmpeg-4.2.tar.xz rename to cinelerra-5.1/thirdparty/src/ffmpeg-4.3.tar.xz index 3fb2293d..98f68fd5 100644 Binary files a/cinelerra-5.1/thirdparty/src/ffmpeg-4.2.tar.xz and b/cinelerra-5.1/thirdparty/src/ffmpeg-4.3.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch0 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch0 index 32c876e1..f9760935 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch0 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch0 @@ -1,7 +1,8 @@ -diff -urN a/fftools/cmdutils.c b/fftools/cmdutils.c ---- a/fftools/cmdutils.c 2019-12-02 08:48:02.860360597 -0700 -+++ b/fftools/cmdutils.c 2019-12-02 08:51:04.603975015 -0700 -@@ -1186,6 +1186,7 @@ +diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c +index 88fdbeaf1e..f39d2e7cc4 100644 +--- a/fftools/cmdutils.c ++++ b/fftools/cmdutils.c +@@ -1184,6 +1184,7 @@ static void print_buildconf(int flags, int level) void show_banner(int argc, char **argv, const OptionDef *options) { diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch1 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch1 index 5ecef3c0..88631302 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch1 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch1 @@ -1,6 +1,7 @@ -diff -urN a/libavformat/bluray.c b/libavformat/bluray.c ---- a/libavformat/bluray.c 2019-12-02 08:48:03.104361421 -0700 -+++ b/libavformat/bluray.c 2019-12-02 08:51:33.187071639 -0700 +diff --git a/libavformat/bluray.c b/libavformat/bluray.c +index 635c4f1b87..80a2e2c3d2 100644 +--- a/libavformat/bluray.c ++++ b/libavformat/bluray.c @@ -28,7 +28,7 @@ #include "libavutil/opt.h" diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch2 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch2 index 1d312469..11573c26 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch2 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch2 @@ -1,4 +1,5 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c +index d827ba3e28..c8c6db979b 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -56,7 +56,8 @@ typedef struct MpegTSService { @@ -6,53 +7,67 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c uint8_t name[256]; uint8_t provider_name[256]; - int pcr_pid; -+ int pcr_sid; /* stream triggering pcr writes */ -+ int pcr_pid; /* pid of pcr stream */ ++ int64_t pcr, pcr_packet_timer, pcr_packet_period; ++ int pcr_sid, pcr_pid; AVProgram *program; } MpegTSService; -@@ -79,10 +80,8 @@ typedef struct MpegTSWrite { - int64_t sdt_period; /* SDT period in PCR time base */ - int64_t pat_period; /* PAT/PMT period in PCR time base */ +@@ -76,11 +77,12 @@ typedef struct MpegTSWrite { + MpegTSSection pat; /* MPEG-2 PAT table */ + MpegTSSection sdt; /* MPEG-2 SDT table context */ + MpegTSService **services; +- int64_t sdt_period; /* SDT period in PCR time base */ +- int64_t pat_period; /* PAT/PMT period in PCR time base */ ++ 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 next_pcr; -+ int onid, tsid; -+ int64_t pcr, first_pcr, next_pcr, delay; ++ int onid; ++ int tsid; ++ int64_t pcr, first_pcr, delay; int mux_rate; ///< set to 1 when VBR int pes_payload_size; -@@ -94,8 +93,8 @@ typedef struct MpegTSWrite { +@@ -90,14 +92,14 @@ typedef struct MpegTSWrite { + int service_type; + int pmt_start_pid; ++ int pcr_start_pid; int start_pid; int m2ts_mode; +- int m2ts_video_pid; +- int m2ts_audio_pid; +- int m2ts_pgssub_pid; +- int m2ts_textsub_pid; + int64_t ts_offset; - int pcr_period_ms; ++ int reemit_pat_pmt; // backward compatibility ++ ++ double pcr_period; #define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01 #define MPEGTS_FLAG_AAC_LATM 0x02 #define MPEGTS_FLAG_PAT_PMT_AT_FRAMES 0x04 -@@ -104,11 +103,11 @@ typedef struct MpegTSWrite { +@@ -106,10 +108,8 @@ typedef struct MpegTSWrite { int flags; int copyts; int tables_version; - int64_t pat_period_us; - int64_t sdt_period_us; - int64_t last_pat_ts; -+ double pcr_period_ms; -+ double sdt_period_ms; -+ double pat_period_ms; - int64_t last_sdt_ts; -- -+ int64_t last_pat_ts; +- int64_t last_sdt_ts; ++ double pat_period; ++ double sdt_period; + int omit_video_pes_length; } MpegTSWrite; +@@ -217,14 +217,15 @@ static int mpegts_write_section1(MpegTSSection *s, int tid, int id, + /* mpegts writer */ -@@ -217,10 +216,10 @@ static int mpegts_write_section1(MpegTSSection *s, int tid, int id, #define DEFAULT_PROVIDER_NAME "FFmpeg" - #define DEFAULT_SERVICE_NAME "Service" +-#define DEFAULT_SERVICE_NAME "Service" ++#define DEFAULT_SERVICE_NAME "Service01" -/* we retransmit the SI info at this rate */ +/* we retransmit the SI info at this rate (ms) */ @@ -62,17 +77,289 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c +#define PCR_RETRANS_TIME 50 typedef struct MpegTSWriteStream { ++ struct MpegTSService *service; int pid; /* stream associated pid */ -@@ -234,7 +233,7 @@ typedef struct MpegTSWriteStream { + int cc; + int discontinuity; +@@ -236,10 +237,7 @@ typedef struct MpegTSWriteStream { int payload_flags; uint8_t *payload; AVFormatContext *amux; +- int data_st_warning; - -+ MpegTSService *service; - int64_t pcr_period; /* PCR period in PCR time base */ - int64_t last_pcr; +- int64_t pcr_period; /* PCR period in PCR time base */ +- int64_t last_pcr; ++ AVRational user_tb; + + /* For Opus */ + int opus_queued_samples; +@@ -259,7 +257,7 @@ static void mpegts_write_pat(AVFormatContext *s) + put16(&q, service->sid); + put16(&q, 0xe000 | service->pmt.pid); + } +- mpegts_write_section1(&ts->pat, PAT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, ++ mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, ts->tables_version, 0, 0, + data, q - data); + } + +@@ -281,148 +279,6 @@ static void put_registration_descriptor(uint8_t **q_ptr, uint32_t tag) + *q_ptr = q; + } + +-static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) +-{ +- MpegTSWrite *ts = s->priv_data; +- MpegTSWriteStream *ts_st = st->priv_data; +- int stream_type; +- +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_MPEG1VIDEO: +- case AV_CODEC_ID_MPEG2VIDEO: +- stream_type = STREAM_TYPE_VIDEO_MPEG2; +- break; +- case AV_CODEC_ID_MPEG4: +- stream_type = STREAM_TYPE_VIDEO_MPEG4; +- break; +- case AV_CODEC_ID_H264: +- stream_type = STREAM_TYPE_VIDEO_H264; +- break; +- case AV_CODEC_ID_HEVC: +- stream_type = STREAM_TYPE_VIDEO_HEVC; +- break; +- case AV_CODEC_ID_CAVS: +- stream_type = STREAM_TYPE_VIDEO_CAVS; +- break; +- case AV_CODEC_ID_DIRAC: +- stream_type = STREAM_TYPE_VIDEO_DIRAC; +- break; +- case AV_CODEC_ID_VC1: +- stream_type = STREAM_TYPE_VIDEO_VC1; +- break; +- case AV_CODEC_ID_MP2: +- case AV_CODEC_ID_MP3: +- if ( st->codecpar->sample_rate > 0 +- && st->codecpar->sample_rate < 32000) { +- stream_type = STREAM_TYPE_AUDIO_MPEG2; +- } else { +- stream_type = STREAM_TYPE_AUDIO_MPEG1; +- } +- break; +- case AV_CODEC_ID_AAC: +- stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) +- ? STREAM_TYPE_AUDIO_AAC_LATM +- : STREAM_TYPE_AUDIO_AAC; +- break; +- case AV_CODEC_ID_AAC_LATM: +- stream_type = STREAM_TYPE_AUDIO_AAC_LATM; +- break; +- case AV_CODEC_ID_AC3: +- stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) +- ? STREAM_TYPE_PRIVATE_DATA +- : STREAM_TYPE_AUDIO_AC3; +- break; +- case AV_CODEC_ID_EAC3: +- stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) +- ? STREAM_TYPE_PRIVATE_DATA +- : STREAM_TYPE_AUDIO_EAC3; +- break; +- case AV_CODEC_ID_DTS: +- stream_type = STREAM_TYPE_AUDIO_DTS; +- break; +- case AV_CODEC_ID_TRUEHD: +- stream_type = STREAM_TYPE_AUDIO_TRUEHD; +- break; +- case AV_CODEC_ID_OPUS: +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- case AV_CODEC_ID_TIMED_ID3: +- stream_type = STREAM_TYPE_METADATA; +- break; +- case AV_CODEC_ID_DVB_SUBTITLE: +- case AV_CODEC_ID_DVB_TELETEXT: +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- case AV_CODEC_ID_SMPTE_KLV: +- if (st->codecpar->profile == FF_PROFILE_KLVA_SYNC) { +- stream_type = STREAM_TYPE_METADATA; +- } else { +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- } +- break; +- default: +- av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, +- "Stream %d, codec %s, is muxed as a private data stream " +- "and may not be recognized upon reading.\n", st->index, +- avcodec_get_name(st->codecpar->codec_id)); +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- } +- +- return stream_type; +-} +- +-static int get_m2ts_stream_type(AVFormatContext *s, AVStream *st) +-{ +- int stream_type; +- MpegTSWriteStream *ts_st = st->priv_data; +- +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_MPEG2VIDEO: +- stream_type = STREAM_TYPE_VIDEO_MPEG2; +- break; +- case AV_CODEC_ID_H264: +- stream_type = STREAM_TYPE_VIDEO_H264; +- break; +- case AV_CODEC_ID_VC1: +- stream_type = STREAM_TYPE_VIDEO_VC1; +- break; +- case AV_CODEC_ID_HEVC: +- stream_type = STREAM_TYPE_VIDEO_HEVC; +- break; +- case AV_CODEC_ID_PCM_BLURAY: +- stream_type = 0x80; +- break; +- case AV_CODEC_ID_AC3: +- stream_type = 0x81; +- break; +- case AV_CODEC_ID_DTS: +- stream_type = (st->codecpar->channels > 6) ? 0x85 : 0x82; +- break; +- case AV_CODEC_ID_TRUEHD: +- stream_type = 0x83; +- break; +- case AV_CODEC_ID_EAC3: +- stream_type = 0x84; +- break; +- case AV_CODEC_ID_HDMV_PGS_SUBTITLE: +- stream_type = 0x90; +- break; +- case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: +- stream_type = 0x92; +- break; +- default: +- av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, +- "Stream %d, codec %s, is muxed as a private data stream " +- "and may not be recognized upon reading.\n", st->index, +- avcodec_get_name(st->codecpar->codec_id)); +- stream_type = STREAM_TYPE_PRIVATE_DATA; +- break; +- } +- +- return stream_type; +-} +- + static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) + { + MpegTSWrite *ts = s->priv_data; +@@ -436,14 +292,6 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) + q += 2; /* patched after */ + + /* put program info here */ +- if (ts->m2ts_mode) { +- put_registration_descriptor(&q, MKTAG('H', 'D', 'M', 'V')); +- *q++ = 0x88; // descriptor_tag - hdmv_copy_control_descriptor +- *q++ = 0x04; // descriptor_length +- put16(&q, 0x0fff); // CA_System_ID +- *q++ = 0xfc; // private_data_byte +- *q++ = 0xfc; // private_data_byte +- } + + val = 0xf000 | (q - program_info_length_ptr - 2); + program_info_length_ptr[0] = val >> 8; +@@ -472,8 +320,72 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) + err = 1; + break; + } +- +- stream_type = ts->m2ts_mode ? get_m2ts_stream_type(s, st) : get_dvb_stream_type(s, st); ++ switch (st->codecpar->codec_id) { ++ case AV_CODEC_ID_MPEG1VIDEO: ++ case AV_CODEC_ID_MPEG2VIDEO: ++ stream_type = STREAM_TYPE_VIDEO_MPEG2; ++ break; ++ case AV_CODEC_ID_MPEG4: ++ stream_type = STREAM_TYPE_VIDEO_MPEG4; ++ break; ++ case AV_CODEC_ID_H264: ++ stream_type = STREAM_TYPE_VIDEO_H264; ++ break; ++ case AV_CODEC_ID_HEVC: ++ stream_type = STREAM_TYPE_VIDEO_HEVC; ++ break; ++ case AV_CODEC_ID_CAVS: ++ stream_type = STREAM_TYPE_VIDEO_CAVS; ++ break; ++ case AV_CODEC_ID_DIRAC: ++ stream_type = STREAM_TYPE_VIDEO_DIRAC; ++ break; ++ case AV_CODEC_ID_VC1: ++ stream_type = STREAM_TYPE_VIDEO_VC1; ++ break; ++ case AV_CODEC_ID_MP2: ++ case AV_CODEC_ID_MP3: ++ if ( st->codecpar->sample_rate > 0 ++ && st->codecpar->sample_rate < 32000) { ++ stream_type = STREAM_TYPE_AUDIO_MPEG2; ++ } else { ++ stream_type = STREAM_TYPE_AUDIO_MPEG1; ++ } ++ break; ++ case AV_CODEC_ID_AAC: ++ stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) ++ ? STREAM_TYPE_AUDIO_AAC_LATM ++ : STREAM_TYPE_AUDIO_AAC; ++ break; ++ case AV_CODEC_ID_AAC_LATM: ++ stream_type = STREAM_TYPE_AUDIO_AAC_LATM; ++ break; ++ case AV_CODEC_ID_AC3: ++ stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) ++ ? STREAM_TYPE_PRIVATE_DATA ++ : STREAM_TYPE_AUDIO_AC3; ++ break; ++ case AV_CODEC_ID_EAC3: ++ stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) ++ ? STREAM_TYPE_PRIVATE_DATA ++ : STREAM_TYPE_AUDIO_EAC3; ++ break; ++ case AV_CODEC_ID_DTS: ++ stream_type = STREAM_TYPE_AUDIO_DTS; ++ break; ++ case AV_CODEC_ID_TRUEHD: ++ stream_type = STREAM_TYPE_AUDIO_TRUEHD; ++ break; ++ case AV_CODEC_ID_OPUS: ++ stream_type = STREAM_TYPE_PRIVATE_DATA; ++ break; ++ case AV_CODEC_ID_TIMED_ID3: ++ stream_type = STREAM_TYPE_METADATA; ++ break; ++ default: ++ stream_type = STREAM_TYPE_PRIVATE_DATA; ++ break; ++ } + + *q++ = stream_type; + put16(&q, 0xe000 | ts_st->pid); +@@ -736,7 +648,7 @@ static void mpegts_write_sdt(AVFormatContext *s) + int i, running_status, free_ca_mode, val; -@@ -713,18 +712,11 @@ invalid: + q = data; +- put16(&q, ts->original_network_id); ++ put16(&q, ts->onid); + *q++ = 0xff; + for (i = 0; i < ts->nb_services; i++) { + service = ts->services[i]; +@@ -762,7 +674,7 @@ static void mpegts_write_sdt(AVFormatContext *s) + desc_list_len_ptr[0] = val >> 8; + desc_list_len_ptr[1] = val; + } +- mpegts_write_section1(&ts->sdt, SDT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, ++ mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, ts->tables_version, 0, 0, + data, q - data); + } + +@@ -802,49 +714,12 @@ invalid: return 0; } @@ -82,171 +369,479 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c - ts->first_pcr; -} - - static void write_packet(AVFormatContext *s, const uint8_t *packet) - { - MpegTSWrite *ts = s->priv_data; - if (ts->m2ts_mode) { +-static void write_packet(AVFormatContext *s, const uint8_t *packet) +-{ +- 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)); -@@ -763,6 +755,7 @@ static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid, +- tp_extra_header = AV_RB32(&tp_extra_header); +- avio_write(s->pb, (unsigned char *) &tp_extra_header, +- sizeof(tp_extra_header)); +- } +- avio_write(s->pb, packet, TS_PACKET_SIZE); +-} +- +-static void section_write_packet(MpegTSSection *s, const uint8_t *packet) +-{ +- AVFormatContext *ctx = s->opaque; +- write_packet(ctx, packet); +-} +- + static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid, +- const AVDictionary *metadata, +- AVProgram *program) ++ const char *provider_name, ++ const char *name) + { + MpegTSWrite *ts = s->priv_data; + MpegTSService *service; +- AVDictionaryEntry *title, *provider; +- char default_service_name[32]; +- const char *service_name; +- const char *provider_name; +- +- title = av_dict_get(metadata, "service_name", NULL, 0); +- if (!title) +- title = av_dict_get(metadata, "title", NULL, 0); +- snprintf(default_service_name, sizeof(default_service_name), "%s%02d", DEFAULT_SERVICE_NAME, ts->nb_services + 1); +- service_name = title ? title->value : default_service_name; +- provider = av_dict_get(metadata, "service_provider", NULL, 0); +- provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; + + service = av_mallocz(sizeof(MpegTSService)); + if (!service) +@@ -852,92 +727,57 @@ static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid, service->pmt.pid = ts->pmt_start_pid + ts->nb_services; service->sid = sid; service->pcr_pid = 0x1fff; + service->pcr_sid = 0x1fff; if (encode_str8(service->provider_name, provider_name) < 0 || - encode_str8(service->name, service_name) < 0) { +- encode_str8(service->name, service_name) < 0) { ++ encode_str8(service->name, name) < 0) { av_log(s, AV_LOG_ERROR, "Too long service or provider name\n"); -@@ -788,30 +781,32 @@ static void enable_pcr_generation_for_stream(AVFormatContext *s, AVStream *pcr_s - MpegTSWrite *ts = s->priv_data; - MpegTSWriteStream *ts_st = pcr_st->priv_data; + goto fail; + } + if (av_dynarray_add_nofree(&ts->services, &ts->nb_services, service) < 0) + goto fail; +- service->pmt.write_packet = section_write_packet; +- service->pmt.opaque = s; +- service->pmt.cc = 15; +- service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; +- service->program = program; +- + return service; + fail: + av_free(service); + return NULL; + } + +-static void enable_pcr_generation_for_stream(AVFormatContext *s, AVStream *pcr_st) ++static void mpegts_prefix_m2ts_header(AVFormatContext *s) + { + MpegTSWrite *ts = s->priv_data; +- MpegTSWriteStream *ts_st = pcr_st->priv_data; +- - if (ts->mux_rate > 1 || ts->pcr_period_ms >= 0) { - int pcr_period_ms = ts->pcr_period_ms == -1 ? PCR_RETRANS_TIME : ts->pcr_period_ms; - ts_st->pcr_period = av_rescale(pcr_period_ms, PCR_TIME_BASE, 1000); - } else { -+ int64_t pcr_period = -1; -+ if (ts->pcr_period_ms >= 0) -+ pcr_period = av_rescale(ts->pcr_period_ms, PCR_TIME_BASE, 1000); -+ else if (ts->mux_rate == 1) { - /* By default, for VBR we select the highest multiple of frame duration which is less than 100 ms. */ - int64_t frame_period = 0; - if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0); +- /* By default, for VBR we select the highest multiple of frame duration which is less than 100 ms. */ +- int64_t frame_period = 0; +- if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { +- int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0); - if (!frame_size) { -+ if (frame_size > 0) -+ frame_period = av_rescale_rnd(frame_size, PCR_TIME_BASE, pcr_st->codecpar->sample_rate, AV_ROUND_UP); -+ else - av_log(s, AV_LOG_WARNING, "frame size not set\n"); +- av_log(s, AV_LOG_WARNING, "frame size not set\n"); - frame_size = 512; - } - frame_period = av_rescale_rnd(frame_size, PCR_TIME_BASE, pcr_st->codecpar->sample_rate, AV_ROUND_UP); - } else if (pcr_st->avg_frame_rate.num) { - frame_period = av_rescale_rnd(pcr_st->avg_frame_rate.den, PCR_TIME_BASE, pcr_st->avg_frame_rate.num, AV_ROUND_UP); - } +- } else if (pcr_st->avg_frame_rate.num) { +- frame_period = av_rescale_rnd(pcr_st->avg_frame_rate.den, PCR_TIME_BASE, pcr_st->avg_frame_rate.num, AV_ROUND_UP); +- } - if (frame_period > 0 && frame_period <= PCR_TIME_BASE / 10) - ts_st->pcr_period = frame_period * (PCR_TIME_BASE / 10 / frame_period); - else - ts_st->pcr_period = 1; -+ if (frame_period > 0 && frame_period <= PCR_TIME_BASE / 10) { -+ int pcr_frames = (PCR_TIME_BASE / 10) / frame_period; -+ if( pcr_frames > 0 ) -+ pcr_period = frame_period * pcr_frames; -+ } ++ if (ts->m2ts_mode) { ++ 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)); } - -+ if( pcr_period < 0 ) -+ pcr_period = av_rescale(PCR_RETRANS_TIME, PCR_TIME_BASE, 1000); -+ ts_st->pcr_period = pcr_period; - // output a PCR as soon as possible +- // output a PCR as soon as possible - ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period; -+ ts_st->last_pcr = ts->first_pcr - pcr_period; } - static void select_pcr_streams(AVFormatContext *s) -@@ -823,22 +818,32 @@ static void select_pcr_streams(AVFormatContext *s) - AVStream *pcr_st = NULL; - AVProgram *program = service->program; - int nb_streams = program ? program->nb_stream_indexes : s->nb_streams; +-static void select_pcr_streams(AVFormatContext *s) ++static void section_write_packet(MpegTSSection *s, const uint8_t *packet) + { +- MpegTSWrite *ts = s->priv_data; - -+ /* find first video stream, or just use first stream */ - for (int j = 0; j < nb_streams; j++) { - AVStream *st = s->streams[program ? program->stream_index[j] : j]; +- for (int i = 0; i < ts->nb_services; i++) { +- MpegTSService *service = ts->services[i]; +- AVStream *pcr_st = NULL; +- AVProgram *program = service->program; +- int nb_streams = program ? program->nb_stream_indexes : s->nb_streams; +- +- for (int j = 0; j < nb_streams; j++) { +- AVStream *st = s->streams[program ? program->stream_index[j] : j]; - if (!pcr_st || - pcr_st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - { -+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - pcr_st = st; -+ break; - } - } +- pcr_st = st; +- } +- } - -+ if (!pcr_st && s->nb_streams > 0) -+ pcr_st = s->streams[0]; - if (pcr_st) { - MpegTSWriteStream *ts_st = pcr_st->priv_data; +- if (pcr_st) { +- MpegTSWriteStream *ts_st = pcr_st->priv_data; - service->pcr_pid = ts_st->pid; -+ service->pcr_sid = ts_st->pid; /* stream id for pcr writes */ -+ service->pcr_pid = ts->m2ts_mode > 1 ? /* pcr pid */ -+ 0x1000 + ts->service_id : ts_st->pid; - enable_pcr_generation_for_stream(s, pcr_st); - av_log(s, AV_LOG_VERBOSE, "service %i using PCR in pid=%i, pcr_period=%"PRId64"ms\n", - service->sid, service->pcr_pid, av_rescale(ts_st->pcr_period, 1000, PCR_TIME_BASE)); -+ for (int j = 0; j < nb_streams; j++) { -+ AVStream *st = s->streams[program ? program->stream_index[j] : j]; -+ MpegTSWriteStream *ts_st = st->priv_data; -+ ts_st->service = service; -+ } -+ if (service->pmt.pid == service->pcr_pid) { -+ av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", service->pcr_pid); -+ } - } - } +- enable_pcr_generation_for_stream(s, pcr_st); +- av_log(s, AV_LOG_VERBOSE, "service %i using PCR in pid=%i, pcr_period=%"PRId64"ms\n", +- service->sid, service->pcr_pid, av_rescale(ts_st->pcr_period, 1000, PCR_TIME_BASE)); +- } +- } ++ AVFormatContext *ctx = s->opaque; ++ mpegts_prefix_m2ts_header(ctx); ++ avio_write(ctx->pb, packet, TS_PACKET_SIZE); } -@@ -860,6 +865,15 @@ static int mpegts_init(AVFormatContext *s) - if (s->max_delay < 0) /* Not set by the caller */ - s->max_delay = 0; + static int mpegts_init(AVFormatContext *s) + { + MpegTSWrite *ts = s->priv_data; ++ MpegTSWriteStream *ts_st; ++ MpegTSService *service; ++ AVStream *st, *pcr_st = NULL; ++ AVDictionaryEntry *title, *provider; ++ double clk_rate; + int i, j; ++ const char *service_name; ++ const char *provider_name; ++ int *pids; + int ret; + ++ 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; -+ } -+ } + if (ts->m2ts_mode == -1) { + if (av_match_ext(s->url, "m2ts")) { + ts->m2ts_mode = 1; +@@ -946,36 +786,53 @@ static int mpegts_init(AVFormatContext *s) + } + } +- ts->m2ts_video_pid = M2TS_VIDEO_PID; +- ts->m2ts_audio_pid = M2TS_AUDIO_START_PID; +- ts->m2ts_pgssub_pid = M2TS_PGSSUB_START_PID; +- ts->m2ts_textsub_pid = M2TS_TEXTSUB_PID; +- +- if (ts->m2ts_mode) { +- ts->pmt_start_pid = M2TS_PMT_PID; +- if (s->nb_programs > 1) { +- av_log(s, AV_LOG_ERROR, "Only one program is allowed in m2ts mode!\n"); +- return AVERROR(EINVAL); +- } +- } +- +- if (s->max_delay < 0) /* Not set by the caller */ +- s->max_delay = 0; +- // round up to a whole number of TS packets ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14; -@@ -920,14 +934,11 @@ static int mpegts_init(AVFormatContext *s) - /* MPEG pid values < 16 are reserved. Applications which set st->id in - * this range are assigned a calculated pid. */ ++ ts->tsid = ts->transport_stream_id; ++ ts->onid = ts->original_network_id; + if (!s->nb_programs) { + /* allocate a single DVB service */ +- if (!mpegts_add_service(s, ts->service_id, s->metadata, NULL)) ++ title = av_dict_get(s->metadata, "service_name", NULL, 0); ++ if (!title) ++ title = av_dict_get(s->metadata, "title", NULL, 0); ++ service_name = title ? title->value : DEFAULT_SERVICE_NAME; ++ provider = av_dict_get(s->metadata, "service_provider", NULL, 0); ++ provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; ++ service = mpegts_add_service(s, ts->service_id, ++ provider_name, service_name); ++ ++ if (!service) + return AVERROR(ENOMEM); ++ ++ service->pmt.write_packet = section_write_packet; ++ service->pmt.opaque = s; ++ service->pmt.cc = 15; ++ service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; + } else { + for (i = 0; i < s->nb_programs; i++) { + AVProgram *program = s->programs[i]; +- if (!mpegts_add_service(s, program->id, program->metadata, program)) ++ title = av_dict_get(program->metadata, "service_name", NULL, 0); ++ if (!title) ++ title = av_dict_get(program->metadata, "title", NULL, 0); ++ service_name = title ? title->value : DEFAULT_SERVICE_NAME; ++ provider = av_dict_get(program->metadata, "service_provider", NULL, 0); ++ provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; ++ service = mpegts_add_service(s, program->id, ++ provider_name, service_name); ++ ++ if (!service) + return AVERROR(ENOMEM); ++ ++ service->pmt.write_packet = section_write_packet; ++ service->pmt.opaque = s; ++ service->pmt.cc = 15; ++ service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; ++ 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 +@@ -991,158 +848,175 @@ static int mpegts_init(AVFormatContext *s) + ts->sdt.write_packet = section_write_packet; + ts->sdt.opaque = s; + ++ pids = av_malloc_array(s->nb_streams, sizeof(*pids)); ++ if (!pids) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ + /* assign pids to each stream */ + for (i = 0; i < s->nb_streams; i++) { +- AVStream *st = s->streams[i]; +- MpegTSWriteStream *ts_st; ++ AVProgram *program; ++ st = s->streams[i]; + + ts_st = av_mallocz(sizeof(MpegTSWriteStream)); + if (!ts_st) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + st->priv_data = ts_st; + ++ ts_st->user_tb = st->time_base; + avpriv_set_pts_info(st, 33, 1, 90000); + + ts_st->payload = av_mallocz(ts->pes_payload_size); + if (!ts_st->payload) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + +- /* MPEG pid values < 16 are reserved. Applications which set st->id in +- * this range are assigned a calculated pid. */ - if (st->id < 16) { -- ts_st->pid = ts->start_pid + i; +- if (ts->m2ts_mode) { +- switch (st->codecpar->codec_type) { +- case AVMEDIA_TYPE_VIDEO: +- ts_st->pid = ts->m2ts_video_pid++; +- break; +- case AVMEDIA_TYPE_AUDIO: +- ts_st->pid = ts->m2ts_audio_pid++; +- break; +- case AVMEDIA_TYPE_SUBTITLE: +- switch (st->codecpar->codec_id) { +- case AV_CODEC_ID_HDMV_PGS_SUBTITLE: +- ts_st->pid = ts->m2ts_pgssub_pid++; +- break; +- case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: +- ts_st->pid = ts->m2ts_textsub_pid++; +- break; +- } ++ program = av_find_program_from_stream(s, NULL, i); ++ if (program) { ++ for (j = 0; j < ts->nb_services; j++) { ++ if (ts->services[j]->program == program) { ++ service = ts->services[j]; + break; + } +- if (ts->m2ts_video_pid > M2TS_VIDEO_PID + 1 || +- ts->m2ts_audio_pid > M2TS_AUDIO_START_PID + 32 || +- ts->m2ts_pgssub_pid > M2TS_PGSSUB_START_PID + 32 || +- ts->m2ts_textsub_pid > M2TS_TEXTSUB_PID + 1 || +- ts_st->pid < 16) { +- av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index); +- return AVERROR(EINVAL); +- } +- } else { +- ts_st->pid = ts->start_pid + i; + } - } else { - ts_st->pid = st->id; -- } + } - if (ts_st->pid >= 0x1FFF) { -+ ts_st->pid = ts->start_pid >= 0 ? ts->start_pid + i : -+ st->id >= 16 ? st->id : FIRST_OTHER_PID + i; -+ if (ts_st->pid < 16 || ts_st->pid >= 0x1FFF) { ++ ++ ts_st->service = service; ++ /* MPEG pid values < 16 are reserved. Applications which set st->id in ++ * this range are assigned a calculated pid. */ ++ if (st->id < 16) { ++ ts_st->pid = ts->start_pid + i; ++ } else if (st->id < 0x1FFF) { ++ ts_st->pid = st->id; ++ } else { av_log(s, AV_LOG_ERROR, -- "Invalid stream id %d, must be less than 8191\n", st->id); -+ "Invalid stream id %d, must be in 16...8191\n", ts_st->pid); - ret = AVERROR(EINVAL); - goto fail; + "Invalid stream id %d, must be less than 8191\n", st->id); +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } +- for (j = 0; j < ts->nb_services; j++) { +- if (ts->services[j]->pmt.pid > LAST_OTHER_PID) { +- av_log(s, AV_LOG_ERROR, +- "Invalid PMT PID %d, must be less than %d\n", ts->services[j]->pmt.pid, LAST_OTHER_PID + 1); +- return AVERROR(EINVAL); +- } +- if (ts_st->pid == ts->services[j]->pmt.pid) { +- av_log(s, AV_LOG_ERROR, "PID %d cannot be both elementary and PMT PID\n", ts_st->pid); +- return AVERROR(EINVAL); +- } ++ if (ts_st->pid == service->pmt.pid) { ++ av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); ++ ret = AVERROR(EINVAL); ++ goto fail; + } + for (j = 0; j < i; j++) { +- MpegTSWriteStream *ts_st_prev = s->streams[j]->priv_data; +- if (ts_st_prev->pid == ts_st->pid) { ++ if (pids[j] == ts_st->pid) { + av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } } -@@ -998,8 +1009,8 @@ static int mpegts_init(AVFormatContext *s) ++ pids[i] = ts_st->pid; + ts_st->payload_pts = AV_NOPTS_VALUE; + ts_st->payload_dts = AV_NOPTS_VALUE; + ts_st->first_pts_check = 1; + ts_st->cc = 15; + 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_sid == 0x1fff) ++ pcr_st = st; ++ + if (st->codecpar->codec_id == AV_CODEC_ID_AAC && + st->codecpar->extradata_size > 0) { + AVStream *ast; + ts_st->amux = avformat_alloc_context(); + if (!ts_st->amux) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + ts_st->amux->oformat = + av_guess_format((ts->flags & MPEGTS_FLAG_AAC_LATM) ? "latm" : "adts", + NULL, NULL); + if (!ts_st->amux->oformat) { +- return AVERROR(EINVAL); ++ ret = AVERROR(EINVAL); ++ goto fail; + } + if (!(ast = avformat_new_stream(ts_st->amux, NULL))) { +- return AVERROR(ENOMEM); ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + ret = avcodec_parameters_copy(ast->codecpar, st->codecpar); + if (ret != 0) +- return ret; ++ goto fail; + ast->time_base = st->time_base; + ret = avformat_write_header(ts_st->amux, NULL); + if (ret < 0) +- return ret; ++ goto fail; + } + if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { + ts_st->opus_pending_trim_start = st->codecpar->initial_padding * 48000 / st->codecpar->sample_rate; + } + } - ts->last_pat_ts = AV_NOPTS_VALUE; - ts->last_sdt_ts = AV_NOPTS_VALUE; ++ av_freep(&pids); ++ ++ /* if no video stream, use the first stream as PCR */ ++ 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; ++ } ++ 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); + +- select_pcr_streams(s); +- +- ts->last_pat_ts = AV_NOPTS_VALUE; +- ts->last_sdt_ts = AV_NOPTS_VALUE; - ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE); - ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE); -+ ts->pat_period = av_rescale(ts->pat_period_ms, PCR_TIME_BASE, 1000); -+ ts->sdt_period = av_rescale(ts->sdt_period_ms, PCR_TIME_BASE, 1000); ++ // output a PCR as soon as possible ++ 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, "); -@@ -1022,20 +1033,16 @@ static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, + else + av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate); +- av_log(s, AV_LOG_VERBOSE, +- "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms\n", +- av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE), +- av_rescale(ts->pat_period, 1000, PCR_TIME_BASE)); + + return 0; ++ ++fail: ++ av_freep(&pids); ++ return ret; + } + + /* send SDT, PAT and PMT tables regularly */ +-static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int64_t pcr) ++static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts) { MpegTSWrite *ts = s->priv_data; int i; -- + - if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) || - (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) || - force_sdt - ) { - if (pcr != AV_NOPTS_VALUE) - ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts); -+ if (force_sdt || (ts->sdt_period >= 0 && pcr != AV_NOPTS_VALUE && -+ (ts->last_sdt_ts == AV_NOPTS_VALUE || (pcr - ts->last_sdt_ts >= ts->sdt_period)) )) { -+ if (pcr > ts->last_sdt_ts) -+ ts->last_sdt_ts = pcr; ++ 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 ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) || @@ -254,14 +849,22 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c - force_pat) { - if (pcr != AV_NOPTS_VALUE) - ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts); -+ if (force_pat || (ts->pat_period >= 0 && pcr != AV_NOPTS_VALUE && -+ (ts->last_pat_ts == AV_NOPTS_VALUE || (pcr - ts->last_pat_ts >= ts->pat_period)) )) { -+ if (pcr > ts->last_pat_ts) -+ ts->last_pat_ts = pcr; ++ 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]); -@@ -1076,13 +1083,14 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) +@@ -1175,7 +1049,8 @@ static void mpegts_insert_null_packet(AVFormatContext *s) + *q++ = 0xff; + *q++ = 0x10; + memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf)); +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + + /* Write a single transport stream packet with a PCR and no payload */ +@@ -1183,13 +1058,14 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) { MpegTSWrite *ts = s->priv_data; MpegTSWriteStream *ts_st = st->priv_data; @@ -278,7 +881,7 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c *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 */ -@@ -1093,7 +1101,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) +@@ -1200,11 +1076,12 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) } /* PCR coded into 6 bytes */ @@ -287,16 +890,31 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c /* stuffing bytes */ memset(q, 0xFF, TS_PACKET_SIZE - (q - buf)); -@@ -1161,7 +1169,6 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + + static void write_pts(uint8_t *q, int fourbits, int64_t pts) +@@ -1268,84 +1145,55 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, 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 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; - int force_sdt = 0; +- int force_sdt = 0; -@@ -1178,67 +1185,46 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, + av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO); + if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + force_pat = 1; + } +- if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { +- force_pat = 1; +- force_sdt = 1; +- ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT; +- } +- is_start = 1; while (payload_size > 0) { - int64_t pcr = AV_NOPTS_VALUE; @@ -310,9 +928,9 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c + av_rescale(avio_tell(s->pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate)); - retransmit_si_info(s, force_pat, force_sdt, pcr); -+ retransmit_si_info(s, force_pat, force_sdt, ts->pcr); ++ retransmit_si_info(s, force_pat, dts); force_pat = 0; - force_sdt = 0; +- force_sdt = 0; write_pcr = 0; - if (ts->mux_rate > 1) { @@ -353,29 +971,26 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c - } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) { - if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) { - ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period); -- write_pcr = 1; -- } -+ if (ts_st->pcr_period > 0 && ts_st->pid == ts_st->service->pcr_sid && -+ ts->pcr - ts_st->last_pcr >= ts_st->pcr_period) { -+ ts_st->last_pcr = ts->pcr; -+ write_pcr = 1; -+ } ++ 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) { -+ /* pcr is on a seperate stream */ -+ mpegts_insert_pcr_only(s, st); -+ continue; ++ mpegts_insert_pcr_only(s, st); ++ continue; + } -+ + if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE && + (dts - ts->pcr / 300) > ts->delay) { -+ /* pcr insert gets priority over null packet insert */ -+ if (write_pcr) -+ mpegts_insert_pcr_only(s, st); ++ /* pcr insert gets priority over null packet insert */ ++ if (write_pcr) ++ mpegts_insert_pcr_only(s, st); + else -+ mpegts_insert_null_packet(s); ++ mpegts_insert_null_packet(s); + /* recalculate write_pcr and possibly retransimit si_info */ + continue; - } ++ } /* prepare packet header */ q = buf; @@ -385,26 +1000,29 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c - val |= 0x20; if (is_start) val |= 0x40; -+ if (ts->m2ts_mode && st->codecpar->codec_id == AV_CODEC_ID_AC3) ++ 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; -@@ -1250,7 +1236,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, +@@ -1357,7 +1205,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, } if (key && is_start && pts != AV_NOPTS_VALUE) { // set Random Access for key frames - if (ts_st->pcr_period) -+ if ( ts_st->pcr_period > 0 && ts_st->pid == ts_st->service->pcr_sid ) ++ if (ts_st->pid == ts_st->service->pcr_sid) write_pcr = 1; set_af_flag(buf, 0x40); q = get_ts_payload_start(buf); -@@ -1258,10 +1244,9 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, +@@ -1365,10 +1213,10 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, 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 (dts != AV_NOPTS_VALUE && dts < pcr / 300) ++ if (ts->mux_rate > 1) + 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)); @@ -412,7 +1030,22 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c q = get_ts_payload_start(buf); } if (is_start) { -@@ -1362,11 +1347,13 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, +@@ -1439,10 +1287,10 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, + if (ts->m2ts_mode && + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->codec_id == AV_CODEC_ID_AC3) { +- /* set PES_extension_flag */ +- pes_extension = 1; +- flags |= 0x01; +- header_len += 3; ++ /* set PES_extension_flag */ ++ pes_extension = 1; ++ flags |= 0x01; ++ header_len += 3; + } + if (is_dvb_teletext) { + pes_header_stuffing_bytes = 0x24 - header_len; +@@ -1469,11 +1317,13 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, *q++ = flags; *q++ = header_len; if (pts != AV_NOPTS_VALUE) { @@ -428,64 +1061,275 @@ diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c q += 5; } if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) { -@@ -1536,7 +1523,6 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) +@@ -1485,14 +1335,14 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, + *q++ = 0x00 | 0x60; + } + /* For Blu-ray AC3 Audio Setting extended flags */ +- if (ts->m2ts_mode && +- pes_extension && +- st->codecpar->codec_id == AV_CODEC_ID_AC3) { +- flags = 0x01; /* set PES_extension_flag_2 */ +- *q++ = flags; +- *q++ = 0x80 | 0x01; /* marker bit + extension length */ +- *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ +- } ++ if (ts->m2ts_mode && ++ pes_extension && ++ st->codecpar->codec_id == AV_CODEC_ID_AC3) { ++ flags = 0x01; /* set PES_extension_flag_2 */ ++ *q++ = flags; ++ *q++ = 0x80 | 0x01; /* marker bit + extension length */ ++ *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ ++ } + + + if (is_dvb_subtitle) { +@@ -1546,7 +1396,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, + + payload += len; + payload_size -= len; +- write_packet(s, buf); ++ mpegts_prefix_m2ts_header(s); ++ avio_write(s->pb, buf, TS_PACKET_SIZE); + } + ts_st->prev_payload_key = key; + } +@@ -1643,8 +1494,6 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) 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; - const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2; +- const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2; int64_t dts = pkt->dts, pts = pkt->pts; int opus_samples = 0; -@@ -1552,9 +1538,9 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + int side_data_size; +@@ -1657,11 +1506,23 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + if (side_data) + stream_id = side_data[0]; ++ if (ts->reemit_pat_pmt) { ++ av_log(s, AV_LOG_WARNING, ++ "resend_headers option is deprecated, use -mpegts_flags resend_headers\n"); ++ ts->reemit_pat_pmt = 0; ++ ts->flags |= MPEGTS_FLAG_REEMIT_PAT_PMT; ++ } ++ ++ if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { ++ 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 += ts->delay * 2; ++ pts += 2*ts->delay; if (dts != AV_NOPTS_VALUE) - dts += delay; -+ dts += ts->delay * 2; ++ dts += 2*ts->delay; } if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) { -@@ -1904,10 +1890,13 @@ static const AVOption options[] = { - { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, AV_OPT_FLAG_ENCODING_PARAM }, +@@ -1724,7 +1585,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + + ret = avio_open_dyn_buf(&ts_st->amux->pb); + if (ret < 0) +- return ret; ++ return AVERROR(ENOMEM); + + ret = av_write_frame(ts_st->amux, &pkt2); + if (ret < 0) { +@@ -1755,7 +1616,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + } while (p < buf_end && (state & 0x7e) != 2*35 && + (state & 0x7e) >= 2*32); + +- if ((state & 0x7e) < 2*16 || (state & 0x7e) >= 2*24) ++ if ((state & 0x7e) < 2*16 && (state & 0x7e) >= 2*24) + extradd = 0; + if ((state & 0x7e) != 2*35) { // AUD NAL + data = av_malloc(pkt->size + 7 + extradd); +@@ -1843,9 +1704,25 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + } + } + ++ if (pkt->dts != AV_NOPTS_VALUE) { ++ int i; ++ for(i=0; inb_streams; i++) { ++ 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 > 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); ++ ts_st2->payload_size = 0; ++ } ++ } ++ } ++ + if (ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size || + (dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE && +- dts - ts_st->payload_dts >= max_audio_delay) || ++ av_compare_ts(dts - ts_st->payload_dts, st->time_base, ++ s->max_delay, AV_TIME_BASE_Q) >= 0) || + ts_st->opus_queued_samples + opus_samples >= 5760 /* 120ms */)) { + mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size, + ts_st->payload_pts, ts_st->payload_dts, +@@ -1881,7 +1758,6 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + + static void mpegts_write_flush(AVFormatContext *s) + { +- MpegTSWrite *ts = s->priv_data; + int i; + + /* flush current packets */ +@@ -1896,12 +1772,6 @@ static void mpegts_write_flush(AVFormatContext *s) + ts_st->opus_queued_samples = 0; + } + } +- +- if (ts->m2ts_mode) { +- int packets = (avio_tell(s->pb) / (TS_PACKET_SIZE + 4)) % 32; +- while (packets++ < 32) +- mpegts_insert_null_packet(s); +- } + } + + static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) +@@ -1969,62 +1839,104 @@ static int mpegts_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt + return ret; + } + +-#define OFFSET(x) offsetof(MpegTSWrite, x) +-#define ENC AV_OPT_FLAG_ENCODING_PARAM + static const AVOption options[] = { + { "mpegts_transport_stream_id", "Set transport_stream_id field.", +- OFFSET(transport_stream_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, ++ { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_original_network_id", "Set original_network_id field.", +- OFFSET(original_network_id), AV_OPT_TYPE_INT, { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, original_network_id), AV_OPT_TYPE_INT, ++ { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_service_id", "Set service_id field.", +- OFFSET(service_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, ++ offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, ++ { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + { "mpegts_service_type", "Set service_type field.", +- OFFSET(service_type), AV_OPT_TYPE_INT, { .i64 = 0x01 }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ offsetof(MpegTSWrite, service_type), AV_OPT_TYPE_INT, ++ { .i64 = 0x01 }, 0x01, 0xff, AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "digital_tv", "Digital Television.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "digital_radio", "Digital Radio.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "teletext", "Teletext.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_radio", "Advanced Codec Digital Radio.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "mpeg2_digital_hdtv", "MPEG2 Digital HDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_sdtv", "Advanced Codec Digital SDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "advanced_codec_digital_hdtv", "Advanced Codec Digital HDTV.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "hevc_digital_hdtv", "HEVC Digital Television Service.", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + { "mpegts_pmt_start_pid", "Set the first pid of the PMT.", +- OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, ++ 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 }, FIRST_OTHER_PID, LAST_OTHER_PID, AV_OPT_FLAG_ENCODING_PARAM }, -+ { .i64 = -1 }, -1, LAST_OTHER_PID, 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 }, -+ offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT, +- OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, +- { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, +- { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, ++ 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, 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 }, -@@ -1941,15 +1930,15 @@ static const AVOption options[] = { ++ { "muxrate", NULL, ++ offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, ++ { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { "pes_payload_size", "Minimum PES packet payload in bytes", +- OFFSET(pes_payload_size), AV_OPT_TYPE_INT, { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, ENC }, +- { "mpegts_flags", "MPEG-TS muxing flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, ++ { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "mpegts_flags", "MPEG-TS muxing flags", ++ offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "resend_headers", "Reemit PAT/PMT before writing the next packet", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "latm", "Use LATM packetization for AAC", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "pat_pmt_at_frames", "Reemit PAT and PMT at each video frame", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "system_b", "Conform to System B (DVB) instead of System A (ATSC)", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, ENC, "mpegts_flags" }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + { "initial_discontinuity", "Mark initial packets as discontinuous", +- 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, ENC, "mpegts_flags" }, +- { "mpegts_copyts", "don't offset dts/pts", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, +- { "tables_version", "set PAT, PMT and SDT version", OFFSET(tables_version), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 31, ENC }, ++ 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, ++ AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, ++ // backward compatibility ++ { "resend_headers", "Reemit PAT/PMT before writing the next packet", ++ offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, ++ { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "mpegts_copyts", "don't offset dts/pts", ++ offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_BOOL, ++ { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM }, ++ { "tables_version", "set PAT, PMT and SDT version", ++ offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, ++ { .i64 = 0 }, 0, 31, AV_OPT_FLAG_ENCODING_PARAM }, { "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 }, +- OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, - { "pcr_period", "PCR retransmission time in milliseconds", -- offsetof(MpegTSWrite, pcr_period_ms), AV_OPT_TYPE_INT, -- { .i64 = -1 }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, +- OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC }, - { "pat_period", "PAT/PMT retransmission time limit in seconds", -- offsetof(MpegTSWrite, pat_period_us), AV_OPT_TYPE_DURATION, -- { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM }, +- OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, - { "sdt_period", "SDT retransmission time limit in seconds", -- offsetof(MpegTSWrite, sdt_period_us), AV_OPT_TYPE_DURATION, -- { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM }, +- OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, ++ offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL, ++ { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, + { "pcr_period", "PCR retransmission time limit in msecs", -+ offsetof(MpegTSWrite, pcr_period_ms), AV_OPT_TYPE_DOUBLE, -+ { .dbl = -1 }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, ++ 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_ms), AV_OPT_TYPE_DOUBLE, ++ offsetof(MpegTSWrite, pat_period), AV_OPT_TYPE_DOUBLE, + { .dbl = PAT_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { "sdt_period", "SDT retransmission time limit in msecs", -+ offsetof(MpegTSWrite, sdt_period_ms), AV_OPT_TYPE_DOUBLE, ++ offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE, + { .dbl = SDT_RETRANS_TIME }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch3 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch3 index e37f37a9..fb8730e4 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch3 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch3 @@ -1,7 +1,8 @@ -diff -urN a/libavformat/avformat.h b/libavformat/avformat.h ---- a/libavformat/avformat.h 2019-12-02 08:48:03.103361418 -0700 -+++ b/libavformat/avformat.h 2019-12-02 08:52:16.724218813 -0700 -@@ -485,6 +485,9 @@ +diff --git a/libavformat/avformat.h b/libavformat/avformat.h +index e91e7f1d33..0f9b26a6d3 100644 +--- a/libavformat/avformat.h ++++ b/libavformat/avformat.h +@@ -480,6 +480,9 @@ typedef struct AVProbeData { The user or muxer can override this through AVFormatContext.avoid_negative_ts */ @@ -11,7 +12,7 @@ diff -urN a/libavformat/avformat.h b/libavformat/avformat.h #define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ -@@ -654,7 +657,8 @@ +@@ -650,7 +653,8 @@ typedef struct AVInputFormat { /** * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, @@ -21,10 +22,11 @@ diff -urN a/libavformat/avformat.h b/libavformat/avformat.h */ int flags; -diff -urN a/libavformat/dv.c b/libavformat/dv.c ---- a/libavformat/dv.c 2019-12-02 08:48:03.107361432 -0700 -+++ b/libavformat/dv.c 2019-12-02 08:52:16.724218813 -0700 -@@ -642,6 +642,7 @@ +diff --git a/libavformat/dv.c b/libavformat/dv.c +index e99422d4b5..58ce1bbb5f 100644 +--- a/libavformat/dv.c ++++ b/libavformat/dv.c +@@ -642,6 +642,7 @@ static int dv_probe(const AVProbeData *p) AVInputFormat ff_dv_demuxer = { .name = "dv", .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), @@ -32,10 +34,11 @@ diff -urN a/libavformat/dv.c b/libavformat/dv.c .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 2019-12-02 08:48:03.116361462 -0700 -+++ b/libavformat/matroskadec.c 2019-12-02 08:52:16.725218816 -0700 -@@ -4224,6 +4224,7 @@ +diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c +index cff7f0cb54..8b6d22aff2 100644 +--- a/libavformat/matroskadec.c ++++ b/libavformat/matroskadec.c +@@ -4251,6 +4251,7 @@ static const AVClass webm_dash_class = { AVInputFormat ff_matroska_demuxer = { .name = "matroska,webm", .long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), @@ -43,7 +46,7 @@ diff -urN a/libavformat/matroskadec.c b/libavformat/matroskadec.c .extensions = "mkv,mk3d,mka,mks", .priv_data_size = sizeof(MatroskaDemuxContext), .read_probe = matroska_probe, -@@ -4237,6 +4238,7 @@ +@@ -4264,6 +4265,7 @@ AVInputFormat ff_matroska_demuxer = { AVInputFormat ff_webm_dash_manifest_demuxer = { .name = "webm_dash_manifest", .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), @@ -51,10 +54,11 @@ diff -urN 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 -urN a/libavformat/utils.c b/libavformat/utils.c ---- a/libavformat/utils.c 2019-12-02 08:48:03.138361536 -0700 -+++ b/libavformat/utils.c 2019-12-02 08:52:16.726218820 -0700 -@@ -2488,6 +2488,13 @@ +diff --git a/libavformat/utils.c b/libavformat/utils.c +index 807d9f10cb..55a444e7b6 100644 +--- a/libavformat/utils.c ++++ b/libavformat/utils.c +@@ -2486,6 +2486,13 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index, return seek_frame_byte(s, stream_index, timestamp, flags); } diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch4 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch4 index 08bdcf24..02c27428 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch4 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch4 @@ -1,7 +1,8 @@ -diff -urN a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c ---- a/libavfilter/af_aformat.c 2019-12-02 08:48:03.060361273 -0700 -+++ b/libavfilter/af_aformat.c 2019-12-02 08:52:25.619248884 -0700 -@@ -109,6 +109,16 @@ +diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c +index 1a702778c3..232d629ba0 100644 +--- a/libavfilter/af_aformat.c ++++ b/libavfilter/af_aformat.c +@@ -112,6 +112,16 @@ static av_cold int init(AVFilterContext *ctx) return 0; } @@ -18,7 +19,7 @@ diff -urN a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c static int query_formats(AVFilterContext *ctx) { AFormatContext *s = ctx->priv; -@@ -146,6 +156,7 @@ +@@ -149,6 +159,7 @@ AVFilter ff_af_aformat = { .name = "aformat", .description = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."), .init = init, diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch5 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch5 index 3469f024..32e7fe11 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch5 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch5 @@ -1,7 +1,8 @@ -diff -urN a/libavfilter/formats.c b/libavfilter/formats.c ---- a/libavfilter/formats.c 2019-12-02 08:48:03.073361317 -0700 -+++ b/libavfilter/formats.c 2019-12-02 08:52:32.155270978 -0700 -@@ -107,11 +107,13 @@ +diff --git a/libavfilter/formats.c b/libavfilter/formats.c +index de4315369d..f430908343 100644 +--- a/libavfilter/formats.c ++++ b/libavfilter/formats.c +@@ -107,11 +107,13 @@ AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, possibly causing a lossy conversion elsewhere in the graph. To avoid that, pretend that there are no common formats to force the insertion of a conversion filter. */ @@ -18,7 +19,7 @@ diff -urN a/libavfilter/formats.c b/libavfilter/formats.c alpha2 |= adesc->flags & bdesc->flags & AV_PIX_FMT_FLAG_ALPHA; chroma2|= adesc->nb_components > 1 && bdesc->nb_components > 1; if (a->formats[i] == b->formats[j]) { -@@ -119,6 +121,8 @@ +@@ -119,6 +121,8 @@ AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, chroma1|= adesc->nb_components > 1; } } diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch6 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch6 index 90094716..e59a17cc 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch6 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch6 @@ -1,7 +1,8 @@ -diff -urN a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c ---- a/libavcodec/vdpau_mpeg12.c 2019-12-02 08:48:03.027361161 -0700 -+++ b/libavcodec/vdpau_mpeg12.c 2019-12-02 08:52:38.667292990 -0700 -@@ -114,6 +114,7 @@ +diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c +index 72220ffb4e..5687c416c9 100644 +--- a/libavcodec/vdpau_mpeg12.c ++++ b/libavcodec/vdpau_mpeg12.c +@@ -114,6 +114,7 @@ const AVHWAccel ff_mpeg1_vdpau_hwaccel = { .frame_priv_data_size = sizeof(struct vdpau_picture_context), .init = vdpau_mpeg1_init, .uninit = ff_vdpau_common_uninit, diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch7 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch7 index 231e05f5..05d3b1d0 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch7 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch7 @@ -1,7 +1,8 @@ -diff -urN a/libavcodec/h263dec.c b/libavcodec/h263dec.c ---- a/libavcodec/h263dec.c 2019-12-02 08:48:02.926360820 -0700 -+++ b/libavcodec/h263dec.c 2019-12-02 08:52:52.428339509 -0700 -@@ -684,7 +684,7 @@ +diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c +index 3b29a189e9..681a4187c5 100644 +--- a/libavcodec/h263dec.c ++++ b/libavcodec/h263dec.c +@@ -684,7 +684,7 @@ frame_end: if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4) ff_mpeg4_frame_end(avctx, buf, buf_size); diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch8 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch8 index 9518ad75..51bc09e3 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch8 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch8 @@ -1,6 +1,8 @@ ---- a/libavformat/mpegenc.c 2019-08-05 14:52:21.000000000 -0600 -+++ /blibavformat/mpegenc.c 2019-11-14 14:07:57.407883232 -0700 -@@ -981,9 +981,9 @@ +diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c +index 9bd0a555d4..111a9f3a46 100644 +--- a/libavformat/mpegenc.c ++++ b/libavformat/mpegenc.c +@@ -976,9 +976,9 @@ static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr) PacketDesc *pkt_desc; while ((pkt_desc = stream->predecode_packet) && diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 index ad17541c..0cf24e74 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 @@ -1,8 +1,8 @@ diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c -index a87c280cf7..718def3dab 100644 +index 718a449b6e..84685fe1d9 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c -@@ -296,9 +296,11 @@ static void cuda_device_uninit(AVHWDeviceContext *device_ctx) +@@ -269,9 +269,11 @@ static void cuda_device_uninit(AVHWDeviceContext *device_ctx) CudaFunctions *cu = hwctx->internal->cuda_dl; if (hwctx->internal->is_allocated && hwctx->cuda_ctx) { @@ -14,7 +14,7 @@ index a87c280cf7..718def3dab 100644 CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx)); hwctx->cuda_ctx = NULL; -@@ -348,7 +350,7 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { +@@ -321,7 +323,7 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { cu = hwctx->internal->cuda_dl; hwctx->internal->flags = flags; @@ -23,7 +23,7 @@ index a87c280cf7..718def3dab 100644 if (flags & AV_CUDA_USE_PRIMARY_CONTEXT) { ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device, &dev_flags, &dev_active)); -@@ -369,7 +371,9 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { +@@ -342,7 +344,9 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { hwctx->internal->cuda_device)); if (ret < 0) return ret; diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patchA b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patchA new file mode 100644 index 00000000..6d181e3c --- /dev/null +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patchA @@ -0,0 +1,24 @@ +diff --git a/libavutil/hwcontext_vdpau.c b/libavutil/hwcontext_vdpau.c +index dbef5495af..fba06d8ccf 100644 +--- a/libavutil/hwcontext_vdpau.c ++++ b/libavutil/hwcontext_vdpau.c +@@ -68,6 +68,11 @@ static const VDPAUPixFmtMap pix_fmts_420[] = { + { 0, AV_PIX_FMT_NONE, }, + }; + ++static const VDPAUPixFmtMap pix_fmts_420j[] = { ++ { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUVJ420P }, ++ { 0, AV_PIX_FMT_NONE, }, ++}; ++ + static const VDPAUPixFmtMap pix_fmts_422[] = { + { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV16 }, + { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV422P }, +@@ -92,6 +97,7 @@ static const struct { + const VDPAUPixFmtMap *map; + } vdpau_pix_fmts[] = { + { VDP_CHROMA_TYPE_420, AV_PIX_FMT_YUV420P, pix_fmts_420 }, ++ { VDP_CHROMA_TYPE_420, AV_PIX_FMT_YUVJ420P, pix_fmts_420j }, + { VDP_CHROMA_TYPE_422, AV_PIX_FMT_YUV422P, pix_fmts_422 }, + { VDP_CHROMA_TYPE_444, AV_PIX_FMT_YUV444P, pix_fmts_444 }, + #ifdef VDP_YCBCR_FORMAT_P016 diff --git a/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz index ed5cb753..7c487066 100644 Binary files a/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz and b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libaom-v1.0.0.tar.xz b/cinelerra-5.1/thirdparty/src/libaom-v1.0.0.tar.xz deleted file mode 100644 index f5d4fee9..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libaom-v1.0.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libaom-v3.0.0.tar.xz b/cinelerra-5.1/thirdparty/src/libaom-v3.0.0.tar.xz new file mode 100644 index 00000000..8151759e Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libaom-v3.0.0.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz deleted file mode 100644 index 5c5ba84c..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.5.tar.xz b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.5.tar.xz new file mode 100644 index 00000000..734f1535 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.5.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libvorbis-1.3.6.tar.xz b/cinelerra-5.1/thirdparty/src/libvorbis-1.3.6.tar.xz deleted file mode 100644 index fb018e31..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libvorbis-1.3.6.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libvorbis-1.3.7.tar.xz b/cinelerra-5.1/thirdparty/src/libvorbis-1.3.7.tar.xz new file mode 100644 index 00000000..7cf72b02 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libvorbis-1.3.7.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libvpx-1.8.1.tar.xz b/cinelerra-5.1/thirdparty/src/libvpx-1.8.1.tar.xz deleted file mode 100644 index caef48da..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libvpx-1.8.1.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libvpx-1.8.2.tar.xz b/cinelerra-5.1/thirdparty/src/libvpx-1.8.2.tar.xz new file mode 100644 index 00000000..66a5dd3e Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libvpx-1.8.2.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz b/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz deleted file mode 100644 index f32ac800..00000000 Binary files a/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/lilv-0.24.8.tar.xz b/cinelerra-5.1/thirdparty/src/lilv-0.24.8.tar.xz new file mode 100644 index 00000000..9be2e8fb Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/lilv-0.24.8.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/lv2-1.16.0.tar.xz b/cinelerra-5.1/thirdparty/src/lv2-1.16.0.tar.xz deleted file mode 100644 index 9b57f632..00000000 Binary files a/cinelerra-5.1/thirdparty/src/lv2-1.16.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/lv2-1.18.0.tar.xz b/cinelerra-5.1/thirdparty/src/lv2-1.18.0.tar.xz new file mode 100644 index 00000000..acb42910 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/lv2-1.18.0.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz b/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz deleted file mode 100644 index 25b82e81..00000000 Binary files a/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/serd-0.30.4.tar.xz b/cinelerra-5.1/thirdparty/src/serd-0.30.4.tar.xz new file mode 100644 index 00000000..98c145d9 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/serd-0.30.4.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz b/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz deleted file mode 100644 index 31621288..00000000 Binary files a/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/x265_3.4.tar.xz b/cinelerra-5.1/thirdparty/src/x265_3.4.tar.xz new file mode 100644 index 00000000..709c382a Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/x265_3.4.tar.xz differ