From: GetAway Date: Sun, 18 Mar 2018 16:27:53 +0000 (+0100) Subject: add 1. part to build neutrino for hd51 X-Git-Url: https://git.webhop.me/?a=commitdiff_plain;h=0ac247a228f28e51f6d34f07eca1dccf3056fe48;p=bs-cst-neutrino-hd.git add 1. part to build neutrino for hd51 use ext crosstool to build and run neutrino. Not more yet --- diff --git a/Makefile b/Makefile index 5d1696f..330b864 100755 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ include make/kernel.mk include make/drivers.mk include make/flashimage.mk include make/cleantargets.mk +include make/ffmpeg.mk ############################################################################ # a print out of environment variables @@ -76,7 +77,7 @@ printenv: @echo " later, you might find those useful:" @echo " * make update-self - update the build system" @echo " * make update-neutrino - update the neutrino source" - @echo " * make update-git - update the coolstream git" + @echo " * make update-git - update the coolstream/armbox git" @echo " * make update-git-target - copy updated git into \$$TARGETPREFIX" @echo "" @echo " cleantargets:" @@ -100,13 +101,22 @@ update-self: update-neutrino: $(MAKE) $(SOURCE_DIR)/neutrino-hd -update-git: +update-git-coolstream: $(MAKE) $(GIT_BOOTLOADER) $(MAKE) $(GIT_DRIVERS_THIRDPARTY) $(MAKE) $(GIT_DRIVERS) $(MAKE) $(GIT_KERNEL) $(MAKE) $(GIT_PLUGINS) +update-git-armbox: + $(MAKE) $(GIT_LIBSTB_HAL) +# $(MAKE) $(GIT_BOOTLOADER) +# $(MAKE) $(GIT_DRIVERS) +# $(MAKE) $(GIT_KERNEL_HD51) + $(MAKE) $(GIT_PLUGINS) + +update-git: update-git-$(BOXTYPE) + update-git-target: $(MAKE) modules includes-and-libs @@ -159,8 +169,23 @@ wittinobi-all: @echo "" # prerequisites.mk -prerequisites: - $(MAKE) $(SOURCE_DIR)/neutrino-hd $(GIT_BOOTLOADER) $(GIT_DRIVERS_THIRDPARTY) $(GIT_DRIVERS) $(GIT_KERNEL) $(GIT_PLUGINS) +prerequisites-coolstream: + $(MAKE) $(SOURCE_DIR)/neutrino-hd + $(MAKE) $(GIT_BOOTLOADER) + $(MAKE) $(GIT_DRIVERS_THIRDPARTY) + $(MAKE) $(GIT_DRIVERS) + $(MAKE) $(GIT_KERNEL) + $(MAKE) $(GIT_PLUGINS) + +prerequisites-armbox: + $(MAKE) $(SOURCE_DIR)/neutrino-hd +# $(MAKE) $(GIT_BOOTLOADER) +# $(MAKE) $(GIT_DRIVERS_THIRDPARTY) +# $(MAKE) $(GIT_DRIVERS) +# $(MAKE) $(GIT_KERNEL) + $(MAKE) $(GIT_PLUGINS) + +prerequisites: prerequisites-$(BOXTYPE) # bootstrap.mk BOOTSTRAP = targetprefix $(BUILD_TMP) $(CROSS_BASE) $(HOSTPREFIX)/bin @@ -183,6 +208,7 @@ post-customize: $(BASE_DIR)/customize/post-customize.sh # neutrino.mk neutrino: $(MAKE) $(D)/neutrino-hd + neutrino-libs: $(MAKE) $(D)/neutrino-hd-libs @@ -315,7 +341,7 @@ PHONY += neutrino-libs PHONY += applications PHONY += multimedia PHONY += plugins -PHONY += kernel -PHONY += bootloader -PHONY += drivers +#PHONY += kernel +#PHONY += bootloader +#PHONY += drivers .PHONY: $(PHONY) diff --git a/archive-patches/alsa-lib-1.1.5-link_fix.patch b/archive-patches/alsa-lib-1.1.5-link_fix.patch new file mode 100644 index 0000000..2869dbf --- /dev/null +++ b/archive-patches/alsa-lib-1.1.5-link_fix.patch @@ -0,0 +1,22 @@ +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -421,7 +421,7 @@ clean-libLTLIBRARIES: + rm -f $${locs}; \ + } + libasound.la: $(libasound_la_OBJECTS) $(libasound_la_DEPENDENCIES) $(EXTRA_libasound_la_DEPENDENCIES) +- $(AM_V_CCLD)$(libasound_la_LINK) -rpath $(libdir) $(libasound_la_OBJECTS) $(libasound_la_LIBADD) $(LIBS) ++ $(AM_V_CCLD)$(libasound_la_LINK) -rpath $(DESTDIR)$(libdir) $(libasound_la_OBJECTS) $(libasound_la_LIBADD) $(LIBS) + + mostlyclean-compile: + -rm -f *.$(OBJEXT) +--- a/src/pcm/scopes/Makefile.in ++++ b/src/pcm/scopes/Makefile.in +@@ -348,7 +348,7 @@ clean-pkglibLTLIBRARIES: + rm -f $${locs}; \ + } + scope-level.la: $(scope_level_la_OBJECTS) $(scope_level_la_DEPENDENCIES) $(EXTRA_scope_level_la_DEPENDENCIES) +- $(AM_V_CCLD)$(scope_level_la_LINK) -rpath $(pkglibdir) $(scope_level_la_OBJECTS) $(scope_level_la_LIBADD) $(LIBS) ++ $(AM_V_CCLD)$(scope_level_la_LINK) -rpath $(DESTDIR)$(pkglibdir) $(scope_level_la_OBJECTS) $(scope_level_la_LIBADD) $(LIBS) + + mostlyclean-compile: + -rm -f *.$(OBJEXT) diff --git a/archive-patches/alsa-lib-1.1.5.patch b/archive-patches/alsa-lib-1.1.5.patch new file mode 100644 index 0000000..879ab27 --- /dev/null +++ b/archive-patches/alsa-lib-1.1.5.patch @@ -0,0 +1,13 @@ +--- a/utils/alsa.pc.in ++++ b/utils/alsa.pc.in +@@ -1,7 +1,7 @@ + prefix=@prefix@ +-exec_prefix=@exec_prefix@ +-libdir=@libdir@ +-includedir=@includedir@ ++exec_prefix=${prefix} ++libdir=${exec_prefix}/lib ++includedir=${prefix}/include + + Name: alsa + Description: Advanced Linux Sound Architecture (ALSA) - Library diff --git a/archive-patches/ffmpeg/ffmpeg-3.3-allow-to-choose-rtmp-impl-at-runtime.patch b/archive-patches/ffmpeg/ffmpeg-3.3-allow-to-choose-rtmp-impl-at-runtime.patch new file mode 100644 index 0000000..14225bc --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.3-allow-to-choose-rtmp-impl-at-runtime.patch @@ -0,0 +1,112 @@ +--- ffmpeg-3.2.2/configure ++++ ffmpeg-3.2.2/configure +@@ -3033,10 +3033,8 @@ + # protocols + async_protocol_deps="threads" + bluray_protocol_deps="libbluray" +-ffrtmpcrypt_protocol_deps="!librtmp_protocol" + ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl" + ffrtmpcrypt_protocol_select="tcp_protocol" +-ffrtmphttp_protocol_deps="!librtmp_protocol" + ffrtmphttp_protocol_select="http_protocol" + ftp_protocol_select="tcp_protocol" + gopher_protocol_select="network" +@@ -3053,14 +3051,12 @@ + libssh_protocol_deps="libssh" + mmsh_protocol_select="http_protocol" + mmst_protocol_select="network" +-rtmp_protocol_deps="!librtmp_protocol" +-rtmp_protocol_select="tcp_protocol" +-rtmpe_protocol_select="ffrtmpcrypt_protocol" +-rtmps_protocol_deps="!librtmp_protocol" +-rtmps_protocol_select="tls_protocol" +-rtmpt_protocol_select="ffrtmphttp_protocol" +-rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" +-rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" ++ffrtmp_protocol_select="tcp_protocol" ++ffrtmpe_protocol_select="ffrtmpcrypt_protocol" ++ffrtmps_protocol_select="tls_protocol" ++ffrtmpt_protocol_select="ffrtmphttp_protocol" ++ffrtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" ++ffrtmpts_protocol_select="ffrtmphttp_protocol https_protocol" + rtp_protocol_select="udp_protocol" + sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags" + sctp_protocol_select="network" +--- ffmpeg-3.2.2/libavformat/rtmpproto.c ++++ ffmpeg-3.2.2/libavformat/rtmpproto.c +@@ -2612,7 +2612,7 @@ + static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts) + { + RTMPContext *rt = s->priv_data; +- char proto[8], hostname[256], path[1024], auth[100], *fname; ++ char *proto, tmpProto[10], hostname[256], path[1024], auth[100], *fname; + char *old_app, *qmark, *n, fname_buffer[1024]; + uint8_t buf[2048]; + int port; +@@ -2623,7 +2623,7 @@ + + rt->is_input = !(flags & AVIO_FLAG_WRITE); + +- av_url_split(proto, sizeof(proto), auth, sizeof(auth), ++ memset(tmpProto, 0, sizeof(tmpProto)); proto = &tmpProto[2]; av_url_split(tmpProto, sizeof(tmpProto), auth, sizeof(auth), + hostname, sizeof(hostname), &port, + path, sizeof(path), s->filename); + +@@ -3157,9 +3157,9 @@ + }; + + +-RTMP_PROTOCOL(rtmp) +-RTMP_PROTOCOL(rtmpe) +-RTMP_PROTOCOL(rtmps) +-RTMP_PROTOCOL(rtmpt) +-RTMP_PROTOCOL(rtmpte) +-RTMP_PROTOCOL(rtmpts) ++RTMP_PROTOCOL(ffrtmp) ++RTMP_PROTOCOL(ffrtmpe) ++RTMP_PROTOCOL(ffrtmps) ++RTMP_PROTOCOL(ffrtmpt) ++RTMP_PROTOCOL(ffrtmpte) ++RTMP_PROTOCOL(ffrtmpts) +--- a/libavformat/Makefile ++++ b/libavformat/Makefile +@@ -566,12 +566,12 @@ + OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o + OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o + OBJS-$(CONFIG_PROMPEG_PROTOCOL) += prompeg.o +-OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMP_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPS_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPT_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPTE_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o + OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o + OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o + OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o +--- a/libavformat/protocols.c ++++ b/libavformat/protocols.c +@@ -44,12 +44,12 @@ + extern const URLProtocol ff_md5_protocol; + extern const URLProtocol ff_pipe_protocol; + extern const URLProtocol ff_prompeg_protocol; +-extern const URLProtocol ff_rtmp_protocol; +-extern const URLProtocol ff_rtmpe_protocol; +-extern const URLProtocol ff_rtmps_protocol; +-extern const URLProtocol ff_rtmpt_protocol; +-extern const URLProtocol ff_rtmpte_protocol; +-extern const URLProtocol ff_rtmpts_protocol; ++extern const URLProtocol ff_ffrtmp_protocol; ++extern const URLProtocol ff_ffrtmpe_protocol; ++extern const URLProtocol ff_ffrtmps_protocol; ++extern const URLProtocol ff_ffrtmpt_protocol; ++extern const URLProtocol ff_ffrtmpte_protocol; ++extern const URLProtocol ff_ffrtmpts_protocol; + extern const URLProtocol ff_rtp_protocol; + extern const URLProtocol ff_sctp_protocol; + extern const URLProtocol ff_srtp_protocol; diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch new file mode 100644 index 0000000..7bab442 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch @@ -0,0 +1,53 @@ +--- a/libavcodec/aacdec_template.c ++++ b/libavcodec/aacdec_template.c +@@ -2453,7 +2453,7 @@ + * @param decode 1 if tool is used normally, 0 if tool is used in LTP. + * @param coef spectral coefficients + */ +-static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns, ++static __attribute__((optimize(0))) void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns, + IndividualChannelStream *ics, int decode) + { + const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb); +--- a/libavcodec/mdct_template.c ++++ b/libavcodec/mdct_template.c +@@ -102,7 +102,7 @@ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale) + * @param output N/2 samples + * @param input N/2 samples + */ +-void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input) ++void __attribute__((optimize(0))) ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input) + { + int k, n8, n4, n2, n, j; + const uint16_t *revtab = s->revtab; +--- a/libavcodec/aacps.c ++++ b/libavcodec/aacps.c +@@ -659,7 +659,7 @@ + par[ 1] = AAC_HALF_SUM(par[ 0], par[ 1]); + } + +-static void decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34) ++static void __attribute__((optimize(0))) decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34) + { + LOCAL_ALIGNED_16(INTFLOAT, power, [34], [PS_QMF_TIME_SLOTS]); + LOCAL_ALIGNED_16(INTFLOAT, transient_gain, [34], [PS_QMF_TIME_SLOTS]); +--- a/libavcodec/fft_template.c ++++ b/libavcodec/fft_template.c +@@ -536,7 +536,7 @@ + pass(z,FFT_NAME(ff_cos_##n),n4/2);\ + } + +-static void fft4(FFTComplex *z) ++static void __attribute__((optimize(0))) fft4(FFTComplex *z) + { + FFTDouble t1, t2, t3, t4, t5, t6, t7, t8; + +@@ -550,7 +550,7 @@ + BF(z[2].im, z[0].im, t2, t5); + } + +-static void fft8(FFTComplex *z) ++static void __attribute__((optimize(0))) fft8(FFTComplex *z) + { + FFTDouble t1, t2, t3, t4, t5, t6; + diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch new file mode 100644 index 0000000..914f841 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch @@ -0,0 +1,118 @@ +diff -uNr ffmpeg-3.4.2/configure ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/configure +--- ffmpeg-3.4.2/configure 2018-02-12 01:29:18.000000000 +0100 ++++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/configure 2018-02-14 21:07:28.278640757 +0100 +@@ -3128,10 +3128,8 @@ + # protocols + async_protocol_deps="threads" + bluray_protocol_deps="libbluray" +-ffrtmpcrypt_protocol_conflict="librtmp_protocol" + ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl" + ffrtmpcrypt_protocol_select="tcp_protocol" +-ffrtmphttp_protocol_conflict="librtmp_protocol" + ffrtmphttp_protocol_select="http_protocol" + ftp_protocol_select="tcp_protocol" + gopher_protocol_select="network" +@@ -3148,14 +3146,12 @@ + libssh_protocol_deps="libssh" + mmsh_protocol_select="http_protocol" + mmst_protocol_select="network" +-rtmp_protocol_conflict="librtmp_protocol" +-rtmp_protocol_select="tcp_protocol" +-rtmpe_protocol_select="ffrtmpcrypt_protocol" +-rtmps_protocol_conflict="librtmp_protocol" +-rtmps_protocol_select="tls_protocol" +-rtmpt_protocol_select="ffrtmphttp_protocol" +-rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" +-rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" ++ffrtmp_protocol_select="tcp_protocol" ++ffrtmpe_protocol_select="ffrtmpcrypt_protocol" ++ffrtmps_protocol_select="tls_protocol" ++ffrtmpt_protocol_select="ffrtmphttp_protocol" ++ffrtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" ++ffrtmpts_protocol_select="ffrtmphttp_protocol https_protocol" + rtp_protocol_select="udp_protocol" + sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags" + sctp_protocol_select="network" +diff -uNr ffmpeg-3.4.2/libavformat/Makefile ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/Makefile +--- ffmpeg-3.4.2/libavformat/Makefile 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/Makefile 2018-02-14 20:10:19.763205912 +0100 +@@ -575,12 +575,12 @@ + OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o + OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o + OBJS-$(CONFIG_PROMPEG_PROTOCOL) += prompeg.o +-OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmppkt.o +-OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMP_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPE_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPS_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPT_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPTE_PROTOCOL) += rtmpproto.o rtmppkt.o ++OBJS-$(CONFIG_FFRTMPTS_PROTOCOL) += rtmpproto.o rtmppkt.o + OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o + OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o + OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o +diff -uNr ffmpeg-3.4.2/libavformat/protocols.c ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/protocols.c +--- ffmpeg-3.4.2/libavformat/protocols.c 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/protocols.c 2018-02-14 20:12:01.235570344 +0100 +@@ -44,12 +44,12 @@ + extern const URLProtocol ff_md5_protocol; + extern const URLProtocol ff_pipe_protocol; + extern const URLProtocol ff_prompeg_protocol; +-extern const URLProtocol ff_rtmp_protocol; +-extern const URLProtocol ff_rtmpe_protocol; +-extern const URLProtocol ff_rtmps_protocol; +-extern const URLProtocol ff_rtmpt_protocol; +-extern const URLProtocol ff_rtmpte_protocol; +-extern const URLProtocol ff_rtmpts_protocol; ++extern const URLProtocol ff_ffrtmp_protocol; ++extern const URLProtocol ff_ffrtmpe_protocol; ++extern const URLProtocol ff_ffrtmps_protocol; ++extern const URLProtocol ff_ffrtmpt_protocol; ++extern const URLProtocol ff_ffrtmpte_protocol; ++extern const URLProtocol ff_ffrtmpts_protocol; + extern const URLProtocol ff_rtp_protocol; + extern const URLProtocol ff_sctp_protocol; + extern const URLProtocol ff_srtp_protocol; +diff -uNr ffmpeg-3.4.2/libavformat/rtmpproto.c ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/rtmpproto.c +--- ffmpeg-3.4.2/libavformat/rtmpproto.c 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/rtmpproto.c 2018-02-14 20:21:41.701280041 +0100 +@@ -2626,7 +2626,7 @@ + static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts) + { + RTMPContext *rt = s->priv_data; +- char proto[8], hostname[256], path[1024], auth[100], *fname; ++ char *proto, tmpProto[10], hostname[256], path[1024], auth[100], *fname; + char *old_app, *qmark, *n, fname_buffer[1024]; + uint8_t buf[2048]; + int port; +@@ -2637,7 +2637,9 @@ + + rt->is_input = !(flags & AVIO_FLAG_WRITE); + +- av_url_split(proto, sizeof(proto), auth, sizeof(auth), ++ memset(tmpProto, 0, sizeof(tmpProto)); ++ proto = &tmpProto[2]; ++ av_url_split(tmpProto, sizeof(tmpProto), auth, sizeof(auth), + hostname, sizeof(hostname), &port, + path, sizeof(path), s->filename); + +@@ -3171,9 +3173,9 @@ + }; + + +-RTMP_PROTOCOL(rtmp) +-RTMP_PROTOCOL(rtmpe) +-RTMP_PROTOCOL(rtmps) +-RTMP_PROTOCOL(rtmpt) +-RTMP_PROTOCOL(rtmpte) +-RTMP_PROTOCOL(rtmpts) ++RTMP_PROTOCOL(ffrtmp) ++RTMP_PROTOCOL(ffrtmpe) ++RTMP_PROTOCOL(ffrtmps) ++RTMP_PROTOCOL(ffrtmpt) ++RTMP_PROTOCOL(ffrtmpte) ++RTMP_PROTOCOL(ffrtmpts) diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch new file mode 100644 index 0000000..bf465aa --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch @@ -0,0 +1,91 @@ +--- a/libavformat/avio.h ++++ b/libavformat/avio.h +@@ -291,12 +291,6 @@ + */ + int writeout_count; + +- /** +- * Original buffer size +- * used internally after probing and ensure seekback to reset the buffer size +- * This field is internal to libavformat and access from outside is not allowed. +- */ +- int orig_buffer_size; + + /** + * Threshold to favor readahead over seek. +--- a/libavformat/aviobuf.c ++++ b/libavformat/aviobuf.c +@@ -33,7 +33,7 @@ + #include "url.h" + #include + +-#define IO_BUFFER_SIZE 32768 ++#define IO_BUFFER_SIZE 262144 + + /** + * Do seeks within this distance ahead of the current buffer by skipping +@@ -88,7 +88,6 @@ + int64_t (*seek)(void *opaque, int64_t offset, int whence)) + { + s->buffer = buffer; +- s->orig_buffer_size = + s->buffer_size = buffer_size; + s->buf_ptr = buffer; + s->buf_ptr_max = buffer; +@@ -557,16 +556,16 @@ + } + + /* make buffer smaller in case it ended up large after probing */ +- if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) { ++ if (s->read_packet && s->buffer_size > max_buffer_size) { + if (dst == s->buffer && s->buf_ptr != dst) { +- int ret = ffio_set_buf_size(s, s->orig_buffer_size); ++ int ret = ffio_set_buf_size(s, max_buffer_size); + if (ret < 0) + av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n"); + + s->checksum_ptr = dst = s->buffer; + } +- av_assert0(len >= s->orig_buffer_size); +- len = s->orig_buffer_size; ++ av_assert0(len >= max_buffer_size); ++ len = max_buffer_size; + } + + if (s->read_packet) +@@ -1009,7 +1008,6 @@ + + av_free(s->buffer); + s->buffer = buffer; +- s->orig_buffer_size = + s->buffer_size = buf_size; + s->buf_ptr = s->buf_ptr_max = buffer; + url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); +--- a/libavformat/utils.c ++++ b/libavformat/utils.c +@@ -118,6 +118,25 @@ + MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb) + FF_ENABLE_DEPRECATION_WARNINGS + #endif ++ ++void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) ++{ ++ if (min_size < *size) ++ return ptr; ++ ++ min_size = FFMAX(17 * min_size / 16 + 32, min_size); ++ ++ ptr = av_realloc(ptr, min_size); ++ /* we could set this to the unmodified min_size but this is safer ++ * if the user lost the ptr and uses NULL now ++ */ ++ if (!ptr) ++ min_size = 0; ++ ++ *size = min_size; ++ ++ return ptr; ++} + + int64_t av_stream_get_end_pts(const AVStream *st) + { diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch new file mode 100644 index 0000000..99ac875 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch @@ -0,0 +1,16 @@ +diff -uNr ffmpeg-3.4.2/libavformat/http.c ffmpeg-3.4.2_chunked_transfer_fix_eof/libavformat/http.c +--- ffmpeg-3.4.2/libavformat/http.c 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_chunked_transfer_fix_eof/libavformat/http.c 2018-02-14 19:56:02.371892777 +0100 +@@ -1296,8 +1296,11 @@ + "Chunked encoding data size: %"PRIu64"'\n", + s->chunksize); + +- if (!s->chunksize) ++ if (!s->chunksize) { ++ /* we need to remember endof*/ ++ s->chunksize = UINT64_MAX; + return 0; ++ } + else if (s->chunksize == UINT64_MAX) { + av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n", + s->chunksize); diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch new file mode 100644 index 0000000..42dbf1a --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch @@ -0,0 +1,1565 @@ +diff -uNr ffmpeg-3.4.2/libavformat/dashdec.c ffmpeg-3.4.2_dashdec/libavformat/dashdec.c +--- ffmpeg-3.4.2/libavformat/dashdec.c 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_dashdec/libavformat/dashdec.c 2018-02-15 19:43:08.889757019 +0100 +@@ -39,7 +39,7 @@ + /* + * reference to : ISO_IEC_23009-1-DASH-2012 + * Section: 5.3.9.6.2 +- * Table: Table 17 — Semantics of SegmentTimeline element ++ * Table: Table 17 — Semantics of SegmentTimeline element + * */ + struct timeline { + /* starttime: Element or Attribute Name +@@ -80,10 +80,13 @@ + AVFormatContext *ctx; + AVPacket pkt; + int rep_idx; +- int rep_count; + int stream_index; + + enum AVMediaType type; ++ char id[20]; ++ int bandwidth; ++ AVRational framerate; ++ AVStream *assoc_stream; /* demuxer stream associated with this representation */ + + int n_fragments; + struct fragment **fragments; /* VOD list of fragment for profile */ +@@ -113,13 +116,32 @@ + uint32_t init_sec_buf_read_offset; + int64_t cur_timestamp; + int is_restart_needed; ++ ++ /* used for live stream were each fragment starts with ++ * 0 pts, so we need to ++ */ ++ int64_t pkt_start_time_offset; ++ int is_first_pkt; + }; + + typedef struct DASHContext { + const AVClass *class; + char *base_url; +- struct representation *cur_video; +- struct representation *cur_audio; ++ ++ int n_videos; ++ struct representation **videos; ++ int n_audios; ++ struct representation **audios; ++ ++ /* Temporary variables used during manifest parsing */ ++ int tmp_video_rep_idx; ++ int tmp_audio_rep_idx; ++ ++ /* Used to force using selected representation */ ++ int video_rep_index; ++ int audio_rep_index; ++ ++ int64_t last_load_time; + + /* MediaPresentationDescription Attribute */ + uint64_t media_presentation_duration; +@@ -141,8 +163,34 @@ + char *headers; ///< holds HTTP headers set as an AVOption to the HTTP protocol context + char *allowed_extensions; + AVDictionary *avio_opts; ++ int max_url_size; + } DASHContext; + ++static int sleep_ms(DASHContext *c, uint32_t time_ms) ++{ ++ int ret = 0; ++ int64_t start_time = av_gettime_relative(); ++ do { ++ if (ff_check_interrupt(c->interrupt_callback)) { ++ ret = 1; ++ break; ++ } ++ av_usleep(100*1000); ++ } while (av_gettime_relative() - start_time < (time_ms*1000)); ++ return ret; ++} ++ ++static int ishttp(char *url) ++{ ++ const char *proto_name = avio_find_protocol_name(url); ++ return av_strstart(proto_name, "http", NULL); ++} ++ ++static int aligned(int val) ++{ ++ return ((val + 0x3F) >> 6) << 6; ++} ++ + static uint64_t get_current_time_in_sec(void) + { + return av_gettime() / 1000000; +@@ -328,17 +376,39 @@ + } + + av_freep(&pls->url_template); +- av_freep(pls); ++ av_freep(&pls); ++} ++ ++static void free_video_list(DASHContext *c) ++{ ++ int i; ++ for (i = 0; i < c->n_videos; i++) { ++ struct representation *pls = c->videos[i]; ++ free_representation(pls); ++ } ++ av_freep(&c->videos); ++ c->n_videos = 0; + } + +-static void set_httpheader_options(DASHContext *c, AVDictionary *opts) ++static void free_audio_list(DASHContext *c) ++{ ++ int i; ++ for (i = 0; i < c->n_audios; i++) { ++ struct representation *pls = c->audios[i]; ++ free_representation(pls); ++ } ++ av_freep(&c->audios); ++ c->n_audios = 0; ++} ++ ++static void set_httpheader_options(DASHContext *c, AVDictionary **opts) + { + // broker prior HTTP options that should be consistent across requests +- av_dict_set(&opts, "user-agent", c->user_agent, 0); +- av_dict_set(&opts, "cookies", c->cookies, 0); +- av_dict_set(&opts, "headers", c->headers, 0); ++ av_dict_set(opts, "user-agent", c->user_agent, 0); ++ av_dict_set(opts, "cookies", c->cookies, 0); ++ av_dict_set(opts, "headers", c->headers, 0); + if (c->is_live) { +- av_dict_set(&opts, "seekable", "0", 0); ++ av_dict_set(opts, "seekable", "0", 0); + } + } + static void update_options(char **dest, const char *name, void *src) +@@ -392,7 +462,8 @@ + else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) + return AVERROR_INVALIDDATA; + +- ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); ++ av_freep(pb); ++ ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); + if (ret >= 0) { + // update cookies on http response with setcookies. + char *new_cookies = NULL; +@@ -418,6 +489,7 @@ + + static char *get_content_url(xmlNodePtr *baseurl_nodes, + int n_baseurl_nodes, ++ int max_url_size, + char *rep_id_val, + char *rep_bandwidth_val, + char *val) +@@ -425,10 +497,12 @@ + int i; + char *text; + char *url = NULL; +- char tmp_str[MAX_URL_SIZE]; +- char tmp_str_2[MAX_URL_SIZE]; ++ char *tmp_str = av_mallocz(max_url_size); ++ char *tmp_str_2 = av_mallocz(max_url_size); + +- memset(tmp_str, 0, sizeof(tmp_str)); ++ if (!tmp_str || !tmp_str_2) { ++ return NULL; ++ } + + for (i = 0; i < n_baseurl_nodes; ++i) { + if (baseurl_nodes[i] && +@@ -436,32 +510,36 @@ + baseurl_nodes[i]->children->type == XML_TEXT_NODE) { + text = xmlNodeGetContent(baseurl_nodes[i]->children); + if (text) { +- memset(tmp_str, 0, sizeof(tmp_str)); +- memset(tmp_str_2, 0, sizeof(tmp_str_2)); +- ff_make_absolute_url(tmp_str_2, MAX_URL_SIZE, tmp_str, text); +- av_strlcpy(tmp_str, tmp_str_2, sizeof(tmp_str)); ++ memset(tmp_str, 0, max_url_size); ++ memset(tmp_str_2, 0, max_url_size); ++ ff_make_absolute_url(tmp_str_2, max_url_size, tmp_str, text); ++ av_strlcpy(tmp_str, tmp_str_2, max_url_size); + xmlFree(text); + } + } + } + + if (val) +- av_strlcat(tmp_str, (const char*)val, sizeof(tmp_str)); ++ av_strlcat(tmp_str, (const char*)val, max_url_size); + + if (rep_id_val) { + url = av_strireplace(tmp_str, "$RepresentationID$", (const char*)rep_id_val); + if (!url) { +- return NULL; ++ goto end; + } +- av_strlcpy(tmp_str, url, sizeof(tmp_str)); +- av_free(url); ++ av_strlcpy(tmp_str, url, max_url_size); + } + if (rep_bandwidth_val && tmp_str[0] != '\0') { ++ // free any previously assigned url before reassigning ++ av_free(url); + url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val); + if (!url) { +- return NULL; ++ goto end; + } + } ++end: ++ av_free(tmp_str); ++ av_free(tmp_str_2); + return url; + } + +@@ -522,55 +600,85 @@ + return type; + } + ++static struct fragment * get_Fragment(char *range) ++{ ++ struct fragment * seg = av_mallocz(sizeof(struct fragment)); ++ ++ if (!seg) ++ return NULL; ++ ++ seg->size = -1; ++ if (range) { ++ char *str_end_offset; ++ char *str_offset = av_strtok(range, "-", &str_end_offset); ++ seg->url_offset = strtoll(str_offset, NULL, 10); ++ seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset; ++ } ++ ++ return seg; ++} ++ + static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representation *rep, + xmlNodePtr fragmenturl_node, + xmlNodePtr *baseurl_nodes, + char *rep_id_val, + char *rep_bandwidth_val) + { ++ DASHContext *c = s->priv_data; + char *initialization_val = NULL; + char *media_val = NULL; ++ char *range_val = NULL; ++ int max_url_size = c ? c->max_url_size: MAX_URL_SIZE; + + if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) { + initialization_val = xmlGetProp(fragmenturl_node, "sourceURL"); +- if (initialization_val) { +- rep->init_section = av_mallocz(sizeof(struct fragment)); ++ range_val = xmlGetProp(fragmenturl_node, "range"); ++ if (initialization_val || range_val) { ++ rep->init_section = get_Fragment(range_val); + if (!rep->init_section) { + xmlFree(initialization_val); ++ xmlFree(range_val); + return AVERROR(ENOMEM); + } + rep->init_section->url = get_content_url(baseurl_nodes, 4, ++ max_url_size, + rep_id_val, + rep_bandwidth_val, + initialization_val); ++ + if (!rep->init_section->url) { + av_free(rep->init_section); + xmlFree(initialization_val); ++ xmlFree(range_val); + return AVERROR(ENOMEM); + } +- rep->init_section->size = -1; + xmlFree(initialization_val); ++ xmlFree(range_val); + } + } else if (!av_strcasecmp(fragmenturl_node->name, (const char *)"SegmentURL")) { + media_val = xmlGetProp(fragmenturl_node, "media"); +- if (media_val) { +- struct fragment *seg = av_mallocz(sizeof(struct fragment)); ++ range_val = xmlGetProp(fragmenturl_node, "mediaRange"); ++ if (media_val || range_val) { ++ struct fragment *seg = get_Fragment(range_val); + if (!seg) { + xmlFree(media_val); ++ xmlFree(range_val); + return AVERROR(ENOMEM); + } + seg->url = get_content_url(baseurl_nodes, 4, ++ max_url_size, + rep_id_val, + rep_bandwidth_val, + media_val); + if (!seg->url) { + av_free(seg); + xmlFree(media_val); ++ xmlFree(range_val); + return AVERROR(ENOMEM); + } +- seg->size = -1; + dynarray_add(&rep->fragments, &rep->n_fragments, seg); + xmlFree(media_val); ++ xmlFree(range_val); + } + } + +@@ -613,26 +721,155 @@ + return 0; + } + ++static int fill_timelines(AVFormatContext *s, struct representation *rep, xmlNodePtr *nodes, const int n_nodes) ++{ ++ xmlNodePtr fragment_timeline_node; ++ int ret = 0; ++ int i = 0; ++ for (; i < n_nodes; ++i) { ++ if (nodes[i]) { ++ ++ fragment_timeline_node = find_child_node_by_name(nodes[i], "SegmentTimeline"); ++ if (fragment_timeline_node) { ++ fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); ++ while (fragment_timeline_node) { ++ ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); ++ if (ret < 0) { ++ return ret; ++ } ++ fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); ++ } ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++static int resolve_content_path(AVFormatContext *s, const char *url, int *max_url_size, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { ++ ++ char *tmp_str = NULL; ++ char *path = NULL; ++ char *mpdName = NULL; ++ xmlNodePtr node = NULL; ++ char *baseurl = NULL; ++ char *root_url = NULL; ++ char *text = NULL; ++ ++ int isRootHttp = 0; ++ char token ='/'; ++ int start = 0; ++ int rootId = 0; ++ int updated = 0; ++ int size = 0; ++ int i; ++ int tmp_max_url_size = strlen(url); ++ ++ for (i = n_baseurl_nodes-1; i >= 0 ; i--) { ++ text = xmlNodeGetContent(baseurl_nodes[i]); ++ if (!text) ++ continue; ++ tmp_max_url_size += strlen(text); ++ if (ishttp(text)) { ++ xmlFree(text); ++ break; ++ } ++ xmlFree(text); ++ } ++ ++ tmp_max_url_size = aligned(tmp_max_url_size); ++ text = av_mallocz(tmp_max_url_size); ++ if (!text) { ++ updated = AVERROR(ENOMEM); ++ goto end; ++ } ++ av_strlcpy(text, url, strlen(url)+1); ++ while (mpdName = av_strtok(text, "/", &text)) { ++ size = strlen(mpdName); ++ } ++ ++ path = av_mallocz(tmp_max_url_size); ++ tmp_str = av_mallocz(tmp_max_url_size); ++ if (!tmp_str || !path) { ++ updated = AVERROR(ENOMEM); ++ goto end; ++ } ++ ++ av_strlcpy (path, url, strlen(url) - size + 1); ++ for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { ++ if (!(node = baseurl_nodes[rootId])) { ++ continue; ++ } ++ if (ishttp(xmlNodeGetContent(node))) { ++ break; ++ } ++ } ++ ++ node = baseurl_nodes[rootId]; ++ baseurl = xmlNodeGetContent(node); ++ root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; ++ if (node) { ++ xmlNodeSetContent(node, root_url); ++ updated = 1; ++ } ++ ++ size = strlen(root_url); ++ isRootHttp = ishttp(root_url); ++ ++ if (root_url[size - 1] != token) { ++ av_strlcat(root_url, "/", size + 2); ++ size += 2; ++ } ++ ++ for (i = 0; i < n_baseurl_nodes; ++i) { ++ if (i == rootId) { ++ continue; ++ } ++ text = xmlNodeGetContent(baseurl_nodes[i]); ++ if (text) { ++ memset(tmp_str, 0, strlen(tmp_str)); ++ if (!ishttp(text) && isRootHttp) { ++ av_strlcpy(tmp_str, root_url, size + 1); ++ } ++ start = (text[0] == token); ++ av_strlcat(tmp_str, text + start, tmp_max_url_size); ++ xmlNodeSetContent(baseurl_nodes[i], tmp_str); ++ updated = 1; ++ xmlFree(text); ++ } ++ } ++ ++end: ++ if (tmp_max_url_size > *max_url_size) { ++ *max_url_size = tmp_max_url_size; ++ } ++ av_free(path); ++ av_free(tmp_str); ++ return updated; ++ ++} ++ + static int parse_manifest_representation(AVFormatContext *s, const char *url, + xmlNodePtr node, + xmlNodePtr adaptionset_node, + xmlNodePtr mpd_baseurl_node, + xmlNodePtr period_baseurl_node, ++ xmlNodePtr period_segmenttemplate_node, ++ xmlNodePtr period_segmentlist_node, + xmlNodePtr fragment_template_node, + xmlNodePtr content_component_node, +- xmlNodePtr adaptionset_baseurl_node) ++ xmlNodePtr adaptionset_baseurl_node, ++ xmlNodePtr adaptionset_segmentlist_node) + { + int32_t ret = 0; +- int32_t audio_rep_idx = 0; +- int32_t video_rep_idx = 0; + DASHContext *c = s->priv_data; + struct representation *rep = NULL; + struct fragment *seg = NULL; + xmlNodePtr representation_segmenttemplate_node = NULL; + xmlNodePtr representation_baseurl_node = NULL; + xmlNodePtr representation_segmentlist_node = NULL; +- xmlNodePtr fragment_timeline_node = NULL; +- xmlNodePtr fragment_templates_tab[2]; ++ xmlNodePtr segmentlists_tab[3]; ++ xmlNodePtr fragment_templates_tab[5]; + char *duration_val = NULL; + char *presentation_timeoffset_val = NULL; + char *startnumber_val = NULL; +@@ -643,6 +880,7 @@ + xmlNodePtr representation_node = node; + char *rep_id_val = xmlGetProp(representation_node, "id"); + char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); ++ char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); + enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN; + + // try get information from representation +@@ -656,7 +894,7 @@ + type = get_content_type(adaptionset_node); + if (type == AVMEDIA_TYPE_UNKNOWN) { + av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url); +- } else if ((type == AVMEDIA_TYPE_VIDEO && !c->cur_video) || (type == AVMEDIA_TYPE_AUDIO && !c->cur_audio)) { ++ } else if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { + // convert selected representation to our internal struct + rep = av_mallocz(sizeof(struct representation)); + if (!rep) { +@@ -672,17 +910,24 @@ + baseurl_nodes[2] = adaptionset_baseurl_node; + baseurl_nodes[3] = representation_baseurl_node; + +- if (representation_segmenttemplate_node || fragment_template_node) { +- fragment_timeline_node = NULL; ++ ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); ++ c->max_url_size = aligned(c->max_url_size + strlen(rep_id_val) + strlen(rep_bandwidth_val)); ++ if (ret == AVERROR(ENOMEM) || ret == 0) { ++ goto end; ++ } ++ if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { + fragment_templates_tab[0] = representation_segmenttemplate_node; +- fragment_templates_tab[1] = fragment_template_node; +- +- presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "presentationTimeOffset"); +- duration_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "duration"); +- startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "startNumber"); +- timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "timescale"); +- initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "initialization"); +- media_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "media"); ++ fragment_templates_tab[1] = adaptionset_segmentlist_node; ++ fragment_templates_tab[2] = fragment_template_node; ++ fragment_templates_tab[3] = period_segmenttemplate_node; ++ fragment_templates_tab[4] = period_segmentlist_node; ++ ++ presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); ++ duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); ++ startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); ++ timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); ++ initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); ++ media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); + + if (initialization_val) { + rep->init_section = av_mallocz(sizeof(struct fragment)); +@@ -691,7 +936,8 @@ + ret = AVERROR(ENOMEM); + goto end; + } +- rep->init_section->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, initialization_val); ++ c->max_url_size = aligned(c->max_url_size + strlen(initialization_val)); ++ rep->init_section->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val); + if (!rep->init_section->url) { + av_free(rep->init_section); + av_free(rep); +@@ -703,7 +949,8 @@ + } + + if (media_val) { +- rep->url_template = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, media_val); ++ c->max_url_size = aligned(c->max_url_size + strlen(media_val)); ++ rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val); + xmlFree(media_val); + } + +@@ -719,32 +966,27 @@ + rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); + xmlFree(timescale_val); + } ++ ++ ret = fill_timelines(s, rep, fragment_templates_tab, 5); ++ if (ret < 0) { ++ return ret; ++ } ++ + if (startnumber_val) { +- rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); ++ if (rep->n_timelines) ++ rep->start_number = (int64_t) strtoll(startnumber_val, NULL, 10); ++ else ++ rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); + xmlFree(startnumber_val); + } + +- fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); +- +- if (!fragment_timeline_node) +- fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); +- if (fragment_timeline_node) { +- fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); +- while (fragment_timeline_node) { +- ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); +- if (ret < 0) { +- return ret; +- } +- fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); +- } +- } + } else if (representation_baseurl_node && !representation_segmentlist_node) { + seg = av_mallocz(sizeof(struct fragment)); + if (!seg) { + ret = AVERROR(ENOMEM); + goto end; + } +- seg->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, NULL); ++ seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL); + if (!seg->url) { + av_free(seg); + ret = AVERROR(ENOMEM); +@@ -756,8 +998,14 @@ + // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html + // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full + xmlNodePtr fragmenturl_node = NULL; +- duration_val = xmlGetProp(representation_segmentlist_node, "duration"); +- timescale_val = xmlGetProp(representation_segmentlist_node, "timescale"); ++ segmentlists_tab[0] = representation_segmentlist_node; ++ segmentlists_tab[1] = adaptionset_segmentlist_node; ++ segmentlists_tab[2] = period_segmentlist_node; ++ ++ duration_val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration"); ++ timescale_val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale"); ++ startnumber_val = get_val_from_nodes_tab(segmentlists_tab, 3, "startNumber"); ++ + if (duration_val) { + rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); + xmlFree(duration_val); +@@ -766,6 +1014,10 @@ + rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); + xmlFree(timescale_val); + } ++ if (startnumber_val) { ++ rep->start_number = (int64_t) strtoll(startnumber_val, NULL, 10); ++ xmlFree(startnumber_val); ++ } + fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node); + while (fragmenturl_node) { + ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node, +@@ -778,19 +1030,9 @@ + fragmenturl_node = xmlNextElementSibling(fragmenturl_node); + } + +- fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); +- +- if (!fragment_timeline_node) +- fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); +- if (fragment_timeline_node) { +- fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); +- while (fragment_timeline_node) { +- ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); +- if (ret < 0) { +- return ret; +- } +- fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); +- } ++ ret = fill_timelines(s, rep, segmentlists_tab, 3); ++ if (ret < 0) { ++ return ret; + } + } else { + free_representation(rep); +@@ -801,24 +1043,37 @@ + if (rep) { + if (rep->fragment_duration > 0 && !rep->fragment_timescale) + rep->fragment_timescale = 1; +- if (type == AVMEDIA_TYPE_VIDEO) { +- rep->rep_idx = video_rep_idx; +- c->cur_video = rep; ++ rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; ++ strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); ++ rep->framerate = av_make_q(0, 0); ++ if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) { ++ ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); ++ if (ret < 0) ++ av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); ++ } ++ if (type == AVMEDIA_TYPE_VIDEO && (c->video_rep_index == -1 || c->video_rep_index == c->tmp_video_rep_idx)) { ++ rep->rep_idx = c->tmp_video_rep_idx; ++ dynarray_add(&c->videos, &c->n_videos, rep); ++ } else if (type == AVMEDIA_TYPE_AUDIO && (c->audio_rep_index == -1 || c->audio_rep_index == c->tmp_audio_rep_idx)) { ++ rep->rep_idx = c->tmp_audio_rep_idx; ++ dynarray_add(&c->audios, &c->n_audios, rep); + } else { +- rep->rep_idx = audio_rep_idx; +- c->cur_audio = rep; ++ free_representation(rep); ++ rep = NULL; + } + } + } +- +- video_rep_idx += type == AVMEDIA_TYPE_VIDEO; +- audio_rep_idx += type == AVMEDIA_TYPE_AUDIO; ++ ++ c->tmp_video_rep_idx += type == AVMEDIA_TYPE_VIDEO; ++ c->tmp_audio_rep_idx += type == AVMEDIA_TYPE_AUDIO; + + end: + if (rep_id_val) + xmlFree(rep_id_val); + if (rep_bandwidth_val) + xmlFree(rep_bandwidth_val); ++ if (rep_framerate_val) ++ xmlFree(rep_framerate_val); + + return ret; + } +@@ -826,12 +1081,15 @@ + static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, + xmlNodePtr adaptionset_node, + xmlNodePtr mpd_baseurl_node, +- xmlNodePtr period_baseurl_node) ++ xmlNodePtr period_baseurl_node, ++ xmlNodePtr period_segmenttemplate_node, ++ xmlNodePtr period_segmentlist_node) + { + int ret = 0; + xmlNodePtr fragment_template_node = NULL; + xmlNodePtr content_component_node = NULL; + xmlNodePtr adaptionset_baseurl_node = NULL; ++ xmlNodePtr adaptionset_segmentlist_node = NULL; + xmlNodePtr node = NULL; + + node = xmlFirstElementChild(adaptionset_node); +@@ -842,14 +1100,19 @@ + content_component_node = node; + } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) { + adaptionset_baseurl_node = node; ++ } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) { ++ adaptionset_segmentlist_node = node; + } else if (!av_strcasecmp(node->name, (const char *)"Representation")) { + ret = parse_manifest_representation(s, url, node, + adaptionset_node, + mpd_baseurl_node, + period_baseurl_node, ++ period_segmenttemplate_node, ++ period_segmentlist_node, + fragment_template_node, + content_component_node, +- adaptionset_baseurl_node); ++ adaptionset_baseurl_node, ++ adaptionset_segmentlist_node); + if (ret < 0) { + return ret; + } +@@ -874,18 +1137,21 @@ + xmlNodePtr period_node = NULL; + xmlNodePtr mpd_baseurl_node = NULL; + xmlNodePtr period_baseurl_node = NULL; ++ xmlNodePtr period_segmenttemplate_node = NULL; ++ xmlNodePtr period_segmentlist_node = NULL; + xmlNodePtr adaptionset_node = NULL; + xmlAttrPtr attr = NULL; + char *val = NULL; + uint32_t perdiod_duration_sec = 0; + uint32_t perdiod_start_sec = 0; +- int32_t audio_rep_idx = 0; +- int32_t video_rep_idx = 0; ++ ++ c->tmp_audio_rep_idx = 0; ++ c->tmp_video_rep_idx = 0; + + if (!in) { + close_in = 1; + +- set_httpheader_options(c, opts); ++ set_httpheader_options(c, &opts); + ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts); + av_dict_free(&opts); + if (ret < 0) +@@ -967,6 +1233,9 @@ + } + + mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); ++ if (!mpd_baseurl_node) { ++ mpd_baseurl_node = xmlNewNode(NULL, "BaseURL"); ++ } + + // at now we can handle only one period, with the longest duration + node = xmlFirstElementChild(node); +@@ -989,7 +1258,7 @@ + period_node = node; + c->period_duration = perdiod_duration_sec; + c->period_start = perdiod_start_sec; +- if (c->period_start > 0) ++ if (c->period_duration > 0) + c->media_presentation_duration = c->period_duration; + } + } +@@ -1005,19 +1274,15 @@ + while (adaptionset_node) { + if (!av_strcasecmp(adaptionset_node->name, (const char *)"BaseURL")) { + period_baseurl_node = adaptionset_node; ++ } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) { ++ period_segmenttemplate_node = adaptionset_node; ++ } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentList")) { ++ period_segmentlist_node = adaptionset_node; + } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) { +- parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node); ++ parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node); + } + adaptionset_node = xmlNextElementSibling(adaptionset_node); + } +- if (c->cur_video) { +- c->cur_video->rep_count = video_rep_idx; +- av_log(s, AV_LOG_VERBOSE, "rep_idx[%d]\n", (int)c->cur_video->rep_idx); +- av_log(s, AV_LOG_VERBOSE, "rep_count[%d]\n", (int)video_rep_idx); +- } +- if (c->cur_audio) { +- c->cur_audio->rep_count = audio_rep_idx; +- } + cleanup: + /*free the document */ + xmlFreeDoc(doc); +@@ -1029,6 +1294,7 @@ + if (close_in) { + avio_close(in); + } ++ c->last_load_time = av_gettime_relative(); + return ret; + } + +@@ -1042,15 +1308,17 @@ + if (pls->n_fragments) { + num = pls->first_seq_no; + } else if (pls->n_timelines) { ++ + start_time_offset = get_segment_start_time_based_on_timeline(pls, 0xFFFFFFFF) - pls->timelines[pls->first_seq_no]->starttime; // total duration of playlist +- if (start_time_offset < 60 * pls->fragment_timescale) ++ if (start_time_offset < 60*pls->fragment_timescale) + start_time_offset = 0; + else + start_time_offset = start_time_offset - 60 * pls->fragment_timescale; +- ++ + num = calc_next_seg_no_from_timelines(pls, pls->timelines[pls->first_seq_no]->starttime + start_time_offset); + if (num == -1) + num = pls->first_seq_no; ++ + } else if (pls->fragment_duration){ + if (pls->presentation_timeoffset) { + num = pls->presentation_timeoffset * pls->fragment_timescale / pls->fragment_duration; +@@ -1079,9 +1347,8 @@ + return num; + } + +-static int64_t calc_max_seg_no(struct representation *pls) ++static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c) + { +- DASHContext *c = pls->parent->priv_data; + int64_t num = 0; + + if (pls->n_fragments) { +@@ -1101,83 +1368,119 @@ + return num; + } + +-static void move_timelines(struct representation *rep_src, struct representation *rep_dest) ++static void move_timelines(struct representation *rep_src, struct representation *rep_dest, DASHContext *c) + { + if (rep_dest && rep_src ) { + free_timelines_list(rep_dest); + rep_dest->timelines = rep_src->timelines; + rep_dest->n_timelines = rep_src->n_timelines; + rep_dest->first_seq_no = rep_src->first_seq_no; +- rep_dest->last_seq_no = calc_max_seg_no(rep_dest); ++ rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c); ++ rep_dest->start_number = rep_src->start_number; + rep_src->timelines = NULL; + rep_src->n_timelines = 0; + rep_dest->cur_seq_no = rep_src->cur_seq_no; + } + } + +-static void move_segments(struct representation *rep_src, struct representation *rep_dest) ++static void move_segments(struct representation *rep_src, struct representation *rep_dest, DASHContext *c) + { +- if (rep_dest && rep_src ) { ++ if (rep_dest && rep_src) { + free_fragment_list(rep_dest); +- if (rep_src->start_number > (rep_dest->start_number + rep_dest->n_fragments)) ++ if (rep_src->start_number > (rep_dest->start_number + rep_dest->cur_seq_no)) + rep_dest->cur_seq_no = 0; + else +- rep_dest->cur_seq_no += rep_src->start_number - rep_dest->start_number; ++ rep_dest->cur_seq_no = rep_src->n_fragments - ((rep_src->start_number + rep_src->n_fragments) - (rep_dest->start_number + rep_dest->cur_seq_no)); + rep_dest->fragments = rep_src->fragments; + rep_dest->n_fragments = rep_src->n_fragments; + rep_dest->parent = rep_src->parent; +- rep_dest->last_seq_no = calc_max_seg_no(rep_dest); ++ rep_dest->start_number = rep_src->start_number; ++ rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c); + rep_src->fragments = NULL; + rep_src->n_fragments = 0; + } + } + ++static int64_t default_reload_interval_us(AVFormatContext *s) ++{ ++ return 2000 * 1000; ++} + + static int refresh_manifest(AVFormatContext *s) + { + +- int ret = 0; ++ int ret = 0, i; + DASHContext *c = s->priv_data; + + // save current context +- struct representation *cur_video = c->cur_video; +- struct representation *cur_audio = c->cur_audio; ++ int n_videos = c->n_videos; ++ struct representation **videos = c->videos; ++ int n_audios = c->n_audios; ++ struct representation **audios = c->audios; + char *base_url = c->base_url; ++ int64_t reload_interval_us = 0; + + c->base_url = NULL; +- c->cur_video = NULL; +- c->cur_audio = NULL; ++ c->n_videos = 0; ++ c->videos = NULL; ++ c->n_audios = 0; ++ c->audios = NULL; ++ ++ reload_interval_us = default_reload_interval_us(s); ++ while (av_gettime_relative() - c->last_load_time < reload_interval_us) { ++ if (ff_check_interrupt(c->interrupt_callback)) ++ return AVERROR_EXIT; ++ av_usleep(100*1000); ++ } ++ + ret = parse_manifest(s, s->filename, NULL); + if (ret) + goto finish; + +- if (cur_video && cur_video->timelines || cur_audio && cur_audio->timelines) { +- // calc current time +- int64_t currentVideoTime = 0; +- int64_t currentAudioTime = 0; +- if (cur_video && cur_video->timelines) +- currentVideoTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale; +- if (cur_audio && cur_audio->timelines) +- currentAudioTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale; +- // update segments +- if (cur_video && cur_video->timelines) { +- c->cur_video->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_video, currentVideoTime * cur_video->fragment_timescale - 1); +- if (c->cur_video->cur_seq_no >= 0) { +- move_timelines(c->cur_video, cur_video); +- } +- } +- if (cur_audio && cur_audio->timelines) { +- c->cur_audio->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_audio, currentAudioTime * cur_audio->fragment_timescale - 1); +- if (c->cur_audio->cur_seq_no >= 0) { +- move_timelines(c->cur_audio, cur_audio); +- } +- } ++ if (c->n_videos != n_videos) { ++ av_log(c, AV_LOG_ERROR, ++ "new manifest has mismatched no. of video representations, %d -> %d\n", ++ n_videos, c->n_videos); ++ return AVERROR_INVALIDDATA; + } +- if (cur_video && cur_video->fragments) { +- move_segments(c->cur_video, cur_video); ++ if (c->n_audios != n_audios) { ++ av_log(c, AV_LOG_ERROR, ++ "new manifest has mismatched no. of audio representations, %d -> %d\n", ++ n_audios, c->n_audios); ++ return AVERROR_INVALIDDATA; + } +- if (cur_audio && cur_audio->fragments) { +- move_segments(c->cur_audio, cur_audio); ++ ++ for (i = 0; i < n_videos; i++) { ++ struct representation *cur_video = videos[i]; ++ struct representation *ccur_video = c->videos[i]; ++ if (cur_video->timelines) { ++ // calc current time ++ int64_t current_time = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale; ++ // update segments ++ ccur_video->cur_seq_no = calc_next_seg_no_from_timelines(ccur_video, current_time * cur_video->fragment_timescale - 1); ++ if (ccur_video->cur_seq_no >= 0) { ++ move_timelines(ccur_video, cur_video, c); ++ } ++ } ++ if (cur_video->fragments) { ++ move_segments(ccur_video, cur_video, c); ++ } ++ } ++ for (i = 0; i < n_audios; i++) { ++ struct representation *cur_audio = audios[i]; ++ struct representation *ccur_audio = c->audios[i]; ++ if (cur_audio->timelines) { ++ // calc current time ++ int64_t current_time = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale; ++ // update segments ++ ccur_audio->cur_seq_no = calc_next_seg_no_from_timelines(ccur_audio, current_time * cur_audio->fragment_timescale - 1); ++ if (ccur_audio->cur_seq_no >= 0) { ++ move_timelines(ccur_audio, cur_audio, c); ++ } ++ } ++ if (cur_audio->fragments) { ++ move_segments(ccur_audio, cur_audio, c); ++ } + } + + finish: +@@ -1186,12 +1489,14 @@ + av_free(base_url); + else + c->base_url = base_url; +- if (c->cur_audio) +- free_representation(c->cur_audio); +- if (c->cur_video) +- free_representation(c->cur_video); +- c->cur_audio = cur_audio; +- c->cur_video = cur_video; ++ if (c->audios) ++ free_audio_list(c); ++ if (c->videos) ++ free_video_list(c); ++ c->n_audios = n_audios; ++ c->audios = audios; ++ c->n_videos = n_videos; ++ c->videos = videos; + return ret; + } + +@@ -1225,17 +1530,29 @@ + } + } + if (c->is_live) { +- min_seq_no = calc_min_seg_no(pls->parent, pls); +- max_seq_no = calc_max_seg_no(pls); +- +- if (pls->timelines || pls->fragments) { +- refresh_manifest(pls->parent); +- } +- if (pls->cur_seq_no <= min_seq_no) { +- av_log(pls->parent, AV_LOG_VERBOSE, "old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx); +- pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls); +- } else if (pls->cur_seq_no > max_seq_no) { +- av_log(pls->parent, AV_LOG_VERBOSE, "new fragment: min[%"PRId64"] max[%"PRId64"], playlist %d\n", min_seq_no, max_seq_no, (int)pls->rep_idx); ++ while (!ff_check_interrupt(c->interrupt_callback)) { ++ min_seq_no = calc_min_seg_no(pls->parent, pls); ++ max_seq_no = calc_max_seg_no(pls, c); ++ ++ if (pls->cur_seq_no <= min_seq_no) { ++ av_log(pls->parent, AV_LOG_VERBOSE, "to old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx); ++ if (pls->timelines || pls->fragments) { ++ refresh_manifest(pls->parent); ++ } ++ pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls); ++ } else if (pls->cur_seq_no > max_seq_no) { ++ av_log(pls->parent, AV_LOG_VERBOSE, "wait for new fragment:cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx); ++ if (pls->timelines || pls->fragments) { ++ refresh_manifest(pls->parent); ++ } else { ++ /* maybe the better solution will be to sleep based on pls->fragment_duration ++ * for example: 1000 * pls->fragment_duration / pls->fragment_timescale ??? ++ */ ++ sleep_ms(c, 2000); ++ } ++ continue; ++ } ++ break; + } + seg = av_mallocz(sizeof(struct fragment)); + if (!seg) { +@@ -1248,19 +1565,22 @@ + } + } + if (seg) { +- char tmpfilename[MAX_URL_SIZE]; +- +- ff_dash_fill_tmpl_params(tmpfilename, sizeof(tmpfilename), pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no)); ++ char *tmpfilename= av_mallocz(c->max_url_size); ++ if (!tmpfilename) { ++ return NULL; ++ } ++ ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no + pls->start_number, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no)); + seg->url = av_strireplace(pls->url_template, pls->url_template, tmpfilename); + if (!seg->url) { + av_log(pls->parent, AV_LOG_WARNING, "Unable to resolve template url '%s', try to use origin template\n", pls->url_template); + seg->url = av_strdup(pls->url_template); + if (!seg->url) { + av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template); ++ av_free(tmpfilename); + return NULL; + } + } +- ++ av_free(tmpfilename); + seg->size = -1; + } + +@@ -1299,10 +1619,14 @@ + static int open_input(DASHContext *c, struct representation *pls, struct fragment *seg) + { + AVDictionary *opts = NULL; +- char url[MAX_URL_SIZE]; +- int ret; ++ char *url = NULL; ++ int ret = 0; + +- set_httpheader_options(c, opts); ++ url = av_mallocz(c->max_url_size); ++ if (!url) { ++ goto cleanup; ++ } ++ set_httpheader_options(c, &opts); + if (seg->size >= 0) { + /* try to restrict the HTTP request to the part we want + * (if this is in fact a HTTP request) */ +@@ -1310,7 +1634,7 @@ + av_dict_set_int(&opts, "end_offset", seg->url_offset + seg->size, 0); + } + +- ff_make_absolute_url(url, MAX_URL_SIZE, c->base_url, seg->url); ++ ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url); + av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64", playlist %d\n", + url, seg->url_offset, pls->rep_idx); + ret = open_url(pls->parent, &pls->input, url, c->avio_opts, opts, NULL); +@@ -1318,19 +1642,8 @@ + goto cleanup; + } + +- /* Seek to the requested position. If this was a HTTP request, the offset +- * should already be where want it to, but this allows e.g. local testing +- * without a HTTP server. */ +- if (!ret && seg->url_offset) { +- int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET); +- if (seekret < 0) { +- av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of DASH fragment '%s'\n", seg->url_offset, seg->url); +- ret = (int) seekret; +- ff_format_io_close(pls->parent, &pls->input); +- } +- } +- + cleanup: ++ av_free(url); + av_dict_free(&opts); + pls->cur_seg_offset = 0; + pls->cur_seg_size = seg->size; +@@ -1416,13 +1729,28 @@ + + ret = open_input(c, v, v->cur_seg); + if (ret < 0) { +- if (ff_check_interrupt(c->interrupt_callback)) { +- goto end; +- ret = AVERROR_EXIT; ++ av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d error [%s]\n", v->rep_idx, av_err2str(ret)); ++ if (ret == AVERROR_HTTP_NOT_FOUND || \ ++ ret == AVERROR_HTTP_BAD_REQUEST || \ ++ ret == AVERROR_HTTP_OTHER_4XX || \ ++ ret == AVERROR_HTTP_SERVER_ERROR) { ++ if (ret == AVERROR_HTTP_OTHER_4XX) { ++ /* 410 - Gone ? our download is to slow? */ ++ v->cur_seq_no++; ++ } else if (c->is_live && v->timelines || v->fragments) { ++ refresh_manifest(v->parent); ++ } else if (!c->is_live) { ++ /* skip missing segment in VOD */ ++ v->cur_seq_no++; ++ } ++ if (ff_check_interrupt(c->interrupt_callback)) { ++ goto end; ++ ret = AVERROR_EXIT; ++ } ++ goto restart; + } +- av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d\n", v->rep_idx); +- v->cur_seq_no++; +- goto restart; ++ ret = AVERROR_INVALIDDATA; ++ goto end; + } + } + +@@ -1447,9 +1775,11 @@ + if (ret > 0) + goto end; + +- if (!v->is_restart_needed) +- v->cur_seq_no++; +- v->is_restart_needed = 1; ++ if (c->is_live || v->cur_seq_no < v->last_seq_no) { ++ if (!v->is_restart_needed) ++ v->cur_seq_no++; ++ v->is_restart_needed = 1; ++ } + + end: + return ret; +@@ -1466,8 +1796,12 @@ + if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { + if (buf[0] != '\0') { + ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); +- if (ret < 0) ++ if (ret < 0) { ++ av_freep(&buf); + return ret; ++ } ++ } else { ++ av_freep(&buf); + } + } + opt++; +@@ -1486,21 +1820,26 @@ + return AVERROR(EPERM); + } + ++static void close_demux_for_component(struct representation *pls) ++{ ++ /* note: the internal buffer could have changed */ ++ av_freep(&pls->pb.buffer); ++ memset(&pls->pb, 0x00, sizeof(AVIOContext)); ++ pls->ctx->pb = NULL; ++ avformat_close_input(&pls->ctx); ++ pls->ctx = NULL; ++} ++ + static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls) + { + DASHContext *c = s->priv_data; + AVInputFormat *in_fmt = NULL; + AVDictionary *in_fmt_opts = NULL; + uint8_t *avio_ctx_buffer = NULL; +- int ret = 0; ++ int ret = 0, i; + + if (pls->ctx) { +- /* note: the internal buffer could have changed, and be != avio_ctx_buffer */ +- av_freep(&pls->pb.buffer); +- memset(&pls->pb, 0x00, sizeof(AVIOContext)); +- pls->ctx->pb = NULL; +- avformat_close_input(&pls->ctx); +- pls->ctx = NULL; ++ close_demux_for_component(pls); + } + if (!(pls->ctx = avformat_alloc_context())) { + ret = AVERROR(ENOMEM); +@@ -1538,12 +1877,22 @@ + pls->ctx->pb = &pls->pb; + pls->ctx->io_open = nested_io_open; + ++ pls->is_first_pkt = 1; ++ pls->pkt_start_time_offset = 0; ++ + // provide additional information from mpd if available + ret = avformat_open_input(&pls->ctx, "", in_fmt, &in_fmt_opts); //pls->init_section->url + av_dict_free(&in_fmt_opts); + if (ret < 0) + goto fail; + if (pls->n_fragments) { ++#if FF_API_R_FRAME_RATE ++ if (pls->framerate.den) { ++ for (i = 0; i < pls->ctx->nb_streams; i++) ++ pls->ctx->streams[i]->r_frame_rate = pls->framerate; ++ } ++#endif ++ + ret = avformat_find_stream_info(pls->ctx, NULL); + if (ret < 0) + goto fail; +@@ -1560,7 +1909,7 @@ + + pls->parent = s; + pls->cur_seq_no = calc_cur_seg_no(s, pls); +- pls->last_seq_no = calc_max_seg_no(pls); ++ pls->last_seq_no = calc_max_seg_no(pls, s->priv_data); + + ret = reopen_demux_for_component(s, pls); + if (ret < 0) { +@@ -1589,6 +1938,7 @@ + DASHContext *c = s->priv_data; + int ret = 0; + int stream_index = 0; ++ int i; + + c->interrupt_callback = &s->interrupt_callback; + // if the URL context is good, read important options we must broker later +@@ -1610,27 +1960,23 @@ + s->duration = (int64_t) c->media_presentation_duration * AV_TIME_BASE; + } + +- /* Open the demuxer for curent video and current audio components if available */ +- if (!ret && c->cur_video) { +- ret = open_demux_for_component(s, c->cur_video); +- if (!ret) { +- c->cur_video->stream_index = stream_index; +- ++stream_index; +- } else { +- free_representation(c->cur_video); +- c->cur_video = NULL; +- } ++ /* Open the demuxer for video and audio components if available */ ++ for (i = 0; i < c->n_videos; i++) { ++ struct representation *cur_video = c->videos[i]; ++ ret = open_demux_for_component(s, cur_video); ++ if (ret) ++ goto fail; ++ cur_video->stream_index = stream_index; ++ ++stream_index; + } + +- if (!ret && c->cur_audio) { +- ret = open_demux_for_component(s, c->cur_audio); +- if (!ret) { +- c->cur_audio->stream_index = stream_index; +- ++stream_index; +- } else { +- free_representation(c->cur_audio); +- c->cur_audio = NULL; +- } ++ for (i = 0; i < c->n_audios; i++) { ++ struct representation *cur_audio = c->audios[i]; ++ ret = open_demux_for_component(s, cur_audio); ++ if (ret) ++ goto fail; ++ cur_audio->stream_index = stream_index; ++ ++stream_index; + } + + if (!stream_index) { +@@ -1646,11 +1992,25 @@ + goto fail; + } + +- if (c->cur_video) { +- av_program_add_stream_index(s, 0, c->cur_video->stream_index); +- } +- if (c->cur_audio) { +- av_program_add_stream_index(s, 0, c->cur_audio->stream_index); ++ for (i = 0; i < c->n_videos; i++) { ++ struct representation *pls = c->videos[i]; ++ ++ av_program_add_stream_index(s, 0, pls->stream_index); ++ pls->assoc_stream = s->streams[pls->stream_index]; ++ if (pls->bandwidth > 0) ++ av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0); ++ if (pls->id[0]) ++ av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0); ++ } ++ for (i = 0; i < c->n_audios; i++) { ++ struct representation *pls = c->audios[i]; ++ ++ av_program_add_stream_index(s, 0, pls->stream_index); ++ pls->assoc_stream = s->streams[pls->stream_index]; ++ if (pls->bandwidth > 0) ++ av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0); ++ if (pls->id[0]) ++ av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0); + } + } + +@@ -1659,43 +2019,89 @@ + return ret; + } + ++static void recheck_discard_flags(AVFormatContext *s, struct representation **p, int n) ++{ ++ int i, j; ++ ++ for (i = 0; i < n; i++) { ++ struct representation *pls = p[i]; ++ ++ int needed = !pls->assoc_stream || pls->assoc_stream->discard < AVDISCARD_ALL; ++ if (needed && !pls->ctx) { ++ pls->cur_seg_offset = 0; ++ pls->init_sec_buf_read_offset = 0; ++ /* Catch up */ ++ for (j = 0; j < n; j++) { ++ pls->cur_seq_no = FFMAX(pls->cur_seq_no, p[j]->cur_seq_no); ++ } ++ reopen_demux_for_component(s, pls); ++ av_log(s, AV_LOG_INFO, "Now receiving stream_index %d\n", pls->stream_index); ++ } else if (!needed && pls->ctx) { ++ close_demux_for_component(pls); ++ if (pls->input) ++ ff_format_io_close(pls->parent, &pls->input); ++ av_log(s, AV_LOG_INFO, "No longer receiving stream_index %d\n", pls->stream_index); ++ } ++ } ++} ++ + static int dash_read_packet(AVFormatContext *s, AVPacket *pkt) + { + DASHContext *c = s->priv_data; +- int ret = 0; ++ int ret = 0, i; ++ int64_t mints = 0; + struct representation *cur = NULL; + +- if (!c->cur_audio && !c->cur_video ) { +- return AVERROR_INVALIDDATA; ++ recheck_discard_flags(s, c->videos, c->n_videos); ++ recheck_discard_flags(s, c->audios, c->n_audios); ++ ++ for (i = 0; i < c->n_videos; i++) { ++ struct representation *pls = c->videos[i]; ++ if (!pls->ctx) ++ continue; ++ if (!cur || pls->cur_timestamp < mints) { ++ cur = pls; ++ mints = pls->cur_timestamp; ++ } + } +- if (c->cur_audio && !c->cur_video) { +- cur = c->cur_audio; +- } else if (!c->cur_audio && c->cur_video) { +- cur = c->cur_video; +- } else if (c->cur_video->cur_timestamp < c->cur_audio->cur_timestamp) { +- cur = c->cur_video; +- } else { +- cur = c->cur_audio; ++ for (i = 0; i < c->n_audios; i++) { ++ struct representation *pls = c->audios[i]; ++ if (!pls->ctx) ++ continue; ++ if (!cur || pls->cur_timestamp < mints) { ++ cur = pls; ++ mints = pls->cur_timestamp; ++ } + } + +- if (cur->ctx) { +- while (!ff_check_interrupt(c->interrupt_callback) && !ret) { +- ret = av_read_frame(cur->ctx, pkt); +- if (ret >= 0) { +- /* If we got a packet, return it */ +- cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den); +- pkt->stream_index = cur->stream_index; +- return 0; +- } +- if (cur->is_restart_needed) { +- cur->cur_seg_offset = 0; +- cur->init_sec_buf_read_offset = 0; +- if (cur->input) +- ff_format_io_close(cur->parent, &cur->input); +- ret = reopen_demux_for_component(s, cur); +- cur->is_restart_needed = 0; +- } +- ++ if (!cur) { ++ return AVERROR_INVALIDDATA; ++ } ++ while (!ff_check_interrupt(c->interrupt_callback) && !ret) { ++ ret = av_read_frame(cur->ctx, pkt); ++ if (ret >= 0) { ++ if (c->is_live && cur->is_first_pkt && 0 == pkt->pts) { ++ cur->pkt_start_time_offset = get_segment_start_time_based_on_timeline(cur, cur->cur_seq_no); ++ } ++ if (cur->pkt_start_time_offset) { ++ AVRational bq; ++ bq.num = 1; ++ bq.den = (int)cur->fragment_timescale; ++ pkt->pts += av_rescale_q(cur->pkt_start_time_offset, bq,cur->ctx->streams[0]->time_base); ++ } ++ /* If we got a packet, return it */ ++ cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den); ++ pkt->stream_index = cur->stream_index; ++ cur->is_first_pkt = 0; ++ return 0; ++ } ++ if (cur->is_restart_needed) { ++ cur->cur_seg_offset = 0; ++ cur->init_sec_buf_read_offset = 0; ++ if (cur->input) ++ ff_format_io_close(cur->parent, &cur->input); ++ ret = reopen_demux_for_component(s, cur); ++ cur->is_restart_needed = 0; + } + } + return AVERROR_EOF; +@@ -1704,12 +2110,8 @@ + static int dash_close(AVFormatContext *s) + { + DASHContext *c = s->priv_data; +- if (c->cur_audio) { +- free_representation(c->cur_audio); +- } +- if (c->cur_video) { +- free_representation(c->cur_video); +- } ++ free_audio_list(c); ++ free_video_list(c); + + av_freep(&c->cookies); + av_freep(&c->user_agent); +@@ -1718,19 +2120,22 @@ + return 0; + } + +-static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags) ++static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags, int dry_run) + { + int ret = 0; + int i = 0; + int j = 0; + int64_t duration = 0; + +- av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d\n", seek_pos_msec, pls->rep_idx); ++ av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d%s\n", ++ seek_pos_msec, pls->rep_idx, dry_run ? " (dry)" : ""); + + // single fragment mode + if (pls->n_fragments == 1) { + pls->cur_timestamp = 0; + pls->cur_seg_offset = 0; ++ if (dry_run) ++ return 0; + ff_read_frame_flush(pls->ctx); + return av_seek_frame(pls->ctx, -1, seek_pos_msec * 1000, flags); + } +@@ -1769,20 +2174,20 @@ + } else if (pls->fragment_duration > 0) { + pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000; + } else { +- av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing fragment_duration\n"); ++ av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing timeline or fragment_duration\n"); + pls->cur_seq_no = pls->first_seq_no; + } + pls->cur_timestamp = 0; + pls->cur_seg_offset = 0; + pls->init_sec_buf_read_offset = 0; +- ret = reopen_demux_for_component(s, pls); ++ ret = dry_run ? 0 : reopen_demux_for_component(s, pls); + + return ret; + } + + static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) + { +- int ret = 0; ++ int ret = 0, i; + DASHContext *c = s->priv_data; + int64_t seek_pos_msec = av_rescale_rnd(timestamp, 1000, + s->streams[stream_index]->time_base.den, +@@ -1790,12 +2195,17 @@ + AV_ROUND_DOWN : AV_ROUND_UP); + if ((flags & AVSEEK_FLAG_BYTE) || c->is_live) + return AVERROR(ENOSYS); +- if (c->cur_audio) { +- ret = dash_seek(s, c->cur_audio, seek_pos_msec, flags); +- } +- if (!ret && c->cur_video) { +- ret = dash_seek(s, c->cur_video, seek_pos_msec, flags); ++ ++ /* Seek in discarded streams with dry_run=1 to avoid reopening them */ ++ for (i = 0; i < c->n_videos; i++) { ++ if (!ret) ++ ret = dash_seek(s, c->videos[i], seek_pos_msec, flags, !c->videos[i]->ctx); ++ } ++ for (i = 0; i < c->n_audios; i++) { ++ if (!ret) ++ ret = dash_seek(s, c->audios[i], seek_pos_msec, flags, !c->audios[i]->ctx); + } ++ + return ret; + } + +@@ -1820,6 +2230,10 @@ + #define OFFSET(x) offsetof(DASHContext, x) + #define FLAGS AV_OPT_FLAG_DECODING_PARAM + static const AVOption dash_options[] = { ++ {"audio_rep_index", "audio representation index to be used", ++ OFFSET(audio_rep_index), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, FLAGS}, ++ {"video_rep_index", "video representation index to be used", ++ OFFSET(video_rep_index), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, FLAGS}, + {"allowed_extensions", "List of file extensions that dash is allowed to access", + OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, + {.str = "aac,m4a,m4s,m4v,mov,mp4"}, +@@ -1845,4 +2259,4 @@ + .read_close = dash_close, + .read_seek = dash_read_seek, + .flags = AVFMT_NO_BYTE_SEEK, +-}; ++}; +\ No newline at end of file diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch new file mode 100644 index 0000000..49e9642 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch @@ -0,0 +1,11 @@ +--- a/libavformat/Makefile ++++ b/libavformat/Makefile +@@ -135,7 +135,7 @@ + OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o + OBJS-$(CONFIG_DATA_MUXER) += rawenc.o + OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o +-OBJS-$(CONFIG_DASH_DEMUXER) += dashdec.o ++OBJS-$(CONFIG_DASH_DEMUXER) += dash.o dashdec.o + OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o + OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o + OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch new file mode 100644 index 0000000..a266023 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch @@ -0,0 +1,16 @@ +Taapat: disable log to fix freezing on edit list parsing intruduced in: +http://git.videolan.org/gitweb.cgi/ffmpeg.git/?p=ffmpeg.git;a=commitdiff;h=ca6cae73db207f17a0d5507609de12842d8f0ca3 + +--- a/libavformat/mov.c ++++ b/libavformat/mov.c +@@ -3191,8 +3191,10 @@ + + if (ctts_data_old && ctts_index_old < ctts_count_old) { + curr_ctts = ctts_data_old[ctts_index_old].duration; ++ /* + av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n", + curr_cts, curr_ctts, ctts_index_old, ctts_count_old); ++ */ + curr_cts += curr_ctts; + ctts_sample_old++; + if (ctts_sample_old == ctts_data_old[ctts_index_old].count) { diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch new file mode 100644 index 0000000..a57cbc8 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch @@ -0,0 +1,15 @@ +--- a/libavformat/hls.c ++++ b/libavformat/hls.c +@@ -1924,8 +1924,10 @@ + HLSContext *c = s->priv_data; + int ret, i, minplaylist = -1; + +- recheck_discard_flags(s, c->first_packet); +- c->first_packet = 0; ++ if (c->first_packet) { ++ recheck_discard_flags(s, 1); ++ c->first_packet = 0; ++ } + + for (i = 0; i < c->n_playlists; i++) { + struct playlist *pls = c->playlists[i]; diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch new file mode 100644 index 0000000..bfd7f72 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch @@ -0,0 +1,16 @@ +diff -uNr ffmpeg-3.4.2/libavformat/mpegts.c ffmpeg-3.4.2_fix_mpegts/libavformat/mpegts.c +--- ffmpeg-3.4.2/libavformat/mpegts.c 2018-02-12 01:29:06.000000000 +0100 ++++ ffmpeg-3.4.2_fix_mpegts/libavformat/mpegts.c 2018-02-14 19:36:28.175054407 +0100 +@@ -917,10 +917,12 @@ + pes->buffer = NULL; + reset_pes_packet_state(pes); + ++ /* + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_MPEGTS_STREAM_ID, 1); + if (!sd) + return AVERROR(ENOMEM); + *sd = pes->stream_id; ++ */ + + return 0; + } diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch new file mode 100644 index 0000000..4248694 --- /dev/null +++ b/archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch @@ -0,0 +1,57 @@ +--- ffmpeg-3.4.2/libavformat/hls.c ++++ ffmpeg-3.4.2/libavformat/hls.c +@@ -206,6 +206,8 @@ + int strict_std_compliance; + char *allowed_extensions; + int max_reload; ++ char *key_uri_replace_old; ++ char *key_uri_replace_new; + } HLSContext; + + static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) +@@ -1127,8 +1129,17 @@ + AVDictionary *opts2 = NULL; + char iv[33], key[33], url[MAX_URL_SIZE]; + if (strcmp(seg->key, pls->key_url)) { ++ char *key_url = NULL; + AVIOContext *pb; +- if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) { ++ ++ if (NULL != c->key_uri_replace_old && \ ++ NULL != c-> key_uri_replace_new && \ ++ '\0' != c->key_uri_replace_old[0]) { ++ key_url = av_strireplace(seg->key, c->key_uri_replace_old, c->key_uri_replace_new); ++ } else { ++ key_url = seg->key; ++ } ++ if (open_url(pls->parent, &pb, key_url, c->avio_opts, opts, NULL) == 0) { + ret = avio_read(pb, pls->key, sizeof(pls->key)); + if (ret != sizeof(pls->key)) { + av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", +@@ -1140,6 +1151,8 @@ + seg->key); + } + av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url)); ++ if (key_url != seg->key) ++ av_free(key_url); + } + ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); + ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); +@@ -1846,7 +1859,7 @@ + for (i = 0; i < c->n_playlists; i++) + c->playlists[i]->cur_needed = 0; + +- for (i = 0; i < s->nb_streams; i++) { ++ for (i = 0; i < s->nb_streams && s->streams[i]->id < c->n_playlists; i++) { + AVStream *st = s->streams[i]; + struct playlist *pls = c->playlists[s->streams[i]->id]; + if (st->discard < AVDISCARD_ALL) +@@ -2159,6 +2172,8 @@ + INT_MIN, INT_MAX, FLAGS}, + {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded", + OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, ++ { "key_uri_old", "allow to replace part of AES key uri - old", OFFSET(key_uri_replace_old), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS }, ++ { "key_uri_new", "allow to replace part of AES key uri - new", OFFSET(key_uri_replace_new), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS }, + {NULL} + }; + diff --git a/archive-patches/libass-0.14.0.patch b/archive-patches/libass-0.14.0.patch new file mode 100644 index 0000000..869c217 --- /dev/null +++ b/archive-patches/libass-0.14.0.patch @@ -0,0 +1,51 @@ +--- a/libass/ass.c ++++ b/libass/ass.c +@@ -627,6 +627,26 @@ + "No event format found, using fallback"); + } + ++// we may get duplicate events from a rewinded stream ... ++static int check_duplicate_event_adv(ASS_Track *track) ++{ ++ int i, last = track->n_events - 1; ++ for (i = 0; i < last; ++i) ++ if (track->events[i].Start == track->events[last].Start ++ && track->events[i].Duration == track->events[last].Duration ++ && track->events[i].Layer == track->events[last].Layer ++ && track->events[i].Style == track->events[last].Style ++ && track->events[i].MarginL == track->events[last].MarginL ++ && track->events[i].MarginR == track->events[last].MarginR ++ && track->events[i].MarginV == track->events[last].MarginV ++ && !strcmp(track->events[i].Name, track->events[last].Name) ++ && !strcmp(track->events[i].Effect, track->events[last].Effect) ++ && !strcmp(track->events[i].Text, track->events[last].Text) ++ ) ++ return 1; ++ return 0; ++} ++ + static int process_events_line(ASS_Track *track, char *str) + { + if (!strncmp(str, "Format:", 7)) { +@@ -653,6 +673,11 @@ + event_format_fallback(track); + + process_event_tail(track, event, str, 0); ++ ++ if (check_duplicate_event_adv(track)) { ++ ass_free_event(track, eid); ++ track->n_events--; ++ } + } else { + ass_msg(track->library, MSGL_V, "Not understood: '%.30s'", str); + } +@@ -939,6 +964,9 @@ + + event->Start = timecode; + event->Duration = duration; ++ ++ if (check_duplicate_event_adv(track)) ++ break; + + free(str); + return; diff --git a/doc/config.example b/doc/config.example index 68804f9..caadf83 100755 --- a/doc/config.example +++ b/doc/config.example @@ -6,6 +6,7 @@ # possible values are tank, trinity, link, zee2, zee and neo # please select also link for trinity duo # and neo for neo-twin, neo2, hd1 and bse as well +# For Armboxes you can set hd51. # if you don't specify a value or something is misspelled # the default value neo will be used # diff --git a/make/archives.mk b/make/archives.mk index c2a53f3..7cd60e0 100755 --- a/make/archives.mk +++ b/make/archives.mk @@ -1,11 +1,17 @@ # makefile for tarball download +$(ARCHIVE)/alsa-lib-$(ALSA_LIB_VER).tar.bz2: + $(WGET) ftp://ftp.alsa-project.org/pub/lib/alsa-lib-$(ALSA_LIB_VER).tar.bz2 + $(ARCHIVE)/autofs-$(AUTOFS4_VER).tar.gz: $(WGET) https://www.kernel.org/pub/linux/daemons/autofs/v4/autofs-$(AUTOFS4_VER).tar.gz $(ARCHIVE)/zlib-$(ZLIB_VER).tar.xz: $(WGET) http://downloads.sourceforge.net/project/libpng/zlib/$(ZLIB_VER)/zlib-$(ZLIB_VER).tar.xz +$(ARCHIVE)/libass-$(LIBASS_VER).tar.xz: + $(WGET) https://github.com/libass/libass/releases/download/$(LIBASS_VER)/libass-$(LIBASS_VER).tar.xz + $(ARCHIVE)/libmad-0.15.1b.tar.gz: $(WGET) http://www.fhloston-paradise.de/libmad-0.15.1b.tar.gz @@ -33,6 +39,9 @@ $(ARCHIVE)/hotplug.tar.gz: $(ARCHIVE)/fbshot-$(FBSHOT_VER).tar.gz: $(WGET) http://distro.ibiblio.org/amigolinux/download/Utils/fbshot/fbshot-$(FBSHOT_VER).tar.gz +$(ARCHIVE)/ffmpeg-$(FFMPEG_VER).tar.xz: + $(WGET) http://www.ffmpeg.org/releases/ffmpeg-$(FFMPEG_VER).tar.xz + $(ARCHIVE)/ffmpeg-git-$(FFMPEG_GIT).tar.gz: set -e; cd $(BUILD_TMP); \ rm -rf ffmpeg-git-$(FFMPEG_GIT); \ diff --git a/make/bootstrap.mk b/make/bootstrap.mk index 7bc42e6..6c48414 100755 --- a/make/bootstrap.mk +++ b/make/bootstrap.mk @@ -51,13 +51,20 @@ skeleton: | $(TARGETPREFIX) else \ cp --remove-destination -a skel-root-kronos/* $(TARGETPREFIX)/; \ fi \ - else \ + elif [ $(PLATFORM) = "nevis" ]; then \ if [ -n $(SKEL_ROOT_DIR) ]; then \ [ ! -e $(BASE_DIR)/my-skel-root-nevis ] && ln -s $(SKEL_ROOT_DIR) $(BASE_DIR)/my-skel-root-nevis; \ cp --remove-destination -a my-skel-root-nevis/* $(TARGETPREFIX)/; \ else \ cp --remove-destination -a skel-root-nevis/* $(TARGETPREFIX)/; \ fi \ + else \ + if [ $(PLATFORM) = "bcm7251s" ]; then \ + [ ! -e $(BASE_DIR)/my-skel-root-hd51 ] && ln -s $(SKEL_ROOT_DIR) $(BASE_DIR)/my-skel-root-hd51; \ + cp --remove-destination -a my-skel-root-hd51/* $(TARGETPREFIX)/; \ + else \ + cp --remove-destination -a skel-root-hd51/* $(TARGETPREFIX)/; \ + fi \ fi touch $(TARGETPREFIX)/.$(PLATFORM) @@ -81,18 +88,24 @@ $(HOSTPREFIX)/bin/get%.sh: | $(HOSTPREFIX)/bin $(TARGETPREFIX)/lib: | $(TARGETPREFIX) mkdir -p $@ - cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/libs/* $@/ - if [ "$(CST_FFMPEG_VERSION)" = "ffmpeg-3.3" ]; then \ - cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/libs-$(CST_FFMPEG_VERSION)/* $@/; \ + if test -e $(SOURCE_DIR)/git/DRIVERS; then \ + cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/libs/* $@/; \ + if [ "$(CST_FFMPEG_VERSION)" = "ffmpeg-3.3" ]; then \ + cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/libs-$(CST_FFMPEG_VERSION)/* $@/; \ + fi \ fi $(TARGETPREFIX)/lib/firmware: | $(TARGETPREFIX) mkdir -p $@ - cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/firmware/* $@/ + if test -e $(SOURCE_DIR)/git/DRIVERS; then \ + cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/firmware/* $@/; \ + fi $(TARGETPREFIX)/lib/modules/$(KVERSION_FULL): | $(TARGETPREFIX) mkdir -p $@ - cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/drivers/$(KVERSION_FULL)/* $@/ + if test -e $(SOURCE_DIR)/git/DRIVERS; then \ + cp -a $(SOURCE_DIR)/git/DRIVERS/$(DRIVER_DIR)/drivers/$(KVERSION_FULL)/* $@/; \ + fi $(TARGETPREFIX)/lib/libc.so.6: | $(TARGETPREFIX) if test -e $(CROSS_DIR)/$(TARGET)/sys-root/lib; then \ diff --git a/make/environment.mk b/make/environment.mk index d77524c..d62c352 100755 --- a/make/environment.mk +++ b/make/environment.mk @@ -59,11 +59,20 @@ else ifeq ($(BOXMODEL), $(filter $(BOXMODEL), neo zee)) CST_KERNEL_VERSION ?= 2.6.34.13 KVERSION_FULL = $(CST_KERNEL_VERSION)-nevis KBRANCH ?= $(CST_KERNEL_VERSION)-cnxt +else ifeq ($(BOXMODEL), hd51) + BOXTYPE = armbox + BOXSERIES = hd51 + TARGET ?= arm-cortex-linux-gnueabihf + PLATFORM = bcm7251s + DRIVER_DIR ?= $(PLATFORM) + CST_KERNEL_VERSION ?= 4.10.12 + KVERSION_FULL = $(CST_KERNEL_VERSION)-nevis + KBRANCH ?= $(CST_KERNEL_VERSION)-cnxt else $(error $(BOXTYPE) BOXMODEL $(BOXMODEL) not supported) endif -ifeq ($(BOXTYPE), coolstream) +ifeq ($(BOXTYPE), $(filter $(BOXTYPE), coolstream armbox)) BOXARCH = arm endif @@ -79,6 +88,12 @@ else ifeq ($(BOXSERIES), hd2) TARGET_EXTRA_CFLAGS = -fdata-sections -ffunction-sections TARGET_EXTRA_LDFLAGS = -Wl,--gc-sections CXX11_ABI = -D_GLIBCXX_USE_CXX11_ABI=0 +else ifeq ($(BOXSERIES), hd51) + CORTEX-STRINGS = -lcortex-strings + TARGET_MARCH_CFLAGS = -march=armv7ve -mtune=cortex-a15 -mfpu=neon-vfpv4 -mfloat-abi=hard + TARGET_EXTRA_CFLAGS = -fdata-sections -ffunction-sections + TARGET_EXTRA_LDFLAGS = -Wl,--gc-sections + CXX11_ABI = else $(error $(BOXTYPE) BOXSERIES $(BOXSERIES) not supported) endif @@ -173,8 +188,9 @@ REPO_DRIVERS_BIN_CST = drivers-bin-cst.git REPO_DRIVERS_THIRD_PARTY_CST = drivers-third-party-cst.git REPO_GUI_NEUTRINO = gui-neutrino.git REPO_GUI_YWEB = gui-yweb.git -REPO_LIBRARY_DVBSI = library-dvbsi.git -REPO_LIBRARY_FFMPEG_CST = library-ffmpeg-cst.git +#REPO_LIBRARY_DVBSI = library-dvbsi.git +#REPO_LIBRARY_FFMPEG_CST = library-ffmpeg-cst.git +REPO_LIBSTB_HAL = library-stb-hal.git REPO_KERNEL_CST = linux-kernel-cst.git REPO_PLUGIN_BLOCKADS = plugin-blockads.git REPO_PLUGIN_COOLITSCLIMAX = plugin-cooliTSclimax.git @@ -195,6 +211,7 @@ REPO_PLUGIN_TUXWETTER = plugin-tuxwetter.git REPO_PLUGINS = plugins.git # (Enthält Submodules) # some usefull folders +GIT_LIBSTB_HAL = $(SOURCE_DIR)/git/LIBSTB_HAL GIT_BOOTLOADER = $(SOURCE_DIR)/git/BOOTLOADER GIT_DRIVERS_THIRDPARTY = $(SOURCE_DIR)/git/DRIVERS_THIRDPARTY GIT_DRIVERS = $(SOURCE_DIR)/git/DRIVERS diff --git a/make/ffmpeg.mk b/make/ffmpeg.mk new file mode 100644 index 0000000..7eb4296 --- /dev/null +++ b/make/ffmpeg.mk @@ -0,0 +1,512 @@ +ifeq ($(BOXTYPE), coolstream) +FFMPEG_CONFIGURE = \ + --disable-doc \ + --disable-htmlpages \ + --disable-manpages \ + --disable-podpages \ + --disable-txtpages \ + \ + --disable-parsers \ + --enable-parser=aac \ + --enable-parser=aac_latm \ + --enable-parser=ac3 \ + --enable-parser=dca \ + --enable-parser=mpeg4video \ + --enable-parser=mpegvideo \ + --enable-parser=mpegaudio \ + --enable-parser=h264 \ + --enable-parser=vc1 \ + --enable-parser=dvdsub \ + --enable-parser=dvbsub \ + --enable-parser=flac \ + --enable-parser=vorbis \ + \ + --disable-decoders \ + --enable-decoder=dca \ + --enable-decoder=dvdsub \ + --enable-decoder=dvbsub \ + --enable-decoder=text \ + --enable-decoder=srt \ + --enable-decoder=subrip \ + --enable-decoder=subviewer \ + --enable-decoder=subviewer1 \ + --enable-decoder=xsub \ + --enable-decoder=pgssub \ + --enable-decoder=movtext \ + --enable-decoder=mp3 \ + --enable-decoder=flac \ + --enable-decoder=vorbis \ + --enable-decoder=aac \ + --enable-decoder=mjpeg \ + --enable-decoder=pcm_s16le \ + --enable-decoder=pcm_s16le_planar \ + \ + --disable-demuxers \ + --enable-demuxer=aac \ + --enable-demuxer=ac3 \ + --enable-demuxer=avi \ + --enable-demuxer=mov \ + --enable-demuxer=vc1 \ + --enable-demuxer=mpegts \ + --enable-demuxer=mpegtsraw \ + --enable-demuxer=mpegps \ + --enable-demuxer=mpegvideo \ + --enable-demuxer=wav \ + --enable-demuxer=pcm_s16be \ + --enable-demuxer=mp3 \ + --enable-demuxer=pcm_s16le \ + --enable-demuxer=matroska \ + --enable-demuxer=flv \ + --enable-demuxer=rm \ + --enable-demuxer=rtsp \ + --enable-demuxer=hls \ + --enable-demuxer=dts \ + --enable-demuxer=wav \ + --enable-demuxer=ogg \ + --enable-demuxer=flac \ + --enable-demuxer=srt \ + --enable-demuxer=hds \ + --enable-demuxer=dash \ + \ + --disable-encoders \ + --disable-muxers \ + --enable-muxer=mpegts \ + \ + --disable-programs \ + --disable-static \ + --disable-filters \ + \ + --enable-librtmp \ + --disable-protocol=data \ + --disable-protocol=cache \ + --disable-protocol=concat \ + --disable-protocol=crypto \ + --disable-protocol=ftp \ + --disable-protocol=gopher \ + --disable-protocol=httpproxy \ + --disable-protocol=pipe \ + --disable-protocol=sctp \ + --disable-protocol=srtp \ + --disable-protocol=subfile \ + --disable-protocol=unix \ + --disable-protocol=md5 \ + --disable-protocol=hls \ + --enable-openssl \ + --enable-protocol=file \ + --enable-protocol=http \ + --enable-protocol=https \ + --enable-protocol=rtmp \ + --enable-protocol=rtmpe \ + --enable-protocol=rtmps \ + --enable-protocol=rtmpte \ + --enable-protocol=mmsh \ + --enable-protocol=mmst \ + --enable-protocol=rtp \ + --enable-protocol=tcp \ + --enable-protocol=udp \ + --enable-bsfs \ + --disable-devices \ + --enable-swresample \ + --disable-postproc \ + --disable-swscale \ + --disable-mmx \ + --disable-altivec \ + --enable-network \ + --enable-cross-compile \ + --enable-shared \ + --enable-small \ + --disable-bzlib \ + --enable-zlib \ + --disable-xlib \ + --enable-libxml2 \ + --disable-debug \ + --enable-stripping \ + --enable-decoder=h264 \ + --enable-decoder=vc1 \ + --target-os=linux \ + --disable-neon \ + --disable-runtime-cpudetect \ + --arch=arm \ + --pkg-config=pkg-config + +else ifeq ($(BOXTYPE), armbox) +FFMPEG_CONFIGURE = \ + --disable-ffserver \ + --disable-ffplay \ + --enable-ffprobe \ + \ + --disable-doc \ + --disable-htmlpages \ + --disable-manpages \ + --disable-podpages \ + --disable-txtpages \ + \ + --disable-altivec \ + --disable-amd3dnow \ + --disable-amd3dnowext \ + --disable-mmx \ + --disable-mmxext \ + --disable-sse \ + --disable-sse2 \ + --disable-sse3 \ + --disable-ssse3 \ + --disable-sse4 \ + --disable-sse42 \ + --disable-avx \ + --disable-xop \ + --disable-fma3 \ + --disable-fma4 \ + --disable-avx2 \ + --disable-armv5te \ + --disable-armv6 \ + --disable-armv6t2 \ + --disable-inline-asm \ + --disable-yasm \ + --disable-mips32r2 \ + --disable-mipsdsp \ + --disable-mipsdspr2 \ + --disable-fast-unaligned \ + \ + --disable-dxva2 \ + --disable-vaapi \ + --disable-vdpau \ + \ + --disable-muxers \ + --enable-muxer=apng \ + --enable-muxer=flac \ + --enable-muxer=mp3 \ + --enable-muxer=h261 \ + --enable-muxer=h263 \ + --enable-muxer=h264 \ + --enable-muxer=hevc \ + --enable-muxer=image2 \ + --enable-muxer=image2pipe \ + --enable-muxer=m4v \ + --enable-muxer=matroska \ + --enable-muxer=mjpeg \ + --enable-muxer=mp4 \ + --enable-muxer=mpeg1video \ + --enable-muxer=mpeg2video \ + --enable-muxer=mpegts \ + --enable-muxer=ogg \ + \ + --disable-parsers \ + --enable-parser=aac \ + --enable-parser=aac_latm \ + --enable-parser=ac3 \ + --enable-parser=dca \ + --enable-parser=dvbsub \ + --enable-parser=dvd_nav \ + --enable-parser=dvdsub \ + --enable-parser=flac \ + --enable-parser=h264 \ + --enable-parser=hevc \ + --enable-parser=mjpeg \ + --enable-parser=mpeg4video \ + --enable-parser=mpegvideo \ + --enable-parser=mpegaudio \ + --enable-parser=png \ + --enable-parser=vc1 \ + --enable-parser=vorbis \ + --enable-parser=vp8 \ + --enable-parser=vp9 \ + \ + --disable-encoders \ + --enable-encoder=aac \ + --enable-encoder=h261 \ + --enable-encoder=h263 \ + --enable-encoder=h263p \ + --enable-encoder=jpeg2000 \ + --enable-encoder=jpegls \ + --enable-encoder=ljpeg \ + --enable-encoder=mjpeg \ + --enable-encoder=mpeg1video \ + --enable-encoder=mpeg2video \ + --enable-encoder=mpeg4 \ + --enable-encoder=png \ + --enable-encoder=rawvideo \ + \ + --disable-decoders \ + --enable-decoder=aac \ + --enable-decoder=aac_latm \ + --enable-decoder=adpcm_ct \ + --enable-decoder=adpcm_g722 \ + --enable-decoder=adpcm_g726 \ + --enable-decoder=adpcm_g726le \ + --enable-decoder=adpcm_ima_amv \ + --enable-decoder=adpcm_ima_oki \ + --enable-decoder=adpcm_ima_qt \ + --enable-decoder=adpcm_ima_rad \ + --enable-decoder=adpcm_ima_wav \ + --enable-decoder=adpcm_ms \ + --enable-decoder=adpcm_sbpro_2 \ + --enable-decoder=adpcm_sbpro_3 \ + --enable-decoder=adpcm_sbpro_4 \ + --enable-decoder=adpcm_swf \ + --enable-decoder=adpcm_yamaha \ + --enable-decoder=alac \ + --enable-decoder=ape \ + --enable-decoder=atrac1 \ + --enable-decoder=atrac3 \ + --enable-decoder=atrac3p \ + --enable-decoder=ass \ + --enable-decoder=cook \ + --enable-decoder=dca \ + --enable-decoder=dsd_lsbf \ + --enable-decoder=dsd_lsbf_planar \ + --enable-decoder=dsd_msbf \ + --enable-decoder=dsd_msbf_planar \ + --enable-decoder=dvbsub \ + --enable-decoder=dvdsub \ + --enable-decoder=eac3 \ + --enable-decoder=evrc \ + --enable-decoder=flac \ + --enable-decoder=g723_1 \ + --enable-decoder=g729 \ + --enable-decoder=h261 \ + --enable-decoder=h263 \ + --enable-decoder=h263i \ + --enable-decoder=h264 \ + --enable-decoder=hevc \ + --enable-decoder=iac \ + --enable-decoder=imc \ + --enable-decoder=jpeg2000 \ + --enable-decoder=jpegls \ + --enable-decoder=mace3 \ + --enable-decoder=mace6 \ + --enable-decoder=metasound \ + --enable-decoder=mjpeg \ + --enable-decoder=mlp \ + --enable-decoder=movtext \ + --enable-decoder=mp1 \ + --enable-decoder=mp3 \ + --enable-decoder=mp3adu \ + --enable-decoder=mp3on4 \ + --enable-decoder=mpeg1video \ + --enable-decoder=mpeg4 \ + --enable-decoder=nellymoser \ + --enable-decoder=opus \ + --enable-decoder=pcm_alaw \ + --enable-decoder=pcm_bluray \ + --enable-decoder=pcm_dvd \ + --enable-decoder=pcm_f32be \ + --enable-decoder=pcm_f32le \ + --enable-decoder=pcm_f64be \ + --enable-decoder=pcm_f64le \ + --enable-decoder=pcm_lxf \ + --enable-decoder=pcm_mulaw \ + --enable-decoder=pcm_s16be \ + --enable-decoder=pcm_s16be_planar \ + --enable-decoder=pcm_s16le \ + --enable-decoder=pcm_s16le_planar \ + --enable-decoder=pcm_s24be \ + --enable-decoder=pcm_s24daud \ + --enable-decoder=pcm_s24le \ + --enable-decoder=pcm_s24le_planar \ + --enable-decoder=pcm_s32be \ + --enable-decoder=pcm_s32le \ + --enable-decoder=pcm_s32le_planar \ + --enable-decoder=pcm_s8 \ + --enable-decoder=pcm_s8_planar \ + --enable-decoder=pcm_u16be \ + --enable-decoder=pcm_u16le \ + --enable-decoder=pcm_u24be \ + --enable-decoder=pcm_u24le \ + --enable-decoder=pcm_u32be \ + --enable-decoder=pcm_u32le \ + --enable-decoder=pcm_u8 \ + --enable-decoder=pcm_zork \ + --enable-decoder=pgssub \ + --enable-decoder=png \ + --enable-decoder=qcelp \ + --enable-decoder=qdm2 \ + --enable-decoder=ra_144 \ + --enable-decoder=ra_288 \ + --enable-decoder=ralf \ + --enable-decoder=s302m \ + --enable-decoder=sipr \ + --enable-decoder=shorten \ + --enable-decoder=sonic \ + --enable-decoder=srt \ + --enable-decoder=ssa \ + --enable-decoder=subrip \ + --enable-decoder=subviewer \ + --enable-decoder=subviewer1 \ + --enable-decoder=tak \ + --enable-decoder=text \ + --enable-decoder=truehd \ + --enable-decoder=truespeech \ + --enable-decoder=tta \ + --enable-decoder=vorbis \ + --enable-decoder=wmalossless \ + --enable-decoder=wmapro \ + --enable-decoder=wmav1 \ + --enable-decoder=wmav2 \ + --enable-decoder=wmavoice \ + --enable-decoder=wavpack \ + --enable-decoder=xsub \ + \ + --disable-demuxers \ + --enable-demuxer=aac \ + --enable-demuxer=ac3 \ + --enable-demuxer=apng \ + --enable-demuxer=ass \ + --enable-demuxer=avi \ + --enable-demuxer=dts \ + --enable-demuxer=dash \ + --enable-demuxer=ffmetadata \ + --enable-demuxer=flac \ + --enable-demuxer=flv \ + --enable-demuxer=h264 \ + --enable-demuxer=hls \ + --enable-demuxer=image2 \ + --enable-demuxer=image2pipe \ + --enable-demuxer=image_bmp_pipe \ + --enable-demuxer=image_jpeg_pipe \ + --enable-demuxer=image_jpegls_pipe \ + --enable-demuxer=image_png_pipe \ + --enable-demuxer=m4v \ + --enable-demuxer=matroska \ + --enable-demuxer=mjpeg \ + --enable-demuxer=mov \ + --enable-demuxer=mp3 \ + --enable-demuxer=mpegts \ + --enable-demuxer=mpegtsraw \ + --enable-demuxer=mpegps \ + --enable-demuxer=mpegvideo \ + --enable-demuxer=mpjpeg \ + --enable-demuxer=ogg \ + --enable-demuxer=pcm_s16be \ + --enable-demuxer=pcm_s16le \ + --enable-demuxer=realtext \ + --enable-demuxer=rawvideo \ + --enable-demuxer=rm \ + --enable-demuxer=rtp \ + --enable-demuxer=rtsp \ + --enable-demuxer=srt \ + --enable-demuxer=vc1 \ + --enable-demuxer=wav \ + --enable-demuxer=webm_dash_manifest \ + \ + --disable-filters \ + --enable-filter=scale \ + --enable-filter=drawtext \ + \ + --enable-zlib \ + --disable-bzlib \ + --enable-openssl \ + --enable-libass \ + --enable-bsfs \ + --disable-xlib \ + --disable-libxcb \ + --disable-libxcb-shm \ + --disable-libxcb-xfixes \ + --disable-libxcb-shape \ + \ + --enable-shared \ + --enable-network \ + --enable-nonfree \ + --enable-small \ + --enable-stripping \ + --disable-static \ + --disable-debug \ + --disable-runtime-cpudetect \ + --enable-pic \ + --enable-pthreads \ + --enable-hardcoded-tables \ + \ + --pkg-config=pkg-config \ + --enable-cross-compile \ + --arch=arm \ + --target-os=linux \ + --bindir=/sbin +else + $(error Boxtype = $(BOXTYPE) not supported) +endif + +FFMPEG_DEP = +ifeq ($(PLATFORM), $(filter $(PLATFORM), apollo kronos)) +FFMPEG_CONFIGURE += --cpu=cortex-a9 --enable-vfp --extra-cflags="-mfpu=vfpv3-d16 -mfloat-abi=hard -I$(TARGETPREFIX)/include" +else ifeq ($(PLATFORM), bcm7251s) +FFMPEG_DEP = $(D)/libass $(D)/alsa-lib +FFMPEG_CONFIGURE += --cpu=cortex-a15 --disable-vfp --extra-cflags="-Wno-deprecated-declarations -I$(TARGETPREFIX)/include" +else +FFMPEG_CONFIGURE += --disable-iconv +FFMPEG_CONFIGURE += --cpu=armv6 --disable-vfp --extra-cflags="-I$(TARGETPREFIX)/include" +endif + +$(D)/ffmpeg-armbox: $(ARCHIVE)/ffmpeg-$(FFMPEG_VER).tar.xz | $(TARGETPREFIX) + $(START_BUILD) + $(REMOVE)/ffmpeg-$(FFMPEG_VER) + $(UNTAR)/ffmpeg-$(FFMPEG_VER).tar.xz + set -e; pushd $(BUILD_TMP)/ffmpeg-$(FFMPEG_VER) && \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-fix-hls.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-buffer-size.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-aac.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-fix-edit-list-parsing.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-fix_mpegts.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-allow_to_choose_rtmp_impl_at_runtime.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-dashdec_improvements.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-fix-dash-build.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-hls_replace_key_uri.patch; \ + $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-chunked_transfer_fix_eof.patch; \ + $(BUILDENV) \ + ./configure \ + $(FFMPEG_CONFIGURE) \ + --extra-ldflags="-L$(TARGETPREFIX)/lib -lz" \ + --logfile=$(BUILD_TMP)/Config-ffmpeg-$(FFMPEG_VER).log \ + --cross-prefix=$(TARGET)- \ + --prefix=/ \ + --mandir=/.remove \ + --datadir=/.remove \ + --docdir=/.remove; \ + $(MAKE) && \ + $(MAKE) install DESTDIR=$(TARGETPREFIX) + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavfilter.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavdevice.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavformat.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavcodec.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavutil.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libswresample.pc + test -e $(PKG_CONFIG_PATH)/libswscale.pc && $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libswscale.pc || true + $(REMOVE)/ffmpeg-$(FFMPEG_VER) $(TARGETPREFIX)/.remove + +$(D)/ffmpeg-coolstream: $(ARCHIVE)/ffmpeg-git-$(FFMPEG_GIT).tar.gz | $(TARGETPREFIX) + $(START_BUILD) + $(REMOVE)/ffmpeg-git-$(FFMPEG_GIT) + $(UNTAR)/ffmpeg-git-$(FFMPEG_GIT).tar.gz + set -e; pushd $(BUILD_TMP)/ffmpeg-git-$(FFMPEG_GIT) && \ + $(PATCH)/ffmpeg/0001-ffmpeg-hds-libroxml-3.x.patch; \ + $(PATCH)/ffmpeg/0002-ffmpeg-aac-3.x.patch; \ + $(PATCH)/ffmpeg/0003-ffmpeg-increase-IO-BUFFER-SIZE-to-128k.patch; \ + $(PATCH)/ffmpeg/0003-Revert-libavformat-aviobuf-keep-track-of-the-original-buffer-size-and-restore-it-after.patch; \ + $(PATCH)/ffmpeg/0004-FFmpeg-devel-v14*.patch; \ + $(PATCH)/ffmpeg/0005-ffmpeg-fix-pts-for-cooli.patch; \ + $(PATCH)/ffmpeg/0006-ffmpeg-fix-sps-pps-for-cooli.patch; \ + $(PATCH)/ffmpeg/0007-ffmpeg-reset-compressed-header-flag.patch; \ + $(PATCH)/ffmpeg/0008-add-ASF-VC1-Annex-G-and-RCV-bitstream-filters.-Origi.patch; \ + $(PATCH)/ffmpeg/ffmpeg-3.3-allow-to-choose-rtmp-impl-at-runtime.patch; \ + $(BUILDENV) \ + ./configure \ + $(FFMPEG_CONFIGURE) \ + --extra-ldflags="-L$(TARGETPREFIX)/lib -lz" \ + --logfile=$(BUILD_TMP)/Config-ffmpeg-$(FFMPEG_GIT).log \ + --cross-prefix=$(TARGET)- \ + --prefix=/ \ + --mandir=/.remove \ + --datadir=/.remove \ + --docdir=/.remove; \ + $(MAKE) && \ + $(MAKE) install DESTDIR=$(TARGETPREFIX) + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavfilter.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavdevice.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavformat.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavcodec.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavutil.pc + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libswresample.pc + test -e $(PKG_CONFIG_PATH)/libswscale.pc && $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libswscale.pc || true + $(REMOVE)/ffmpeg-git-$(FFMPEG_GIT) $(TARGETPREFIX)/.remove + +$(D)/ffmpeg: $(D)/libxml2 $(D)/librtmp $(D)/libroxml $(FFMPEG_DEP) ffmpeg-$(BOXTYPE) + $(TOUCH) + diff --git a/make/libraries.mk b/make/libraries.mk index 424503d..95a6e65 100755 --- a/make/libraries.mk +++ b/make/libraries.mk @@ -12,6 +12,26 @@ ncurses-prereq: false; \ fi +$(D)/libass: $(D)/freetype $(D)/libfribidi $(ARCHIVE)/libass-$(LIBASS_VER).tar.xz | $(TARGET_DIR) + $(START_BUILD) + $(UNTAR)/libass-$(LIBASS_VER).tar.xz + pushd $(BUILD_TMP)/libass-$(LIBASS_VER) && \ + $(PATCH)/libass-0.14.0.patch && \ + $(CONFIGURE) \ + --target=$(TARGET) \ + --prefix= \ + --disable-static \ + --disable-test \ + --disable-fontconfig \ + --disable-harfbuzz \ + --disable-require-system-font-provider && \ + $(MAKE) && \ + $(MAKE) install DESTDIR=$(TARGETPREFIX) + $(REMOVE)/libass-$(LIBASS_VER) + $(REWRITE_LIBTOOL)/libass.la + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libass.pc + $(TOUCH) + $(D)/libncurses: $(ARCHIVE)/ncurses-$(NCURSES_VER).tar.gz | ncurses-prereq $(TARGETPREFIX) $(START_BUILD) $(UNTAR)/ncurses-$(NCURSES_VER).tar.gz && \ @@ -296,7 +316,11 @@ $(D)/cortex-strings: $(ARCHIVE)/cortex-strings-git-$(CRTXSTR_GIT).tar.gz | $(TAR $(START_BUILD) $(UNTAR)/cortex-strings-git-$(CRTXSTR_GIT).tar.gz set -e; cd $(BUILD_TMP)/cortex-strings-git-$(CRTXSTR_GIT); \ - $(CONFIGURE) --prefix= --enable-shared --disable-static --without-neon; \ + $(CONFIGURE) + --prefix= \ + --enable-shared \ + --disable-static \ + --without-neon; \ $(MAKE); \ make install DESTDIR=$(TARGETPREFIX) $(REWRITE_LIBTOOL)/libcortex-strings.la @@ -415,176 +439,6 @@ $(D)/libbluray: $(ARCHIVE)/libbluray-0.5.0.tar.bz2 | $(TARGETPREFIX) $(REMOVE)/libbluray-0.5.0 $(TOUCH) -ifeq ($(BOXARCH), arm) -FFMPEG_CONFIGURE = \ - --disable-doc \ - --disable-htmlpages \ - --disable-manpages \ - --disable-podpages \ - --disable-txtpages \ - \ - --disable-parsers \ - --enable-parser=aac \ - --enable-parser=aac_latm \ - --enable-parser=ac3 \ - --enable-parser=dca \ - --enable-parser=mpeg4video \ - --enable-parser=mpegvideo \ - --enable-parser=mpegaudio \ - --enable-parser=h264 \ - --enable-parser=vc1 \ - --enable-parser=dvdsub \ - --enable-parser=dvbsub \ - --enable-parser=flac \ - --enable-parser=vorbis \ - \ - --disable-decoders \ - --enable-decoder=dca \ - --enable-decoder=dvdsub \ - --enable-decoder=dvbsub \ - --enable-decoder=text \ - --enable-decoder=srt \ - --enable-decoder=subrip \ - --enable-decoder=subviewer \ - --enable-decoder=subviewer1 \ - --enable-decoder=xsub \ - --enable-decoder=pgssub \ - --enable-decoder=movtext \ - --enable-decoder=mp3 \ - --enable-decoder=flac \ - --enable-decoder=vorbis \ - --enable-decoder=aac \ - --enable-decoder=mjpeg \ - --enable-decoder=pcm_s16le \ - --enable-decoder=pcm_s16le_planar \ - \ - --disable-demuxers \ - --enable-demuxer=aac \ - --enable-demuxer=ac3 \ - --enable-demuxer=avi \ - --enable-demuxer=mov \ - --enable-demuxer=vc1 \ - --enable-demuxer=mpegts \ - --enable-demuxer=mpegtsraw \ - --enable-demuxer=mpegps \ - --enable-demuxer=mpegvideo \ - --enable-demuxer=wav \ - --enable-demuxer=pcm_s16be \ - --enable-demuxer=mp3 \ - --enable-demuxer=pcm_s16le \ - --enable-demuxer=matroska \ - --enable-demuxer=flv \ - --enable-demuxer=rm \ - --enable-demuxer=rtsp \ - --enable-demuxer=hls \ - --enable-demuxer=dts \ - --enable-demuxer=wav \ - --enable-demuxer=ogg \ - --enable-demuxer=flac \ - --enable-demuxer=srt \ - --enable-demuxer=hds \ - --enable-demuxer=dash \ - \ - --disable-encoders \ - --disable-muxers \ - --enable-muxer=mpegts \ - \ - --disable-programs \ - --disable-static \ - --disable-filters \ - \ - --enable-librtmp \ - --disable-protocol=data \ - --disable-protocol=cache \ - --disable-protocol=concat \ - --disable-protocol=crypto \ - --disable-protocol=ftp \ - --disable-protocol=gopher \ - --disable-protocol=httpproxy \ - --disable-protocol=pipe \ - --disable-protocol=sctp \ - --disable-protocol=srtp \ - --disable-protocol=subfile \ - --disable-protocol=unix \ - --disable-protocol=md5 \ - --disable-protocol=hls \ - --enable-openssl \ - --enable-protocol=file \ - --enable-protocol=http \ - --enable-protocol=https \ - --enable-protocol=rtmp \ - --enable-protocol=rtmpe \ - --enable-protocol=rtmps \ - --enable-protocol=rtmpte \ - --enable-protocol=mmsh \ - --enable-protocol=mmst \ - --enable-protocol=rtp \ - --enable-protocol=tcp \ - --enable-protocol=udp \ - --enable-bsfs \ - --disable-devices \ - --enable-swresample \ - --disable-postproc \ - --disable-swscale \ - --disable-mmx \ - --disable-altivec \ - --enable-network \ - --enable-cross-compile \ - --enable-shared \ - --enable-small \ - --disable-bzlib \ - --enable-zlib \ - --disable-xlib \ - --enable-libxml2 \ - --disable-debug \ - --enable-stripping \ - --enable-decoder=h264 \ - --enable-decoder=vc1 \ - --target-os=linux \ - --disable-neon \ - --disable-runtime-cpudetect \ - --arch=arm -endif # ifeq ($(BOXARCH), arm) - -ifeq ($(PLATFORM), $(filter $(PLATFORM), apollo kronos)) -FFMPEG_CONFIGURE += --cpu=cortex-a9 --enable-vfp --extra-cflags="-mfpu=vfpv3-d16 -mfloat-abi=hard -I$(TARGETPREFIX)/include" -else -FFMPEG_CONFIGURE += --disable-iconv -FFMPEG_CONFIGURE += --cpu=armv6 --disable-vfp --extra-cflags="-I$(TARGETPREFIX)/include" -endif -$(D)/ffmpeg: $(D)/libxml2 $(D)/librtmp $(D)/libroxml $(ARCHIVE)/ffmpeg-git-$(FFMPEG_GIT).tar.gz | $(TARGETPREFIX) - $(START_BUILD) - $(REMOVE)/ffmpeg-git-$(FFMPEG_GIT) - $(UNTAR)/ffmpeg-git-$(FFMPEG_GIT).tar.gz - set -e; pushd $(BUILD_TMP)/ffmpeg-git-$(FFMPEG_GIT) && \ - $(PATCH)/ffmpeg/0001-ffmpeg-hds-libroxml-3.x.patch; \ - $(PATCH)/ffmpeg/0002-ffmpeg-aac-3.x.patch; \ - $(PATCH)/ffmpeg/0003-ffmpeg-increase-IO-BUFFER-SIZE-to-128k.patch; \ - $(PATCH)/ffmpeg/0003-Revert-libavformat-aviobuf-keep-track-of-the-original-buffer-size-and-restore-it-after.patch; \ - $(PATCH)/ffmpeg/0004-FFmpeg-devel-v14*.patch; \ - $(PATCH)/ffmpeg/0005-ffmpeg-fix-pts-for-cooli.patch; \ - $(PATCH)/ffmpeg/0006-ffmpeg-fix-sps-pps-for-cooli.patch; \ - $(PATCH)/ffmpeg/0007-ffmpeg-reset-compressed-header-flag.patch; \ - $(PATCH)/ffmpeg/0008-add-ASF-VC1-Annex-G-and-RCV-bitstream-filters.-Origi.patch; \ - $(BUILDENV) \ - ./configure \ - $(FFMPEG_CONFIGURE) \ - --extra-ldflags="-L$(TARGETPREFIX)/lib -lz" \ - --logfile=$(BUILD_TMP)/Config-ffmpeg-$(FFMPEG_GIT).log \ - --cross-prefix=$(TARGET)- \ - --prefix=$(TARGETPREFIX) \ - --mandir=/.remove; \ - $(MAKE) && \ - $(MAKE) install - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavfilter.pc - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavdevice.pc - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavformat.pc - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavcodec.pc - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libavutil.pc - $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/libswresample.pc - $(REMOVE)/ffmpeg-git-$(FFMPEG_GIT) $(TARGETPREFIX)/.remove - $(TOUCH) - $(D)/libroxml: $(ARCHIVE)/libroxml-$(LIBROXML_VER).tar.gz | $(TARGETPREFIX) $(START_BUILD) $(UNTAR)/libroxml-$(LIBROXML_VER).tar.gz @@ -602,6 +456,10 @@ $(D)/libroxml: $(ARCHIVE)/libroxml-$(LIBROXML_VER).tar.gz | $(TARGETPREFIX) $(REMOVE)/libroxml-$(LIBROXML_VER) $(TOUCH) +DVBSI_CPPFLAG = +ifeq ($(BOXSERIES), hd2) +DVBSI_CPPFLAG = "-D_GLIBCXX_USE_CXX11_ABI=0" +endif $(D)/libdvbsi++: $(ARCHIVE)/libdvbsi++-$(LIBDVBSI_GIT).tar.bz2 | $(TARGETPREFIX) $(START_BUILD) $(UNTAR)/libdvbsi++-$(LIBDVBSI_GIT).tar.bz2 @@ -609,7 +467,7 @@ $(D)/libdvbsi++: $(ARCHIVE)/libdvbsi++-$(LIBDVBSI_GIT).tar.bz2 | $(TARGETPREFIX) $(PATCH)/libdvbsi++-src-time_date_section.cpp-fix-sectionLength-check.patch; \ $(PATCH)/libdvbsi++-fix-unaligned-access-on-SuperH.patch; \ $(PATCH)/libdvbsi++-content_identifier_descriptor.patch; \ - $(CONFIGURE) CPPFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" \ + $(CONFIGURE) CPPFLAGS=$(DVBSI_CPPFLAG) \ --prefix=$(TARGETPREFIX) \ --build=$(BUILD) \ --host=$(TARGET); \ diff --git a/make/multimedia.mk b/make/multimedia.mk index 90bd3c5..dff31e0 100755 --- a/make/multimedia.mk +++ b/make/multimedia.mk @@ -144,21 +144,37 @@ $(D)/libsdl-mixer: $(D)/libsdl $(ARCHIVE)/SDL_mixer-1.2.11.tar.gz | $(TARGETPREF $(REMOVE)/SDL_mixer-1.2.11 $(TOUCH) -$(D)/libalsa: $(ARCHIVE)/alsa-lib-1.0.12.tar.gz | $(TARGETPREFIX) +$(D)/alsa-lib: $(ARCHIVE)/alsa-lib-$(ALSA_LIB_VER).tar.bz2 $(START_BUILD) - $(UNTAR)/alsa-lib-1.0.12.tar.gz - pushd $(BUILD_TMP)/alsa-lib-1.0.12 && \ - $(CONFIGURE) --prefix=$(TARGETPREFIX) \ - --build=$(BUILD) \ - --host=$(TARGET) \ - --enable-shared=yes && \ - $(MAKE) && \ - $(MAKE) install && \ - rm -rf $(TARGETPREFIX)/man - $(REMOVE)/alsa-lib-1.0.12 + $(UNTAR)/alsa-lib-$(ALSA_LIB_VER).tar.bz2 + set -e; cd $(BUILD_TMP)/alsa-lib-$(ALSA_LIB_VER); \ + $(PATCH)/alsa-lib-$(ALSA_LIB_VER).patch; \ + $(PATCH)/alsa-lib-$(ALSA_LIB_VER)-link_fix.patch; \ + $(CONFIGURE) \ + --prefix= \ + --datarootdir=/.remove \ + --with-alsa-devdir=/dev/snd/ \ + --with-plugindir=/lib/alsa \ + --without-debug \ + --with-debug=no \ + --with-versioned=no \ + --enable-symbolic-functions \ + --disable-aload \ + --disable-rawmidi \ + --disable-resmgr \ + --disable-old-symbols \ + --disable-alisp \ + --disable-hwdep \ + --disable-python \ + ; \ + $(MAKE); \ + $(MAKE) install DESTDIR=$(TARGETPREFIX) + $(REWRITE_PKGCONF) $(PKG_CONFIG_PATH)/alsa.pc + $(REWRITE_LIBTOOL)/libasound.la + $(REMOVE)/alsa-lib-$(ALSA_LIB_VER) $(TOUCH) -$(D)/libalsa-utils: $(D)/libalsa $(ARCHIVE)/alsa-utils-1.0.12.tar.gz | $(TARGETPREFIX) +$(D)/libalsa-utils: $(D)/alsa-lib $(ARCHIVE)/alsa-utils-1.0.12.tar.gz | $(TARGETPREFIX) $(START_BUILD) $(UNTAR)/alsa-utils-1.0.12.tar.gz pushd $(BUILD_TMP)/alsa-utils-1.0.12 && \ diff --git a/make/neutrino.mk b/make/neutrino.mk index 34b4c01..e659ca6 100755 --- a/make/neutrino.mk +++ b/make/neutrino.mk @@ -1,6 +1,9 @@ #Makefile to build NEUTRINO -N_CFLAGS = -Wall -Werror -Wextra -Wshadow -Wsign-compare +N_CFLAGS = -Wall -Wextra -Wshadow -Wsign-compare +ifeq ($(BOXTYPE), coolstream) +N_CFLAGS += -Werror +endif N_CFLAGS += -O2 N_CFLAGS += -fmax-errors=10 @@ -18,12 +21,6 @@ else N_CFLAGS += endif -ifeq ($(BOXMODEL), $(filter $(BOXMODEL), zee2 link)) -HW_TYPE = --with-boxmodel=apollo -else -HW_TYPE = --with-boxmodel=$(PLATFORM) -endif - N_CFLAGS += -I$(TARGETPREFIX)/include N_CFLAGS += -I$(NEUTRINO_OBJDIR) N_CFLAGS += -I$(NEUTRINO_OBJDIR)/src/gui @@ -64,24 +61,32 @@ N_BUILDENV = \ # finally we can build outside of the source directory NEUTRINO_OBJDIR = $(BUILD_TMP)/neutrino-hd -# use this if you want to build inside the source dir - but you don't want that ;) -# NEUTRINO_OBJDIR = $(SOURCE_DIR)/neutrino-hd +LH_OBJDIR = $(BUILD_TMP)/LIBSTB_HAL AUDIODEC = ffmpeg ifeq ($(AUDIODEC), ffmpeg) # enable ffmpeg audio decoder in neutrino -N_CONFIG_OPTS = --enable-ffmpegdec + N_CONFIG_OPTS = --enable-ffmpegdec else -NEUTRINO_DEPS = libid3tag libmad -N_CONFIG_OPTS = --with-tremor -NEUTRINO_DEPS += libvorbis + NEUTRINO_DEPS = libid3tag libmad + N_CONFIG_OPTS = --with-tremor + NEUTRINO_DEPS += libvorbis # enable FLAC decoder in neutrino -N_CONFIG_OPTS += --enable-flac -NEUTRINO_DEPS += libflac + N_CONFIG_OPTS += --enable-flac + NEUTRINO_DEPS += libflac endif + ifeq ($(PLATFORM), $(filter $(PLATFORM), apollo kronos)) - NEUTRINO_DEPS += libiconv cortex-strings + NEUTRINO_DEPS += libiconv cortex-strings +endif + +N_CONFIGURE_LIBSTB_HAL = +ifeq ($(BOXTYPE), armbox) + NEUTRINO_DEPS += cortex-strings libstb-hal + N_CONFIGURE_LIBSTB_HAL += \ + --with-stb-hal-includes=$(LH_OBJDIR)/include \ + --with-stb-hal-build=$(LH_OBJDIR) endif neutrino-deps: $(NEUTRINO_DEPS) @@ -97,17 +102,21 @@ $(D)/neutrino-hd: $(NEUTRINO_OBJDIR)/config.status cp -a $(BUILD_TMP)/neutrino-hd/config.h $(TARGETPREFIX)/include/config.h # touch $@ -$(NEUTRINO_OBJDIR)/config.status: $(NEUTRINO_DEPS) $(D)/neutrino-hd-libs +$(NEUTRINO_OBJDIR)/config.status: $(D)/neutrino-hd-libs $(NEUTRINO_DEPS) test -d $(NEUTRINO_OBJDIR) || mkdir -p $(NEUTRINO_OBJDIR) $(SOURCE_DIR)/neutrino-hd/autogen.sh pushd $(NEUTRINO_OBJDIR) && \ export PKG_CONFIG=$(PKG_CONFIG) && \ export PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) && \ $(N_BUILDENV) \ - $(SOURCE_DIR)/neutrino-hd/configure --host=$(TARGET) --build=$(BUILD) --prefix= \ - --enable-maintainer-mode --with-target=cdk --with-targetprefix="" \ - --with-boxtype=$(BOXTYPE) \ - --with-boxmodel=$(BOXSERIES) \ + $(SOURCE_DIR)/neutrino-hd/configure \ + --host=$(TARGET) \ + --build=$(BUILD) \ + --prefix= \ + --enable-maintainer-mode \ + --enable-silent-rules \ + \ + $(N_CONFIG_OPTS) \ --enable-freesatepg \ --enable-mdev \ --enable-pip \ @@ -115,7 +124,49 @@ $(NEUTRINO_OBJDIR)/config.status: $(NEUTRINO_DEPS) $(D)/neutrino-hd-libs --enable-giflib \ --enable-pugixml \ --enable-fribidi \ - $(N_CONFIG_OPTS) + \ + $(N_CONFIGURE_LIBSTB_HAL) \ + --with-target=cdk \ + --with-targetprefix="" \ + --with-boxtype=$(BOXTYPE) \ + --with-boxmodel=$(BOXSERIES) + +$(LH_OBJDIR)/config.status: $(LH_DEPS) + rm -rf $(LH_OBJDIR) + tar -C $(SOURCE_DIR)/git -cp LIBSTB_HAL --exclude-vcs | tar -C $(BUILD_TMP) -x; + pushd $(LH_OBJDIR) && \ + ./autogen.sh && \ + \ + export PKG_CONFIG=$(PKG_CONFIG) && \ + export PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) && \ + $(N_BUILDENV) \ + ./configure \ + --host=$(TARGET) \ + --build=$(BUILD) \ + --prefix= \ + --enable-maintainer-mode \ + --enable-silent-rules \ + --enable-shared=no \ + \ + $(LH_CONFIGURE_GSTREAMER) \ + \ + --with-target=cdk \ + --with-boxtype=$(BOXMODEL) + +$(D)/libstb-hal: $(LH_OBJDIR)/config.status + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ + $(MAKE) -C $(LH_OBJDIR) all DESTDIR=$(TARGETPREFIX) + $(MAKE) -C $(LH_OBJDIR) install DESTDIR=$(TARGETPREFIX) + $(REWRITE_LIBTOOL)/libstb-hal.la + touch $@ + +libstb-hal-clean: + -make -C $(LH_OBJDIR) clean + -rm $(LH_OBJDIR)/config.status + -rm $(D)/libstb-hal + +libstb-hal-clean-all: libstb-hal-clean + -rm -r $(LH_OBJDIR) neutrino-version: $(TARGETPREFIX)/bin/neutrino if [ -e $(BASE_DIR)/customize/version.sh ]; then \ @@ -137,7 +188,8 @@ $(D)/neutrino-hd-libs: $(START_BUILD) $(MAKE) $(D)/libsigc $(D)/giflib $(D)/openssl \ $(D)/libcurl $(D)/freetype $(D)/libjpeg \ - $(D)/libdvbsi++ $(D)/pugixml $(D)/ffmpeg \ + $(D)/libdvbsi++ $(D)/pugixml $(D)/alsa-lib $(D)/ffmpeg \ $(D)/libbluray $(D)/libopenthreads $(D)/libusb $(D)/libfribidi \ $(D)/luaposix $(D)/luacurl $(D)/luasocket $(D)/lua-expat $(D)/lua-feedparser $(TOUCH) + diff --git a/make/prerequisites.mk b/make/prerequisites.mk index 45dd965..12865d0 100755 --- a/make/prerequisites.mk +++ b/make/prerequisites.mk @@ -38,6 +38,20 @@ $(SOURCE_DIR)/neutrino-hd: fi; \ fi +$(GIT_LIBSTB_HAL): + mkdir -p $(SOURCE_DIR)/git + cd $(SOURCE_DIR)/git && \ + if [ -d $(GIT_LIBSTB_HAL)/ ]; then \ + cd $(GIT_LIBSTB_HAL) && \ + git checkout mpx; \ + git pull origin mpx; \ + else \ + cd $(SOURCE_DIR)/git; \ + git clone $(CSGIT)/$(REPO_LIBSTB_HAL) LIBSTB_HAL; \ + cd $(GIT_LIBSTB_HAL) && \ + git checkout mpx; \ + fi + $(GIT_BOOTLOADER): mkdir -p $(SOURCE_DIR)/git cd $(SOURCE_DIR)/git && \ @@ -107,6 +121,7 @@ $(GIT_PLUGINS): # hack to make sure they are always copied PHONY += $(SOURCE_DIR)/neutrino-hd +PHONY += $(GIT_LIBSTB_HAL) PHONY += $(GIT_BOOTLOADER) PHONY += $(GIT_DRIVERS_THIRDPARTY) PHONY += $(GIT_DRIVERS) diff --git a/make/versions.mk b/make/versions.mk index b236688..0650c3b 100644 --- a/make/versions.mk +++ b/make/versions.mk @@ -1,3 +1,5 @@ +# The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI functionality to the Linux operating system. +ALSA_LIB_VER = 1.1.5 AUTOFS4_VER = 4.1.4 @@ -45,7 +47,11 @@ EXPAT_VER = 2.2.0 FBSHOT_VER = 0.3 # FFMPEG-3.3 | A complete, cross-platform solution to record, convert and stream audio and video +ifeq ($(BOXTYPE), armbox) +FFMPEG_VER = 3.4.2 +else FFMPEG_GIT = 2ba896f +endif # FLEX (the fast lexical analyser) FLEX_VER=2.5.35 @@ -65,6 +71,9 @@ INADYN_VER=02.28.10 # libjpeg-turbo; a derivative of libjpeg for x86 and x86-64 processors which uses SIMD instructions (MMX, SSE2, etc.) to accelerate baseline JPEG compression and decompression JPEG_TURBO_VER = 1.5.2 +# libass is a portable subtitle renderer for the ASS/SSA (Advanced Substation Alpha/Substation Alpha) subtitle format. +LIBASS_VER=0.14.0 + # libdvbsi++; libdvbsi++ is a open source C++ library for parsing DVB Service Information and MPEG-2 Program Specific Information. LIBDVBSI_GIT=ff57e5