include make/drivers.mk
 include make/flashimage.mk
 include make/cleantargets.mk
+include make/ffmpeg.mk
 
 ############################################################################
 #  a print out of environment variables
        @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:"
 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
 
        @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
 # neutrino.mk
 neutrino:
        $(MAKE) $(D)/neutrino-hd
+
 neutrino-libs:
        $(MAKE) $(D)/neutrino-hd-libs
 
 PHONY += applications
 PHONY += multimedia
 PHONY += plugins
-PHONY += kernel
-PHONY += bootloader
-PHONY += drivers
+#PHONY += kernel
+#PHONY += bootloader
+#PHONY += drivers
 .PHONY: $(PHONY)
 
--- /dev/null
+--- 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)
 
--- /dev/null
+--- 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
 
--- /dev/null
+--- 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;
 
--- /dev/null
+--- 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;
+ 
 
--- /dev/null
+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)
 
--- /dev/null
+--- 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 <stdarg.h>
+ 
+-#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)
+ {
 
--- /dev/null
+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);
 
--- /dev/null
+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
 
--- /dev/null
+--- 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
 
--- /dev/null
+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) {
 
--- /dev/null
+--- 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];
 
--- /dev/null
+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;
+ }
 
--- /dev/null
+--- 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}
+ };
+ 
 
--- /dev/null
+--- 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;
 
 # 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
 #
 
 # 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
 
 $(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); \
 
                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)
 
 
 $(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 \
 
   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
 
   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
 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
 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
 
--- /dev/null
+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)
+
 
                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 && \
        $(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
        $(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
        $(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
                $(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); \
 
        $(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 && \
 
 #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
 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
 
 # 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)
        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 \
                        --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 \
        $(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)
+
 
                        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 && \
 
 # 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)
 
+# 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
 
 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
 # 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