]> git.webhop.me Git - bs-cst-neutrino-hd.git/commitdiff
armbox: bump version ffmpeg-4.0.3
authorMarkham <markham001@gmx.de>
Sun, 4 Nov 2018 15:58:30 +0000 (16:58 +0100)
committerMarkham <markham001@gmx.de>
Sun, 4 Nov 2018 15:58:30 +0000 (16:58 +0100)
19 files changed:
archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch [deleted file]
archive-patches/ffmpeg/ffmpeg-4.0.3-allow_to_choose_rtmp_impl_at_runtime.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-fix_edit_list_parsing.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-fix_hls.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-fix_mpegts.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-hls_replace_key_uri.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-increase_buffer_size.patch [new file with mode: 0644]
archive-patches/ffmpeg/ffmpeg-4.0.3-optimize_aac.patch [new file with mode: 0644]
make/ffmpeg.mk
make/versions.mk

diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-aac.patch
deleted file mode 100644 (file)
index 7bab442..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/libavcodec/aacdec_template.c
-+++ b/libavcodec/aacdec_template.c
-@@ -2453,7 +2453,7 @@
-  * @param   decode  1 if tool is used normally, 0 if tool is used in LTP.
-  * @param   coef    spectral coefficients
-  */
--static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
-+static __attribute__((optimize(0))) void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
-                       IndividualChannelStream *ics, int decode)
- {
-     const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
---- a/libavcodec/mdct_template.c
-+++ b/libavcodec/mdct_template.c
-@@ -102,7 +102,7 @@ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale)
-  * @param output N/2 samples
-  * @param input N/2 samples
-  */
--void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input)
-+void __attribute__((optimize(0))) ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input)
- {
-     int k, n8, n4, n2, n, j;
-     const uint16_t *revtab = s->revtab;
---- a/libavcodec/aacps.c
-+++ b/libavcodec/aacps.c
-@@ -659,7 +659,7 @@
-     par[ 1] = AAC_HALF_SUM(par[ 0], par[ 1]);
- }
--static void decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34)
-+static void __attribute__((optimize(0))) decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34)
- {
-     LOCAL_ALIGNED_16(INTFLOAT, power, [34], [PS_QMF_TIME_SLOTS]);
-     LOCAL_ALIGNED_16(INTFLOAT, transient_gain, [34], [PS_QMF_TIME_SLOTS]);
---- a/libavcodec/fft_template.c
-+++ b/libavcodec/fft_template.c
-@@ -536,7 +536,7 @@
-     pass(z,FFT_NAME(ff_cos_##n),n4/2);\
- }
--static void fft4(FFTComplex *z)
-+static void __attribute__((optimize(0))) fft4(FFTComplex *z)
- {
-     FFTDouble t1, t2, t3, t4, t5, t6, t7, t8;
-@@ -550,7 +550,7 @@
-     BF(z[2].im, z[0].im, t2, t5);
- }
--static void fft8(FFTComplex *z)
-+static void __attribute__((optimize(0))) fft8(FFTComplex *z)
- {
-     FFTDouble t1, t2, t3, t4, t5, t6;
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-allow_to_choose_rtmp_impl_at_runtime.patch
deleted file mode 100644 (file)
index 914f841..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-diff -uNr ffmpeg-3.4.2/configure ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/configure
---- ffmpeg-3.4.2/configure     2018-02-12 01:29:18.000000000 +0100
-+++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/configure        2018-02-14 21:07:28.278640757 +0100
-@@ -3128,10 +3128,8 @@
- # protocols
- async_protocol_deps="threads"
- bluray_protocol_deps="libbluray"
--ffrtmpcrypt_protocol_conflict="librtmp_protocol"
- ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl"
- ffrtmpcrypt_protocol_select="tcp_protocol"
--ffrtmphttp_protocol_conflict="librtmp_protocol"
- ffrtmphttp_protocol_select="http_protocol"
- ftp_protocol_select="tcp_protocol"
- gopher_protocol_select="network"
-@@ -3148,14 +3146,12 @@
- libssh_protocol_deps="libssh"
- mmsh_protocol_select="http_protocol"
- mmst_protocol_select="network"
--rtmp_protocol_conflict="librtmp_protocol"
--rtmp_protocol_select="tcp_protocol"
--rtmpe_protocol_select="ffrtmpcrypt_protocol"
--rtmps_protocol_conflict="librtmp_protocol"
--rtmps_protocol_select="tls_protocol"
--rtmpt_protocol_select="ffrtmphttp_protocol"
--rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol"
--rtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
-+ffrtmp_protocol_select="tcp_protocol"
-+ffrtmpe_protocol_select="ffrtmpcrypt_protocol"
-+ffrtmps_protocol_select="tls_protocol"
-+ffrtmpt_protocol_select="ffrtmphttp_protocol"
-+ffrtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol"
-+ffrtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
- rtp_protocol_select="udp_protocol"
- sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags"
- sctp_protocol_select="network"
-diff -uNr ffmpeg-3.4.2/libavformat/Makefile ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/Makefile
---- ffmpeg-3.4.2/libavformat/Makefile  2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/Makefile     2018-02-14 20:10:19.763205912 +0100
-@@ -575,12 +575,12 @@
- OBJS-$(CONFIG_MMST_PROTOCOL)             += mmst.o mms.o asf.o
- OBJS-$(CONFIG_PIPE_PROTOCOL)             += file.o
- OBJS-$(CONFIG_PROMPEG_PROTOCOL)          += prompeg.o
--OBJS-$(CONFIG_RTMP_PROTOCOL)             += rtmpproto.o rtmppkt.o
--OBJS-$(CONFIG_RTMPE_PROTOCOL)            += rtmpproto.o rtmppkt.o
--OBJS-$(CONFIG_RTMPS_PROTOCOL)            += rtmpproto.o rtmppkt.o
--OBJS-$(CONFIG_RTMPT_PROTOCOL)            += rtmpproto.o rtmppkt.o
--OBJS-$(CONFIG_RTMPTE_PROTOCOL)           += rtmpproto.o rtmppkt.o
--OBJS-$(CONFIG_RTMPTS_PROTOCOL)           += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMP_PROTOCOL)           += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMPE_PROTOCOL)          += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMPS_PROTOCOL)          += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMPT_PROTOCOL)          += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMPTE_PROTOCOL)         += rtmpproto.o rtmppkt.o
-+OBJS-$(CONFIG_FFRTMPTS_PROTOCOL)         += rtmpproto.o rtmppkt.o
- OBJS-$(CONFIG_RTP_PROTOCOL)              += rtpproto.o
- OBJS-$(CONFIG_SCTP_PROTOCOL)             += sctp.o
- OBJS-$(CONFIG_SRTP_PROTOCOL)             += srtpproto.o srtp.o
-diff -uNr ffmpeg-3.4.2/libavformat/protocols.c ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/protocols.c
---- ffmpeg-3.4.2/libavformat/protocols.c       2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/protocols.c  2018-02-14 20:12:01.235570344 +0100
-@@ -44,12 +44,12 @@
- extern const URLProtocol ff_md5_protocol;
- extern const URLProtocol ff_pipe_protocol;
- extern const URLProtocol ff_prompeg_protocol;
--extern const URLProtocol ff_rtmp_protocol;
--extern const URLProtocol ff_rtmpe_protocol;
--extern const URLProtocol ff_rtmps_protocol;
--extern const URLProtocol ff_rtmpt_protocol;
--extern const URLProtocol ff_rtmpte_protocol;
--extern const URLProtocol ff_rtmpts_protocol;
-+extern const URLProtocol ff_ffrtmp_protocol;
-+extern const URLProtocol ff_ffrtmpe_protocol;
-+extern const URLProtocol ff_ffrtmps_protocol;
-+extern const URLProtocol ff_ffrtmpt_protocol;
-+extern const URLProtocol ff_ffrtmpte_protocol;
-+extern const URLProtocol ff_ffrtmpts_protocol;
- extern const URLProtocol ff_rtp_protocol;
- extern const URLProtocol ff_sctp_protocol;
- extern const URLProtocol ff_srtp_protocol;
-diff -uNr ffmpeg-3.4.2/libavformat/rtmpproto.c ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/rtmpproto.c
---- ffmpeg-3.4.2/libavformat/rtmpproto.c       2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_allow_to_choose_rtmp_impl_at_runtime/libavformat/rtmpproto.c  2018-02-14 20:21:41.701280041 +0100
-@@ -2626,7 +2626,7 @@
- static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
- {
-     RTMPContext *rt = s->priv_data;
--    char proto[8], hostname[256], path[1024], auth[100], *fname;
-+    char *proto, tmpProto[10], hostname[256], path[1024], auth[100], *fname;
-     char *old_app, *qmark, *n, fname_buffer[1024];
-     uint8_t buf[2048];
-     int port;
-@@ -2637,7 +2637,9 @@
-     rt->is_input = !(flags & AVIO_FLAG_WRITE);
--    av_url_split(proto, sizeof(proto), auth, sizeof(auth),
-+    memset(tmpProto, 0, sizeof(tmpProto)); 
-+    proto = &tmpProto[2];
-+    av_url_split(tmpProto, sizeof(tmpProto), auth, sizeof(auth),
-                  hostname, sizeof(hostname), &port,
-                  path, sizeof(path), s->filename);
-@@ -3171,9 +3173,9 @@
- };
--RTMP_PROTOCOL(rtmp)
--RTMP_PROTOCOL(rtmpe)
--RTMP_PROTOCOL(rtmps)
--RTMP_PROTOCOL(rtmpt)
--RTMP_PROTOCOL(rtmpte)
--RTMP_PROTOCOL(rtmpts)
-+RTMP_PROTOCOL(ffrtmp)
-+RTMP_PROTOCOL(ffrtmpe)
-+RTMP_PROTOCOL(ffrtmps)
-+RTMP_PROTOCOL(ffrtmpt)
-+RTMP_PROTOCOL(ffrtmpte)
-+RTMP_PROTOCOL(ffrtmpts)
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-buffer-size.patch
deleted file mode 100644 (file)
index bf465aa..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
---- 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)
- {
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-chunked_transfer_fix_eof.patch
deleted file mode 100644 (file)
index 99ac875..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -uNr ffmpeg-3.4.2/libavformat/http.c ffmpeg-3.4.2_chunked_transfer_fix_eof/libavformat/http.c
---- ffmpeg-3.4.2/libavformat/http.c    2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_chunked_transfer_fix_eof/libavformat/http.c   2018-02-14 19:56:02.371892777 +0100
-@@ -1296,8 +1296,11 @@
-                    "Chunked encoding data size: %"PRIu64"'\n",
-                     s->chunksize);
--            if (!s->chunksize)
-+            if (!s->chunksize) {
-+                /* we need to remember endof*/
-+                s->chunksize = UINT64_MAX;
-                 return 0;
-+            }
-             else if (s->chunksize == UINT64_MAX) {
-                 av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
-                        s->chunksize);
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-dashdec_improvements.patch
deleted file mode 100644 (file)
index 42dbf1a..0000000
+++ /dev/null
@@ -1,1565 +0,0 @@
-diff -uNr ffmpeg-3.4.2/libavformat/dashdec.c ffmpeg-3.4.2_dashdec/libavformat/dashdec.c
---- ffmpeg-3.4.2/libavformat/dashdec.c 2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_dashdec/libavformat/dashdec.c 2018-02-15 19:43:08.889757019 +0100
-@@ -39,7 +39,7 @@
- /*
-  * reference to : ISO_IEC_23009-1-DASH-2012
-  * Section: 5.3.9.6.2
-- * Table: Table 17 — Semantics of SegmentTimeline element
-+ * Table: Table 17 â€” Semantics of SegmentTimeline element
-  * */
- struct timeline {
-     /* starttime: Element or Attribute Name
-@@ -80,10 +80,13 @@
-     AVFormatContext *ctx;
-     AVPacket pkt;
-     int rep_idx;
--    int rep_count;
-     int stream_index;
-     enum AVMediaType type;
-+    char id[20];
-+    int bandwidth;
-+    AVRational framerate;
-+    AVStream *assoc_stream; /* demuxer stream associated with this representation */
-     int n_fragments;
-     struct fragment **fragments; /* VOD list of fragment for profile */
-@@ -113,13 +116,32 @@
-     uint32_t init_sec_buf_read_offset;
-     int64_t cur_timestamp;
-     int is_restart_needed;
-+    
-+    /* used for live stream were each fragment starts with 
-+     * 0 pts, so we need to 
-+     */
-+    int64_t pkt_start_time_offset;
-+    int is_first_pkt;
- };
- typedef struct DASHContext {
-     const AVClass *class;
-     char *base_url;
--    struct representation *cur_video;
--    struct representation *cur_audio;
-+
-+    int n_videos;
-+    struct representation **videos;
-+    int n_audios;
-+    struct representation **audios;
-+    
-+    /* Temporary variables used during manifest parsing */
-+    int tmp_video_rep_idx;
-+    int tmp_audio_rep_idx;
-+    
-+    /* Used to force using selected representation */ 
-+    int video_rep_index;
-+    int audio_rep_index;
-+    
-+    int64_t last_load_time;
-     /* MediaPresentationDescription Attribute */
-     uint64_t media_presentation_duration;
-@@ -141,8 +163,34 @@
-     char *headers;                       ///< holds HTTP headers set as an AVOption to the HTTP protocol context
-     char *allowed_extensions;
-     AVDictionary *avio_opts;
-+    int max_url_size;
- } DASHContext;
-+static int sleep_ms(DASHContext *c, uint32_t time_ms)
-+{
-+    int ret = 0;
-+    int64_t start_time = av_gettime_relative();
-+    do {
-+        if (ff_check_interrupt(c->interrupt_callback)) {
-+            ret = 1;
-+            break;
-+        }
-+        av_usleep(100*1000);
-+    } while (av_gettime_relative() - start_time < (time_ms*1000));
-+    return ret;
-+}
-+
-+static int ishttp(char *url)
-+{
-+    const char *proto_name = avio_find_protocol_name(url);
-+    return av_strstart(proto_name, "http", NULL);
-+}
-+
-+static int aligned(int val)
-+{
-+    return ((val + 0x3F) >> 6) << 6;
-+}
-+
- static uint64_t get_current_time_in_sec(void)
- {
-     return  av_gettime() / 1000000;
-@@ -328,17 +376,39 @@
-     }
-     av_freep(&pls->url_template);
--    av_freep(pls);
-+    av_freep(&pls);
-+}
-+
-+static void free_video_list(DASHContext *c)
-+{
-+    int i;
-+    for (i = 0; i < c->n_videos; i++) {
-+        struct representation *pls = c->videos[i];
-+        free_representation(pls);
-+    }
-+    av_freep(&c->videos);
-+    c->n_videos = 0;
- }
--static void set_httpheader_options(DASHContext *c, AVDictionary *opts)
-+static void free_audio_list(DASHContext *c)
-+{
-+    int i;
-+    for (i = 0; i < c->n_audios; i++) {
-+        struct representation *pls = c->audios[i];
-+        free_representation(pls);
-+    }
-+    av_freep(&c->audios);
-+    c->n_audios = 0;
-+}
-+
-+static void set_httpheader_options(DASHContext *c, AVDictionary **opts)
- {
-     // broker prior HTTP options that should be consistent across requests
--    av_dict_set(&opts, "user-agent", c->user_agent, 0);
--    av_dict_set(&opts, "cookies", c->cookies, 0);
--    av_dict_set(&opts, "headers", c->headers, 0);
-+    av_dict_set(opts, "user-agent", c->user_agent, 0);
-+    av_dict_set(opts, "cookies", c->cookies, 0);
-+    av_dict_set(opts, "headers", c->headers, 0);
-     if (c->is_live) {
--        av_dict_set(&opts, "seekable", "0", 0);
-+        av_dict_set(opts, "seekable", "0", 0);
-     }
- }
- static void update_options(char **dest, const char *name, void *src)
-@@ -392,7 +462,8 @@
-     else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
-         return AVERROR_INVALIDDATA;
--    ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
-+    av_freep(pb);
-+    ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
-     if (ret >= 0) {
-         // update cookies on http response with setcookies.
-         char *new_cookies = NULL;
-@@ -418,6 +489,7 @@
- static char *get_content_url(xmlNodePtr *baseurl_nodes,
-                              int n_baseurl_nodes,
-+                             int max_url_size,
-                              char *rep_id_val,
-                              char *rep_bandwidth_val,
-                              char *val)
-@@ -425,10 +497,12 @@
-     int i;
-     char *text;
-     char *url = NULL;
--    char tmp_str[MAX_URL_SIZE];
--    char tmp_str_2[MAX_URL_SIZE];
-+    char *tmp_str = av_mallocz(max_url_size);
-+    char *tmp_str_2 = av_mallocz(max_url_size);
--    memset(tmp_str, 0, sizeof(tmp_str));
-+    if (!tmp_str || !tmp_str_2) {
-+        return NULL;
-+    }
-     for (i = 0; i < n_baseurl_nodes; ++i) {
-         if (baseurl_nodes[i] &&
-@@ -436,32 +510,36 @@
-             baseurl_nodes[i]->children->type == XML_TEXT_NODE) {
-             text = xmlNodeGetContent(baseurl_nodes[i]->children);
-             if (text) {
--                memset(tmp_str, 0, sizeof(tmp_str));
--                memset(tmp_str_2, 0, sizeof(tmp_str_2));
--                ff_make_absolute_url(tmp_str_2, MAX_URL_SIZE, tmp_str, text);
--                av_strlcpy(tmp_str, tmp_str_2, sizeof(tmp_str));
-+                memset(tmp_str, 0, max_url_size);
-+                memset(tmp_str_2, 0, max_url_size);
-+                ff_make_absolute_url(tmp_str_2, max_url_size, tmp_str, text);
-+                av_strlcpy(tmp_str, tmp_str_2, max_url_size);
-                 xmlFree(text);
-             }
-         }
-     }
-     if (val)
--        av_strlcat(tmp_str, (const char*)val, sizeof(tmp_str));
-+        av_strlcat(tmp_str, (const char*)val, max_url_size);
-     if (rep_id_val) {
-         url = av_strireplace(tmp_str, "$RepresentationID$", (const char*)rep_id_val);
-         if (!url) {
--            return NULL;
-+            goto end;
-         }
--        av_strlcpy(tmp_str, url, sizeof(tmp_str));
--        av_free(url);
-+        av_strlcpy(tmp_str, url, max_url_size);
-     }
-     if (rep_bandwidth_val && tmp_str[0] != '\0') {
-+        // free any previously assigned url before reassigning
-+        av_free(url);
-         url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val);
-         if (!url) {
--            return NULL;
-+            goto end;
-         }
-     }
-+end:
-+    av_free(tmp_str);
-+    av_free(tmp_str_2);
-     return url;
- }
-@@ -522,55 +600,85 @@
-     return type;
- }
-+static struct fragment * get_Fragment(char *range)
-+{
-+    struct fragment * seg =  av_mallocz(sizeof(struct fragment));
-+
-+    if (!seg)
-+        return NULL;
-+
-+    seg->size = -1;
-+    if (range) {
-+        char *str_end_offset;
-+        char *str_offset = av_strtok(range, "-", &str_end_offset);
-+        seg->url_offset = strtoll(str_offset, NULL, 10);
-+        seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset;
-+    }
-+
-+    return seg;
-+}
-+
- static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representation *rep,
-                                          xmlNodePtr fragmenturl_node,
-                                          xmlNodePtr *baseurl_nodes,
-                                          char *rep_id_val,
-                                          char *rep_bandwidth_val)
- {
-+    DASHContext *c = s->priv_data;
-     char *initialization_val = NULL;
-     char *media_val = NULL;
-+    char *range_val = NULL;
-+    int max_url_size = c ? c->max_url_size: MAX_URL_SIZE;
-     if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) {
-         initialization_val = xmlGetProp(fragmenturl_node, "sourceURL");
--        if (initialization_val) {
--            rep->init_section = av_mallocz(sizeof(struct fragment));
-+        range_val = xmlGetProp(fragmenturl_node, "range");
-+        if (initialization_val || range_val) {
-+            rep->init_section = get_Fragment(range_val);
-             if (!rep->init_section) {
-                 xmlFree(initialization_val);
-+                xmlFree(range_val);
-                 return AVERROR(ENOMEM);
-             }
-             rep->init_section->url = get_content_url(baseurl_nodes, 4,
-+                                                     max_url_size,
-                                                      rep_id_val,
-                                                      rep_bandwidth_val,
-                                                      initialization_val);
-+
-             if (!rep->init_section->url) {
-                 av_free(rep->init_section);
-                 xmlFree(initialization_val);
-+                xmlFree(range_val);
-                 return AVERROR(ENOMEM);
-             }
--            rep->init_section->size = -1;
-             xmlFree(initialization_val);
-+            xmlFree(range_val);
-         }
-     } else if (!av_strcasecmp(fragmenturl_node->name, (const char *)"SegmentURL")) {
-         media_val = xmlGetProp(fragmenturl_node, "media");
--        if (media_val) {
--            struct fragment *seg = av_mallocz(sizeof(struct fragment));
-+        range_val = xmlGetProp(fragmenturl_node, "mediaRange");
-+        if (media_val || range_val) {
-+            struct fragment *seg = get_Fragment(range_val);
-             if (!seg) {
-                 xmlFree(media_val);
-+                xmlFree(range_val);
-                 return AVERROR(ENOMEM);
-             }
-             seg->url = get_content_url(baseurl_nodes, 4,
-+                                       max_url_size,
-                                        rep_id_val,
-                                        rep_bandwidth_val,
-                                        media_val);
-             if (!seg->url) {
-                 av_free(seg);
-                 xmlFree(media_val);
-+                xmlFree(range_val);
-                 return AVERROR(ENOMEM);
-             }
--            seg->size = -1;
-             dynarray_add(&rep->fragments, &rep->n_fragments, seg);
-             xmlFree(media_val);
-+            xmlFree(range_val);
-         }
-     }
-@@ -613,26 +721,155 @@
-     return 0;
- }
-+static int fill_timelines(AVFormatContext *s, struct representation *rep, xmlNodePtr *nodes, const int n_nodes)
-+{
-+    xmlNodePtr fragment_timeline_node;
-+    int ret = 0;
-+    int i = 0;
-+    for (; i < n_nodes; ++i) {
-+        if (nodes[i]) {
-+            
-+            fragment_timeline_node = find_child_node_by_name(nodes[i], "SegmentTimeline");
-+            if (fragment_timeline_node) {
-+                fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
-+                while (fragment_timeline_node) {
-+                    ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node);
-+                    if (ret < 0) {
-+                        return ret;
-+                    }
-+                    fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
-+                }
-+            }
-+        }
-+    }
-+    
-+    return ret;
-+}
-+
-+static int resolve_content_path(AVFormatContext *s, const char *url, int *max_url_size, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
-+
-+    char *tmp_str = NULL;
-+    char *path = NULL;
-+    char *mpdName = NULL;
-+    xmlNodePtr node = NULL;
-+    char *baseurl = NULL;
-+    char *root_url = NULL;
-+    char *text = NULL;
-+
-+    int isRootHttp = 0;
-+    char token ='/';
-+    int start =  0;
-+    int rootId = 0;
-+    int updated = 0;
-+    int size = 0;
-+    int i;
-+    int tmp_max_url_size = strlen(url);
-+
-+    for (i = n_baseurl_nodes-1; i >= 0 ; i--) {
-+        text = xmlNodeGetContent(baseurl_nodes[i]);
-+        if (!text)
-+            continue;
-+        tmp_max_url_size += strlen(text);
-+        if (ishttp(text)) {
-+            xmlFree(text);
-+            break;
-+        }
-+        xmlFree(text);
-+    }
-+
-+    tmp_max_url_size = aligned(tmp_max_url_size);
-+    text = av_mallocz(tmp_max_url_size);
-+    if (!text) {
-+        updated = AVERROR(ENOMEM);
-+        goto end;
-+    }
-+    av_strlcpy(text, url, strlen(url)+1);
-+    while (mpdName = av_strtok(text, "/", &text))  {
-+        size = strlen(mpdName);
-+    }
-+
-+    path = av_mallocz(tmp_max_url_size);
-+    tmp_str = av_mallocz(tmp_max_url_size);
-+    if (!tmp_str || !path) {
-+        updated = AVERROR(ENOMEM);
-+        goto end;
-+    }
-+
-+    av_strlcpy (path, url, strlen(url) - size + 1);
-+    for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
-+        if (!(node = baseurl_nodes[rootId])) {
-+            continue;
-+        }
-+        if (ishttp(xmlNodeGetContent(node))) {
-+            break;
-+        }
-+    }
-+
-+    node = baseurl_nodes[rootId];
-+    baseurl = xmlNodeGetContent(node);
-+    root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
-+    if (node) {
-+        xmlNodeSetContent(node, root_url);
-+        updated = 1;
-+    }
-+
-+    size = strlen(root_url);
-+    isRootHttp = ishttp(root_url);
-+
-+    if (root_url[size - 1] != token) {
-+        av_strlcat(root_url, "/", size + 2);
-+        size += 2;
-+    }
-+
-+    for (i = 0; i < n_baseurl_nodes; ++i) {
-+        if (i == rootId) {
-+            continue;
-+        }
-+        text = xmlNodeGetContent(baseurl_nodes[i]);
-+        if (text) {
-+            memset(tmp_str, 0, strlen(tmp_str));
-+            if (!ishttp(text) && isRootHttp) {
-+                av_strlcpy(tmp_str, root_url, size + 1);
-+            }
-+            start = (text[0] == token);
-+            av_strlcat(tmp_str, text + start, tmp_max_url_size);
-+            xmlNodeSetContent(baseurl_nodes[i], tmp_str);
-+            updated = 1;
-+            xmlFree(text);
-+        }
-+    }
-+
-+end:
-+    if (tmp_max_url_size > *max_url_size) {
-+        *max_url_size = tmp_max_url_size;
-+    }
-+    av_free(path);
-+    av_free(tmp_str);
-+    return updated;
-+
-+}
-+
- static int parse_manifest_representation(AVFormatContext *s, const char *url,
-                                          xmlNodePtr node,
-                                          xmlNodePtr adaptionset_node,
-                                          xmlNodePtr mpd_baseurl_node,
-                                          xmlNodePtr period_baseurl_node,
-+                                         xmlNodePtr period_segmenttemplate_node,
-+                                         xmlNodePtr period_segmentlist_node,
-                                          xmlNodePtr fragment_template_node,
-                                          xmlNodePtr content_component_node,
--                                         xmlNodePtr adaptionset_baseurl_node)
-+                                         xmlNodePtr adaptionset_baseurl_node,
-+                                         xmlNodePtr adaptionset_segmentlist_node)
- {
-     int32_t ret = 0;
--    int32_t audio_rep_idx = 0;
--    int32_t video_rep_idx = 0;
-     DASHContext *c = s->priv_data;
-     struct representation *rep = NULL;
-     struct fragment *seg = NULL;
-     xmlNodePtr representation_segmenttemplate_node = NULL;
-     xmlNodePtr representation_baseurl_node = NULL;
-     xmlNodePtr representation_segmentlist_node = NULL;
--    xmlNodePtr fragment_timeline_node = NULL;
--    xmlNodePtr fragment_templates_tab[2];
-+    xmlNodePtr segmentlists_tab[3];
-+    xmlNodePtr fragment_templates_tab[5];
-     char *duration_val = NULL;
-     char *presentation_timeoffset_val = NULL;
-     char *startnumber_val = NULL;
-@@ -643,6 +880,7 @@
-     xmlNodePtr representation_node = node;
-     char *rep_id_val = xmlGetProp(representation_node, "id");
-     char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth");
-+    char *rep_framerate_val = xmlGetProp(representation_node, "frameRate");
-     enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
-     // try get information from representation
-@@ -656,7 +894,7 @@
-         type = get_content_type(adaptionset_node);
-     if (type == AVMEDIA_TYPE_UNKNOWN) {
-         av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url);
--    } else if ((type == AVMEDIA_TYPE_VIDEO && !c->cur_video) || (type == AVMEDIA_TYPE_AUDIO && !c->cur_audio)) {
-+    } else if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) {
-         // convert selected representation to our internal struct
-         rep = av_mallocz(sizeof(struct representation));
-         if (!rep) {
-@@ -672,17 +910,24 @@
-         baseurl_nodes[2] = adaptionset_baseurl_node;
-         baseurl_nodes[3] = representation_baseurl_node;
--        if (representation_segmenttemplate_node || fragment_template_node) {
--            fragment_timeline_node = NULL;
-+        ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4);
-+        c->max_url_size = aligned(c->max_url_size  + strlen(rep_id_val) + strlen(rep_bandwidth_val));
-+        if (ret == AVERROR(ENOMEM) || ret == 0) {
-+            goto end;
-+        }
-+        if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) {
-             fragment_templates_tab[0] = representation_segmenttemplate_node;
--            fragment_templates_tab[1] = fragment_template_node;
--
--            presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "presentationTimeOffset");
--            duration_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "duration");
--            startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "startNumber");
--            timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "timescale");
--            initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "initialization");
--            media_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "media");
-+            fragment_templates_tab[1] = adaptionset_segmentlist_node;
-+            fragment_templates_tab[2] = fragment_template_node;
-+            fragment_templates_tab[3] = period_segmenttemplate_node;
-+            fragment_templates_tab[4] = period_segmentlist_node;
-+
-+            presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset");
-+            duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration");
-+            startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber");
-+            timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale");
-+            initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization");
-+            media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media");
-             if (initialization_val) {
-                 rep->init_section = av_mallocz(sizeof(struct fragment));
-@@ -691,7 +936,8 @@
-                     ret = AVERROR(ENOMEM);
-                     goto end;
-                 }
--                rep->init_section->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, initialization_val);
-+                c->max_url_size = aligned(c->max_url_size  + strlen(initialization_val));
-+                rep->init_section->url = get_content_url(baseurl_nodes, 4,  c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val);
-                 if (!rep->init_section->url) {
-                     av_free(rep->init_section);
-                     av_free(rep);
-@@ -703,7 +949,8 @@
-             }
-             if (media_val) {
--                rep->url_template = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, media_val);
-+                c->max_url_size = aligned(c->max_url_size  + strlen(media_val));
-+                rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val);
-                 xmlFree(media_val);
-             }
-@@ -719,32 +966,27 @@
-                 rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10);
-                 xmlFree(timescale_val);
-             }
-+            
-+            ret = fill_timelines(s, rep, fragment_templates_tab, 5);
-+            if (ret < 0) {
-+                return ret;
-+            }
-+            
-             if (startnumber_val) {
--                rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10);
-+                if (rep->n_timelines)
-+                    rep->start_number = (int64_t) strtoll(startnumber_val, NULL, 10);
-+                else
-+                    rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10);
-                 xmlFree(startnumber_val);
-             }
--            fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline");
--
--            if (!fragment_timeline_node)
--                fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
--            if (fragment_timeline_node) {
--                fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
--                while (fragment_timeline_node) {
--                    ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node);
--                    if (ret < 0) {
--                        return ret;
--                    }
--                    fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
--                }
--            }
-         } else if (representation_baseurl_node && !representation_segmentlist_node) {
-             seg = av_mallocz(sizeof(struct fragment));
-             if (!seg) {
-                 ret = AVERROR(ENOMEM);
-                 goto end;
-             }
--            seg->url = get_content_url(baseurl_nodes, 4, rep_id_val, rep_bandwidth_val, NULL);
-+            seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL);
-             if (!seg->url) {
-                 av_free(seg);
-                 ret = AVERROR(ENOMEM);
-@@ -756,8 +998,14 @@
-             // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html
-             // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full
-             xmlNodePtr fragmenturl_node = NULL;
--            duration_val = xmlGetProp(representation_segmentlist_node, "duration");
--            timescale_val = xmlGetProp(representation_segmentlist_node, "timescale");
-+            segmentlists_tab[0] = representation_segmentlist_node;
-+            segmentlists_tab[1] = adaptionset_segmentlist_node;
-+            segmentlists_tab[2] = period_segmentlist_node;
-+
-+            duration_val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration");
-+            timescale_val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale");
-+            startnumber_val = get_val_from_nodes_tab(segmentlists_tab, 3, "startNumber");
-+            
-             if (duration_val) {
-                 rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10);
-                 xmlFree(duration_val);
-@@ -766,6 +1014,10 @@
-                 rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10);
-                 xmlFree(timescale_val);
-             }
-+            if (startnumber_val) {
-+                rep->start_number = (int64_t) strtoll(startnumber_val, NULL, 10);
-+                xmlFree(startnumber_val);
-+            }
-             fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node);
-             while (fragmenturl_node) {
-                 ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node,
-@@ -778,19 +1030,9 @@
-                 fragmenturl_node = xmlNextElementSibling(fragmenturl_node);
-             }
--            fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline");
--
--            if (!fragment_timeline_node)
--                fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
--            if (fragment_timeline_node) {
--                fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
--                while (fragment_timeline_node) {
--                    ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node);
--                    if (ret < 0) {
--                        return ret;
--                    }
--                    fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
--                }
-+            ret = fill_timelines(s, rep, segmentlists_tab, 3);
-+            if (ret < 0) {
-+                return ret;
-             }
-         } else {
-             free_representation(rep);
-@@ -801,24 +1043,37 @@
-         if (rep) {
-             if (rep->fragment_duration > 0 && !rep->fragment_timescale)
-                 rep->fragment_timescale = 1;
--            if (type == AVMEDIA_TYPE_VIDEO) {
--                rep->rep_idx = video_rep_idx;
--                c->cur_video = rep;
-+            rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0;
-+            strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id));
-+            rep->framerate = av_make_q(0, 0);
-+            if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) {
-+                ret = av_parse_video_rate(&rep->framerate, rep_framerate_val);
-+                if (ret < 0)
-+                    av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val);
-+            }
-+            if (type == AVMEDIA_TYPE_VIDEO && (c->video_rep_index == -1 || c->video_rep_index == c->tmp_video_rep_idx)) {
-+                rep->rep_idx = c->tmp_video_rep_idx;
-+                dynarray_add(&c->videos, &c->n_videos, rep);
-+            } else if (type == AVMEDIA_TYPE_AUDIO && (c->audio_rep_index == -1 || c->audio_rep_index == c->tmp_audio_rep_idx)) {
-+                rep->rep_idx = c->tmp_audio_rep_idx;
-+                dynarray_add(&c->audios, &c->n_audios, rep);
-             } else {
--                rep->rep_idx = audio_rep_idx;
--                c->cur_audio = rep;
-+                free_representation(rep);
-+                rep = NULL;
-             }
-         }
-     }
--
--    video_rep_idx += type == AVMEDIA_TYPE_VIDEO;
--    audio_rep_idx += type == AVMEDIA_TYPE_AUDIO;
-+    
-+    c->tmp_video_rep_idx += type == AVMEDIA_TYPE_VIDEO;
-+    c->tmp_audio_rep_idx += type == AVMEDIA_TYPE_AUDIO;
- end:
-     if (rep_id_val)
-         xmlFree(rep_id_val);
-     if (rep_bandwidth_val)
-         xmlFree(rep_bandwidth_val);
-+    if (rep_framerate_val)
-+        xmlFree(rep_framerate_val);
-     return ret;
- }
-@@ -826,12 +1081,15 @@
- static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
-                                         xmlNodePtr adaptionset_node,
-                                         xmlNodePtr mpd_baseurl_node,
--                                        xmlNodePtr period_baseurl_node)
-+                                        xmlNodePtr period_baseurl_node,
-+                                        xmlNodePtr period_segmenttemplate_node,
-+                                        xmlNodePtr period_segmentlist_node)
- {
-     int ret = 0;
-     xmlNodePtr fragment_template_node = NULL;
-     xmlNodePtr content_component_node = NULL;
-     xmlNodePtr adaptionset_baseurl_node = NULL;
-+    xmlNodePtr adaptionset_segmentlist_node = NULL;
-     xmlNodePtr node = NULL;
-     node = xmlFirstElementChild(adaptionset_node);
-@@ -842,14 +1100,19 @@
-             content_component_node = node;
-         } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) {
-             adaptionset_baseurl_node = node;
-+        } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) {
-+            adaptionset_segmentlist_node = node;
-         } else if (!av_strcasecmp(node->name, (const char *)"Representation")) {
-             ret = parse_manifest_representation(s, url, node,
-                                                 adaptionset_node,
-                                                 mpd_baseurl_node,
-                                                 period_baseurl_node,
-+                                                period_segmenttemplate_node,
-+                                                period_segmentlist_node,
-                                                 fragment_template_node,
-                                                 content_component_node,
--                                                adaptionset_baseurl_node);
-+                                                adaptionset_baseurl_node,
-+                                                adaptionset_segmentlist_node);
-             if (ret < 0) {
-                 return ret;
-             }
-@@ -874,18 +1137,21 @@
-     xmlNodePtr period_node = NULL;
-     xmlNodePtr mpd_baseurl_node = NULL;
-     xmlNodePtr period_baseurl_node = NULL;
-+    xmlNodePtr period_segmenttemplate_node = NULL;
-+    xmlNodePtr period_segmentlist_node = NULL;
-     xmlNodePtr adaptionset_node = NULL;
-     xmlAttrPtr attr = NULL;
-     char *val  = NULL;
-     uint32_t perdiod_duration_sec = 0;
-     uint32_t perdiod_start_sec = 0;
--    int32_t audio_rep_idx = 0;
--    int32_t video_rep_idx = 0;
-+    
-+    c->tmp_audio_rep_idx = 0;
-+    c->tmp_video_rep_idx = 0;
-     if (!in) {
-         close_in = 1;
--        set_httpheader_options(c, opts);
-+        set_httpheader_options(c, &opts);
-         ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts);
-         av_dict_free(&opts);
-         if (ret < 0)
-@@ -967,6 +1233,9 @@
-         }
-         mpd_baseurl_node = find_child_node_by_name(node, "BaseURL");
-+        if (!mpd_baseurl_node) {
-+            mpd_baseurl_node = xmlNewNode(NULL, "BaseURL");
-+        }
-         // at now we can handle only one period, with the longest duration
-         node = xmlFirstElementChild(node);
-@@ -989,7 +1258,7 @@
-                     period_node = node;
-                     c->period_duration = perdiod_duration_sec;
-                     c->period_start = perdiod_start_sec;
--                    if (c->period_start > 0)
-+                    if (c->period_duration > 0)
-                         c->media_presentation_duration = c->period_duration;
-                 }
-             }
-@@ -1005,19 +1274,15 @@
-         while (adaptionset_node) {
-             if (!av_strcasecmp(adaptionset_node->name, (const char *)"BaseURL")) {
-                 period_baseurl_node = adaptionset_node;
-+            } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) {
-+                period_segmenttemplate_node = adaptionset_node;
-+            } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentList")) {
-+                period_segmentlist_node = adaptionset_node;
-             } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) {
--                parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node);
-+                parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node);
-             }
-             adaptionset_node = xmlNextElementSibling(adaptionset_node);
-         }
--        if (c->cur_video) {
--            c->cur_video->rep_count = video_rep_idx;
--            av_log(s, AV_LOG_VERBOSE, "rep_idx[%d]\n", (int)c->cur_video->rep_idx);
--            av_log(s, AV_LOG_VERBOSE, "rep_count[%d]\n", (int)video_rep_idx);
--        }
--        if (c->cur_audio) {
--            c->cur_audio->rep_count = audio_rep_idx;
--        }
- cleanup:
-         /*free the document */
-         xmlFreeDoc(doc);
-@@ -1029,6 +1294,7 @@
-     if (close_in) {
-         avio_close(in);
-     }
-+    c->last_load_time = av_gettime_relative();
-     return ret;
- }
-@@ -1042,15 +1308,17 @@
-         if (pls->n_fragments) {
-             num = pls->first_seq_no;
-         } else if (pls->n_timelines) {
-+            
-             start_time_offset = get_segment_start_time_based_on_timeline(pls, 0xFFFFFFFF) - pls->timelines[pls->first_seq_no]->starttime; // total duration of playlist
--            if (start_time_offset < 60 * pls->fragment_timescale)
-+            if (start_time_offset < 60*pls->fragment_timescale)
-                 start_time_offset = 0;
-             else
-                 start_time_offset = start_time_offset - 60 * pls->fragment_timescale;
--
-+            
-             num = calc_next_seg_no_from_timelines(pls, pls->timelines[pls->first_seq_no]->starttime + start_time_offset);
-             if (num == -1)
-                 num = pls->first_seq_no;
-+            
-         } else if (pls->fragment_duration){
-             if (pls->presentation_timeoffset) {
-                 num = pls->presentation_timeoffset * pls->fragment_timescale / pls->fragment_duration;
-@@ -1079,9 +1347,8 @@
-     return num;
- }
--static int64_t calc_max_seg_no(struct representation *pls)
-+static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c)
- {
--    DASHContext *c = pls->parent->priv_data;
-     int64_t num = 0;
-     if (pls->n_fragments) {
-@@ -1101,83 +1368,119 @@
-     return num;
- }
--static void move_timelines(struct representation *rep_src, struct representation *rep_dest)
-+static void move_timelines(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
- {
-     if (rep_dest && rep_src ) {
-         free_timelines_list(rep_dest);
-         rep_dest->timelines    = rep_src->timelines;
-         rep_dest->n_timelines  = rep_src->n_timelines;
-         rep_dest->first_seq_no = rep_src->first_seq_no;
--        rep_dest->last_seq_no = calc_max_seg_no(rep_dest);
-+        rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c);
-+        rep_dest->start_number = rep_src->start_number;
-         rep_src->timelines = NULL;
-         rep_src->n_timelines = 0;
-         rep_dest->cur_seq_no = rep_src->cur_seq_no;
-     }
- }
--static void move_segments(struct representation *rep_src, struct representation *rep_dest)
-+static void move_segments(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
- {
--    if (rep_dest && rep_src ) {
-+    if (rep_dest && rep_src) {
-         free_fragment_list(rep_dest);
--        if (rep_src->start_number > (rep_dest->start_number + rep_dest->n_fragments))
-+        if (rep_src->start_number > (rep_dest->start_number + rep_dest->cur_seq_no))
-             rep_dest->cur_seq_no = 0;
-         else
--            rep_dest->cur_seq_no += rep_src->start_number - rep_dest->start_number;
-+            rep_dest->cur_seq_no = rep_src->n_fragments - ((rep_src->start_number + rep_src->n_fragments) - (rep_dest->start_number + rep_dest->cur_seq_no));
-         rep_dest->fragments    = rep_src->fragments;
-         rep_dest->n_fragments  = rep_src->n_fragments;
-         rep_dest->parent  = rep_src->parent;
--        rep_dest->last_seq_no = calc_max_seg_no(rep_dest);
-+        rep_dest->start_number = rep_src->start_number;
-+        rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c);
-         rep_src->fragments = NULL;
-         rep_src->n_fragments = 0;
-     }
- }
-+static int64_t default_reload_interval_us(AVFormatContext *s)
-+{
-+    return 2000 * 1000;
-+}
- static int refresh_manifest(AVFormatContext *s)
- {
--    int ret = 0;
-+    int ret = 0, i;
-     DASHContext *c = s->priv_data;
-     // save current context
--    struct representation *cur_video =  c->cur_video;
--    struct representation *cur_audio =  c->cur_audio;
-+    int n_videos = c->n_videos;
-+    struct representation **videos = c->videos;
-+    int n_audios = c->n_audios;
-+    struct representation **audios = c->audios;
-     char *base_url = c->base_url;
-+    int64_t reload_interval_us = 0;
-     c->base_url = NULL;
--    c->cur_video = NULL;
--    c->cur_audio = NULL;
-+    c->n_videos = 0;
-+    c->videos = NULL;
-+    c->n_audios = 0;
-+    c->audios = NULL;
-+    
-+    reload_interval_us = default_reload_interval_us(s);
-+    while (av_gettime_relative() - c->last_load_time < reload_interval_us) {
-+        if (ff_check_interrupt(c->interrupt_callback))
-+            return AVERROR_EXIT;
-+        av_usleep(100*1000);
-+    }
-+    
-     ret = parse_manifest(s, s->filename, NULL);
-     if (ret)
-         goto finish;
--    if (cur_video && cur_video->timelines || cur_audio && cur_audio->timelines) {
--        // calc current time
--        int64_t currentVideoTime = 0;
--        int64_t currentAudioTime = 0;
--        if (cur_video && cur_video->timelines)
--            currentVideoTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale;
--        if (cur_audio && cur_audio->timelines)
--            currentAudioTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale;
--        // update segments
--        if (cur_video && cur_video->timelines) {
--            c->cur_video->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_video, currentVideoTime * cur_video->fragment_timescale - 1);
--            if (c->cur_video->cur_seq_no >= 0) {
--                move_timelines(c->cur_video, cur_video);
--            }
--        }
--        if (cur_audio && cur_audio->timelines) {
--            c->cur_audio->cur_seq_no = calc_next_seg_no_from_timelines(c->cur_audio, currentAudioTime * cur_audio->fragment_timescale - 1);
--            if (c->cur_audio->cur_seq_no >= 0) {
--               move_timelines(c->cur_audio, cur_audio);
--            }
--        }
-+    if (c->n_videos != n_videos) {
-+        av_log(c, AV_LOG_ERROR,
-+            "new manifest has mismatched no. of video representations, %d -> %d\n",
-+            n_videos, c->n_videos);
-+        return AVERROR_INVALIDDATA;
-     }
--    if (cur_video && cur_video->fragments) {
--        move_segments(c->cur_video, cur_video);
-+    if (c->n_audios != n_audios) {
-+        av_log(c, AV_LOG_ERROR,
-+            "new manifest has mismatched no. of audio representations, %d -> %d\n",
-+            n_audios, c->n_audios);
-+        return AVERROR_INVALIDDATA;
-     }
--    if (cur_audio && cur_audio->fragments) {
--        move_segments(c->cur_audio, cur_audio);
-+
-+    for (i = 0; i < n_videos; i++) {
-+        struct representation *cur_video = videos[i];
-+        struct representation *ccur_video = c->videos[i];
-+        if (cur_video->timelines) {
-+            // calc current time
-+            int64_t current_time = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale;
-+            // update segments
-+            ccur_video->cur_seq_no = calc_next_seg_no_from_timelines(ccur_video, current_time * cur_video->fragment_timescale - 1);
-+            if (ccur_video->cur_seq_no >= 0) {
-+                move_timelines(ccur_video, cur_video, c);
-+            }
-+        }
-+        if (cur_video->fragments) {
-+            move_segments(ccur_video, cur_video, c);
-+        }
-+    }
-+    for (i = 0; i < n_audios; i++) {
-+        struct representation *cur_audio = audios[i];
-+        struct representation *ccur_audio = c->audios[i];
-+        if (cur_audio->timelines) {
-+            // calc current time
-+            int64_t current_time = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale;
-+            // update segments
-+            ccur_audio->cur_seq_no = calc_next_seg_no_from_timelines(ccur_audio, current_time * cur_audio->fragment_timescale - 1);
-+            if (ccur_audio->cur_seq_no >= 0) {
-+                move_timelines(ccur_audio, cur_audio, c);
-+            }
-+        }
-+        if (cur_audio->fragments) {
-+            move_segments(ccur_audio, cur_audio, c);
-+        }
-     }
- finish:
-@@ -1186,12 +1489,14 @@
-         av_free(base_url);
-     else
-         c->base_url  = base_url;
--    if (c->cur_audio)
--        free_representation(c->cur_audio);
--    if (c->cur_video)
--        free_representation(c->cur_video);
--    c->cur_audio = cur_audio;
--    c->cur_video = cur_video;
-+    if (c->audios)
-+        free_audio_list(c);
-+    if (c->videos)
-+        free_video_list(c);
-+    c->n_audios = n_audios;
-+    c->audios = audios;
-+    c->n_videos = n_videos;
-+    c->videos = videos;
-     return ret;
- }
-@@ -1225,17 +1530,29 @@
-         }
-     }
-     if (c->is_live) {
--        min_seq_no = calc_min_seg_no(pls->parent, pls);
--        max_seq_no = calc_max_seg_no(pls);
--
--        if (pls->timelines || pls->fragments) {
--            refresh_manifest(pls->parent);
--        }
--        if (pls->cur_seq_no <= min_seq_no) {
--            av_log(pls->parent, AV_LOG_VERBOSE, "old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx);
--            pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls);
--        } else if (pls->cur_seq_no > max_seq_no) {
--            av_log(pls->parent, AV_LOG_VERBOSE, "new fragment: min[%"PRId64"] max[%"PRId64"], playlist %d\n", min_seq_no, max_seq_no, (int)pls->rep_idx);
-+        while (!ff_check_interrupt(c->interrupt_callback)) {
-+            min_seq_no = calc_min_seg_no(pls->parent, pls);
-+            max_seq_no = calc_max_seg_no(pls, c);
-+            
-+            if (pls->cur_seq_no <= min_seq_no) {
-+                av_log(pls->parent, AV_LOG_VERBOSE, "to old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx);
-+                if (pls->timelines || pls->fragments) {
-+                    refresh_manifest(pls->parent);
-+                }
-+                pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls);
-+            } else if (pls->cur_seq_no > max_seq_no) {
-+                av_log(pls->parent, AV_LOG_VERBOSE, "wait for new fragment:cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx);
-+                if (pls->timelines || pls->fragments) {
-+                    refresh_manifest(pls->parent);
-+                } else {
-+                    /* maybe the better solution will be to sleep based on pls->fragment_duration 
-+                     * for example: 1000 * pls->fragment_duration / pls->fragment_timescale ???
-+                     */
-+                    sleep_ms(c, 2000);
-+                }
-+                continue;
-+            }
-+            break;
-         }
-         seg = av_mallocz(sizeof(struct fragment));
-         if (!seg) {
-@@ -1248,19 +1565,22 @@
-         }
-     }
-     if (seg) {
--        char tmpfilename[MAX_URL_SIZE];
--
--        ff_dash_fill_tmpl_params(tmpfilename, sizeof(tmpfilename), pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no));
-+        char *tmpfilename= av_mallocz(c->max_url_size);
-+        if (!tmpfilename) {
-+            return NULL;
-+        }
-+        ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no + pls->start_number, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no));
-         seg->url = av_strireplace(pls->url_template, pls->url_template, tmpfilename);
-         if (!seg->url) {
-             av_log(pls->parent, AV_LOG_WARNING, "Unable to resolve template url '%s', try to use origin template\n", pls->url_template);
-             seg->url = av_strdup(pls->url_template);
-             if (!seg->url) {
-                 av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template);
-+                av_free(tmpfilename);
-                 return NULL;
-             }
-         }
--
-+        av_free(tmpfilename);
-         seg->size = -1;
-     }
-@@ -1299,10 +1619,14 @@
- static int open_input(DASHContext *c, struct representation *pls, struct fragment *seg)
- {
-     AVDictionary *opts = NULL;
--    char url[MAX_URL_SIZE];
--    int ret;
-+    char *url = NULL;
-+    int ret = 0;
--    set_httpheader_options(c, opts);
-+    url = av_mallocz(c->max_url_size);
-+    if (!url) {
-+        goto cleanup;
-+    }
-+    set_httpheader_options(c, &opts);
-     if (seg->size >= 0) {
-         /* try to restrict the HTTP request to the part we want
-          * (if this is in fact a HTTP request) */
-@@ -1310,7 +1634,7 @@
-         av_dict_set_int(&opts, "end_offset", seg->url_offset + seg->size, 0);
-     }
--    ff_make_absolute_url(url, MAX_URL_SIZE, c->base_url, seg->url);
-+    ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url);
-     av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64", playlist %d\n",
-            url, seg->url_offset, pls->rep_idx);
-     ret = open_url(pls->parent, &pls->input, url, c->avio_opts, opts, NULL);
-@@ -1318,19 +1642,8 @@
-         goto cleanup;
-     }
--    /* Seek to the requested position. If this was a HTTP request, the offset
--     * should already be where want it to, but this allows e.g. local testing
--     * without a HTTP server. */
--    if (!ret && seg->url_offset) {
--        int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET);
--        if (seekret < 0) {
--            av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of DASH fragment '%s'\n", seg->url_offset, seg->url);
--            ret = (int) seekret;
--            ff_format_io_close(pls->parent, &pls->input);
--        }
--    }
--
- cleanup:
-+    av_free(url);
-     av_dict_free(&opts);
-     pls->cur_seg_offset = 0;
-     pls->cur_seg_size = seg->size;
-@@ -1416,13 +1729,28 @@
-         ret = open_input(c, v, v->cur_seg);
-         if (ret < 0) {
--            if (ff_check_interrupt(c->interrupt_callback)) {
--                goto end;
--                ret = AVERROR_EXIT;
-+            av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d error [%s]\n", v->rep_idx, av_err2str(ret));
-+            if (ret == AVERROR_HTTP_NOT_FOUND || \
-+                ret == AVERROR_HTTP_BAD_REQUEST || \
-+                ret == AVERROR_HTTP_OTHER_4XX || \
-+                ret == AVERROR_HTTP_SERVER_ERROR) {
-+                if (ret == AVERROR_HTTP_OTHER_4XX)  {
-+                    /* 410 - Gone ? our download is to slow? */
-+                    v->cur_seq_no++;
-+                } else if (c->is_live && v->timelines || v->fragments) {
-+                    refresh_manifest(v->parent);
-+                } else if (!c->is_live) {
-+                    /* skip missing segment in VOD */
-+                    v->cur_seq_no++;
-+                }
-+                if (ff_check_interrupt(c->interrupt_callback)) {
-+                    goto end;
-+                    ret = AVERROR_EXIT;
-+                }
-+                goto restart;
-             }
--            av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d\n", v->rep_idx);
--            v->cur_seq_no++;
--            goto restart;
-+            ret = AVERROR_INVALIDDATA;
-+            goto end;
-         }
-     }
-@@ -1447,9 +1775,11 @@
-     if (ret > 0)
-         goto end;
--    if (!v->is_restart_needed)
--        v->cur_seq_no++;
--    v->is_restart_needed = 1;
-+    if (c->is_live || v->cur_seq_no < v->last_seq_no) {
-+        if (!v->is_restart_needed)
-+            v->cur_seq_no++;
-+        v->is_restart_needed = 1;
-+    }
- end:
-     return ret;
-@@ -1466,8 +1796,12 @@
-         if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
-             if (buf[0] != '\0') {
-                 ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL);
--                if (ret < 0)
-+                if (ret < 0) {
-+                    av_freep(&buf);
-                     return ret;
-+                }
-+            } else {
-+                av_freep(&buf);
-             }
-         }
-         opt++;
-@@ -1486,21 +1820,26 @@
-     return AVERROR(EPERM);
- }
-+static void close_demux_for_component(struct representation *pls)
-+{
-+    /* note: the internal buffer could have changed */
-+    av_freep(&pls->pb.buffer);
-+    memset(&pls->pb, 0x00, sizeof(AVIOContext));
-+    pls->ctx->pb = NULL;
-+    avformat_close_input(&pls->ctx);
-+    pls->ctx = NULL;
-+}
-+
- static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls)
- {
-     DASHContext *c = s->priv_data;
-     AVInputFormat *in_fmt = NULL;
-     AVDictionary  *in_fmt_opts = NULL;
-     uint8_t *avio_ctx_buffer  = NULL;
--    int ret = 0;
-+    int ret = 0, i;
-     if (pls->ctx) {
--        /* note: the internal buffer could have changed, and be != avio_ctx_buffer */
--        av_freep(&pls->pb.buffer);
--        memset(&pls->pb, 0x00, sizeof(AVIOContext));
--        pls->ctx->pb = NULL;
--        avformat_close_input(&pls->ctx);
--        pls->ctx = NULL;
-+        close_demux_for_component(pls);
-     }
-     if (!(pls->ctx = avformat_alloc_context())) {
-         ret = AVERROR(ENOMEM);
-@@ -1538,12 +1877,22 @@
-     pls->ctx->pb = &pls->pb;
-     pls->ctx->io_open  = nested_io_open;
-+    pls->is_first_pkt = 1;
-+    pls->pkt_start_time_offset = 0;
-+
-     // provide additional information from mpd if available
-     ret = avformat_open_input(&pls->ctx, "", in_fmt, &in_fmt_opts); //pls->init_section->url
-     av_dict_free(&in_fmt_opts);
-     if (ret < 0)
-         goto fail;
-     if (pls->n_fragments) {
-+#if FF_API_R_FRAME_RATE
-+        if (pls->framerate.den) {
-+            for (i = 0; i < pls->ctx->nb_streams; i++)
-+                pls->ctx->streams[i]->r_frame_rate = pls->framerate;
-+        }
-+#endif
-+
-         ret = avformat_find_stream_info(pls->ctx, NULL);
-         if (ret < 0)
-             goto fail;
-@@ -1560,7 +1909,7 @@
-     pls->parent = s;
-     pls->cur_seq_no  = calc_cur_seg_no(s, pls);
--    pls->last_seq_no = calc_max_seg_no(pls);
-+    pls->last_seq_no = calc_max_seg_no(pls, s->priv_data);
-     ret = reopen_demux_for_component(s, pls);
-     if (ret < 0) {
-@@ -1589,6 +1938,7 @@
-     DASHContext *c = s->priv_data;
-     int ret = 0;
-     int stream_index = 0;
-+    int i;
-     c->interrupt_callback = &s->interrupt_callback;
-     // if the URL context is good, read important options we must broker later
-@@ -1610,27 +1960,23 @@
-         s->duration = (int64_t) c->media_presentation_duration * AV_TIME_BASE;
-     }
--    /* Open the demuxer for curent video and current audio components if available */
--    if (!ret && c->cur_video) {
--        ret = open_demux_for_component(s, c->cur_video);
--        if (!ret) {
--            c->cur_video->stream_index = stream_index;
--            ++stream_index;
--        } else {
--            free_representation(c->cur_video);
--            c->cur_video = NULL;
--        }
-+    /* Open the demuxer for video and audio components if available */
-+    for (i = 0; i < c->n_videos; i++) {
-+        struct representation *cur_video = c->videos[i];
-+        ret = open_demux_for_component(s, cur_video);
-+        if (ret)
-+            goto fail;
-+        cur_video->stream_index = stream_index;
-+        ++stream_index;
-     }
--    if (!ret && c->cur_audio) {
--        ret = open_demux_for_component(s, c->cur_audio);
--        if (!ret) {
--            c->cur_audio->stream_index = stream_index;
--            ++stream_index;
--        } else {
--            free_representation(c->cur_audio);
--            c->cur_audio = NULL;
--        }
-+    for (i = 0; i < c->n_audios; i++) {
-+        struct representation *cur_audio = c->audios[i];
-+        ret = open_demux_for_component(s, cur_audio);
-+        if (ret)
-+            goto fail;
-+        cur_audio->stream_index = stream_index;
-+        ++stream_index;
-     }
-     if (!stream_index) {
-@@ -1646,11 +1992,25 @@
-             goto fail;
-         }
--        if (c->cur_video) {
--            av_program_add_stream_index(s, 0, c->cur_video->stream_index);
--        }
--        if (c->cur_audio) {
--            av_program_add_stream_index(s, 0, c->cur_audio->stream_index);
-+        for (i = 0; i < c->n_videos; i++) {
-+            struct representation *pls = c->videos[i];
-+
-+            av_program_add_stream_index(s, 0, pls->stream_index);
-+            pls->assoc_stream = s->streams[pls->stream_index];
-+            if (pls->bandwidth > 0)
-+                av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0);
-+            if (pls->id[0])
-+                av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0);
-+         }
-+        for (i = 0; i < c->n_audios; i++) {
-+            struct representation *pls = c->audios[i];
-+
-+            av_program_add_stream_index(s, 0, pls->stream_index);
-+            pls->assoc_stream = s->streams[pls->stream_index];
-+            if (pls->bandwidth > 0)
-+                av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0);
-+            if (pls->id[0])
-+                av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0);
-         }
-     }
-@@ -1659,43 +2019,89 @@
-     return ret;
- }
-+static void recheck_discard_flags(AVFormatContext *s, struct representation **p, int n)
-+{
-+    int i, j;
-+
-+    for (i = 0; i < n; i++) {
-+        struct representation *pls = p[i];
-+
-+        int needed = !pls->assoc_stream || pls->assoc_stream->discard < AVDISCARD_ALL;
-+        if (needed && !pls->ctx) {
-+            pls->cur_seg_offset = 0;
-+            pls->init_sec_buf_read_offset = 0;
-+            /* Catch up */
-+            for (j = 0; j < n; j++) {
-+                pls->cur_seq_no = FFMAX(pls->cur_seq_no, p[j]->cur_seq_no);
-+            }
-+            reopen_demux_for_component(s, pls);
-+            av_log(s, AV_LOG_INFO, "Now receiving stream_index %d\n", pls->stream_index);
-+        } else if (!needed && pls->ctx) {
-+            close_demux_for_component(pls);
-+            if (pls->input)
-+                ff_format_io_close(pls->parent, &pls->input);
-+            av_log(s, AV_LOG_INFO, "No longer receiving stream_index %d\n", pls->stream_index);
-+        }
-+    }
-+}
-+
- static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
- {
-     DASHContext *c = s->priv_data;
--    int ret = 0;
-+    int ret = 0, i;
-+    int64_t mints = 0;
-     struct representation *cur = NULL;
--    if (!c->cur_audio && !c->cur_video ) {
--        return AVERROR_INVALIDDATA;
-+    recheck_discard_flags(s, c->videos, c->n_videos);
-+    recheck_discard_flags(s, c->audios, c->n_audios);
-+
-+    for (i = 0; i < c->n_videos; i++) {
-+        struct representation *pls = c->videos[i];
-+        if (!pls->ctx)
-+            continue;
-+        if (!cur || pls->cur_timestamp < mints) {
-+            cur = pls;
-+            mints = pls->cur_timestamp;
-+        }
-     }
--    if (c->cur_audio && !c->cur_video) {
--        cur = c->cur_audio;
--    } else if (!c->cur_audio && c->cur_video) {
--        cur = c->cur_video;
--    } else if (c->cur_video->cur_timestamp < c->cur_audio->cur_timestamp) {
--        cur = c->cur_video;
--    } else {
--        cur = c->cur_audio;
-+    for (i = 0; i < c->n_audios; i++) {
-+        struct representation *pls = c->audios[i];
-+        if (!pls->ctx)
-+            continue;
-+        if (!cur || pls->cur_timestamp < mints) {
-+            cur = pls;
-+            mints = pls->cur_timestamp;
-+        }
-     }
--    if (cur->ctx) {
--        while (!ff_check_interrupt(c->interrupt_callback) && !ret) {
--            ret = av_read_frame(cur->ctx, pkt);
--            if (ret >= 0) {
--                /* If we got a packet, return it */
--                cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den);
--                pkt->stream_index = cur->stream_index;
--                return 0;
--            }
--            if (cur->is_restart_needed) {
--                cur->cur_seg_offset = 0;
--                cur->init_sec_buf_read_offset = 0;
--                if (cur->input)
--                    ff_format_io_close(cur->parent, &cur->input);
--                ret = reopen_demux_for_component(s, cur);
--                cur->is_restart_needed = 0;
--            }
--
-+    if (!cur) {
-+        return AVERROR_INVALIDDATA;
-+    }
-+    while (!ff_check_interrupt(c->interrupt_callback) && !ret) {
-+        ret = av_read_frame(cur->ctx, pkt);
-+        if (ret >= 0) {
-+            if (c->is_live && cur->is_first_pkt && 0 == pkt->pts) {
-+                cur->pkt_start_time_offset = get_segment_start_time_based_on_timeline(cur, cur->cur_seq_no);
-+            }
-+            if (cur->pkt_start_time_offset) {
-+                AVRational bq;
-+                bq.num = 1;
-+                bq.den = (int)cur->fragment_timescale;
-+                pkt->pts += av_rescale_q(cur->pkt_start_time_offset, bq,cur->ctx->streams[0]->time_base);
-+            }
-+            /* If we got a packet, return it */
-+            cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den);
-+            pkt->stream_index = cur->stream_index;
-+            cur->is_first_pkt = 0;
-+            return 0;
-+        }
-+        if (cur->is_restart_needed) {
-+            cur->cur_seg_offset = 0;
-+            cur->init_sec_buf_read_offset = 0;
-+            if (cur->input)
-+                ff_format_io_close(cur->parent, &cur->input);
-+            ret = reopen_demux_for_component(s, cur);
-+            cur->is_restart_needed = 0;
-         }
-     }
-     return AVERROR_EOF;
-@@ -1704,12 +2110,8 @@
- static int dash_close(AVFormatContext *s)
- {
-     DASHContext *c = s->priv_data;
--    if (c->cur_audio) {
--        free_representation(c->cur_audio);
--    }
--    if (c->cur_video) {
--        free_representation(c->cur_video);
--    }
-+    free_audio_list(c);
-+    free_video_list(c);
-     av_freep(&c->cookies);
-     av_freep(&c->user_agent);
-@@ -1718,19 +2120,22 @@
-     return 0;
- }
--static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags)
-+static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags, int dry_run)
- {
-     int ret = 0;
-     int i = 0;
-     int j = 0;
-     int64_t duration = 0;
--    av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d\n", seek_pos_msec, pls->rep_idx);
-+    av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d%s\n",
-+            seek_pos_msec, pls->rep_idx, dry_run ? " (dry)" : "");
-     // single fragment mode
-     if (pls->n_fragments == 1) {
-         pls->cur_timestamp = 0;
-         pls->cur_seg_offset = 0;
-+        if (dry_run)
-+            return 0;
-         ff_read_frame_flush(pls->ctx);
-         return av_seek_frame(pls->ctx, -1, seek_pos_msec * 1000, flags);
-     }
-@@ -1769,20 +2174,20 @@
-     } else if (pls->fragment_duration > 0) {
-         pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000;
-     } else {
--        av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing fragment_duration\n");
-+        av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing timeline or fragment_duration\n");
-         pls->cur_seq_no = pls->first_seq_no;
-     }
-     pls->cur_timestamp = 0;
-     pls->cur_seg_offset = 0;
-     pls->init_sec_buf_read_offset = 0;
--    ret = reopen_demux_for_component(s, pls);
-+    ret = dry_run ? 0 : reopen_demux_for_component(s, pls);
-     return ret;
- }
- static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
- {
--    int ret = 0;
-+    int ret = 0, i;
-     DASHContext *c = s->priv_data;
-     int64_t seek_pos_msec = av_rescale_rnd(timestamp, 1000,
-                                            s->streams[stream_index]->time_base.den,
-@@ -1790,12 +2195,17 @@
-                                            AV_ROUND_DOWN : AV_ROUND_UP);
-     if ((flags & AVSEEK_FLAG_BYTE) || c->is_live)
-         return AVERROR(ENOSYS);
--    if (c->cur_audio) {
--        ret = dash_seek(s, c->cur_audio, seek_pos_msec, flags);
--    }
--    if (!ret && c->cur_video) {
--        ret = dash_seek(s, c->cur_video, seek_pos_msec, flags);
-+
-+    /* Seek in discarded streams with dry_run=1 to avoid reopening them */
-+    for (i = 0; i < c->n_videos; i++) {
-+        if (!ret)
-+            ret = dash_seek(s, c->videos[i], seek_pos_msec, flags, !c->videos[i]->ctx);
-+    }
-+    for (i = 0; i < c->n_audios; i++) {
-+        if (!ret)
-+            ret = dash_seek(s, c->audios[i], seek_pos_msec, flags, !c->audios[i]->ctx);
-     }
-+
-     return ret;
- }
-@@ -1820,6 +2230,10 @@
- #define OFFSET(x) offsetof(DASHContext, x)
- #define FLAGS AV_OPT_FLAG_DECODING_PARAM
- static const AVOption dash_options[] = {
-+    {"audio_rep_index", "audio representation index to be used",
-+        OFFSET(audio_rep_index), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, FLAGS},
-+    {"video_rep_index", "video representation index to be used",
-+        OFFSET(video_rep_index), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, FLAGS},
-     {"allowed_extensions", "List of file extensions that dash is allowed to access",
-         OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
-         {.str = "aac,m4a,m4s,m4v,mov,mp4"},
-@@ -1845,4 +2259,4 @@
-     .read_close     = dash_close,
-     .read_seek      = dash_read_seek,
-     .flags          = AVFMT_NO_BYTE_SEEK,
--};
-+};
-\ No newline at end of file
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-dash-build.patch
deleted file mode 100644 (file)
index 49e9642..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/libavformat/Makefile
-+++ b/libavformat/Makefile
-@@ -135,7 +135,7 @@
- OBJS-$(CONFIG_DATA_DEMUXER)              += rawdec.o
- OBJS-$(CONFIG_DATA_MUXER)                += rawenc.o
- OBJS-$(CONFIG_DASH_MUXER)                += dash.o dashenc.o
--OBJS-$(CONFIG_DASH_DEMUXER)              += dashdec.o
-+OBJS-$(CONFIG_DASH_DEMUXER)              += dash.o dashdec.o
- OBJS-$(CONFIG_DAUD_DEMUXER)              += dauddec.o
- OBJS-$(CONFIG_DAUD_MUXER)                += daudenc.o
- OBJS-$(CONFIG_DCSTR_DEMUXER)             += dcstr.o
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-edit-list-parsing.patch
deleted file mode 100644 (file)
index a266023..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Taapat: disable log to fix freezing on edit list parsing intruduced in:
-http://git.videolan.org/gitweb.cgi/ffmpeg.git/?p=ffmpeg.git;a=commitdiff;h=ca6cae73db207f17a0d5507609de12842d8f0ca3
-
---- a/libavformat/mov.c
-+++ b/libavformat/mov.c
-@@ -3191,8 +3191,10 @@
-             if (ctts_data_old && ctts_index_old < ctts_count_old) {
-                 curr_ctts = ctts_data_old[ctts_index_old].duration;
-+                /*
-                 av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
-                        curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
-+                */
-                 curr_cts += curr_ctts;
-                 ctts_sample_old++;
-                 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix-hls.patch
deleted file mode 100644 (file)
index a57cbc8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
---- a/libavformat/hls.c
-+++ b/libavformat/hls.c
-@@ -1924,8 +1924,10 @@
-     HLSContext *c = s->priv_data;
-     int ret, i, minplaylist = -1;
--    recheck_discard_flags(s, c->first_packet);
--    c->first_packet = 0;
-+    if (c->first_packet) {
-+        recheck_discard_flags(s, 1);
-+        c->first_packet = 0;
-+    }
-     for (i = 0; i < c->n_playlists; i++) {
-         struct playlist *pls = c->playlists[i];
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-fix_mpegts.patch
deleted file mode 100644 (file)
index bfd7f72..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -uNr ffmpeg-3.4.2/libavformat/mpegts.c ffmpeg-3.4.2_fix_mpegts/libavformat/mpegts.c
---- ffmpeg-3.4.2/libavformat/mpegts.c  2018-02-12 01:29:06.000000000 +0100
-+++ ffmpeg-3.4.2_fix_mpegts/libavformat/mpegts.c       2018-02-14 19:36:28.175054407 +0100
-@@ -917,10 +917,12 @@
-     pes->buffer = NULL;
-     reset_pes_packet_state(pes);
-+    /*
-     sd = av_packet_new_side_data(pkt, AV_PKT_DATA_MPEGTS_STREAM_ID, 1);
-     if (!sd)
-         return AVERROR(ENOMEM);
-     *sd = pes->stream_id;
-+    */
-     return 0;
- }
diff --git a/archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch b/archive-patches/ffmpeg/ffmpeg-3.4.2-hls_replace_key_uri.patch
deleted file mode 100644 (file)
index 4248694..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
---- ffmpeg-3.4.2/libavformat/hls.c
-+++ ffmpeg-3.4.2/libavformat/hls.c
-@@ -206,6 +206,8 @@
-     int strict_std_compliance;
-     char *allowed_extensions;
-     int max_reload;
-+    char *key_uri_replace_old;
-+    char *key_uri_replace_new;
- } HLSContext;
- static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
-@@ -1127,8 +1129,17 @@
-         AVDictionary *opts2 = NULL;
-         char iv[33], key[33], url[MAX_URL_SIZE];
-         if (strcmp(seg->key, pls->key_url)) {
-+            char *key_url = NULL;
-             AVIOContext *pb;
--            if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) {
-+            
-+            if (NULL != c->key_uri_replace_old && \
-+                NULL != c-> key_uri_replace_new && \
-+                '\0' != c->key_uri_replace_old[0]) {
-+                key_url = av_strireplace(seg->key, c->key_uri_replace_old, c->key_uri_replace_new);
-+            } else {
-+                key_url = seg->key;
-+            }
-+            if (open_url(pls->parent, &pb, key_url, c->avio_opts, opts, NULL) == 0) {
-                 ret = avio_read(pb, pls->key, sizeof(pls->key));
-                 if (ret != sizeof(pls->key)) {
-                     av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
-@@ -1140,6 +1151,8 @@
-                        seg->key);
-             }
-             av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url));
-+            if (key_url != seg->key)
-+                av_free(key_url);
-         }
-         ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
-         ff_data_to_hex(key, pls->key, sizeof(pls->key), 0);
-@@ -1846,7 +1859,7 @@
-     for (i = 0; i < c->n_playlists; i++)
-         c->playlists[i]->cur_needed = 0;
--    for (i = 0; i < s->nb_streams; i++) {
-+    for (i = 0; i < s->nb_streams && s->streams[i]->id < c->n_playlists; i++) {
-         AVStream *st = s->streams[i];
-         struct playlist *pls = c->playlists[s->streams[i]->id];
-         if (st->discard < AVDISCARD_ALL)
-@@ -2159,6 +2172,8 @@
-         INT_MIN, INT_MAX, FLAGS},
-     {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
-         OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS},
-+    { "key_uri_old", "allow to replace part of AES key uri - old", OFFSET(key_uri_replace_old), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
-+    { "key_uri_new", "allow to replace part of AES key uri - new", OFFSET(key_uri_replace_new), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
-     {NULL}
- };
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-allow_to_choose_rtmp_impl_at_runtime.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-allow_to_choose_rtmp_impl_at_runtime.patch
new file mode 100644 (file)
index 0000000..b369da7
--- /dev/null
@@ -0,0 +1,126 @@
+--- a/configure        2018-08-17 11:51:31.066805453 +0200
++++ b/configure        2018-08-17 12:03:19.617555506 +0200
+@@ -3251,10 +3251,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"
+@@ -3277,20 +3275,18 @@
+ mmst_protocol_select="network"
+ libsrt_protocol_deps="libsrt"
+ libsrt_protocol_select="network"
+-rtmp_protocol_conflict="librtmp_protocol"
+-rtmp_protocol_select="tcp_protocol"
+-rtmp_protocol_suggest="zlib"
+-rtmpe_protocol_select="ffrtmpcrypt_protocol"
+-rtmpe_protocol_suggest="zlib"
+-rtmps_protocol_conflict="librtmp_protocol"
+-rtmps_protocol_select="tls_protocol"
+-rtmps_protocol_suggest="zlib"
+-rtmpt_protocol_select="ffrtmphttp_protocol"
+-rtmpt_protocol_suggest="zlib"
+-rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol"
+-rtmpte_protocol_suggest="zlib"
+-rtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
+-rtmpts_protocol_suggest="zlib"
++ffrtmp_protocol_select="tcp_protocol"
++ffrtmp_protocol_suggest="zlib"
++ffrtmpe_protocol_select="ffrtmpcrypt_protocol"
++ffrtmpe_protocol_suggest="zlib"
++ffrtmps_protocol_select="tls_protocol"
++ffrtmps_protocol_suggest="zlib"
++ffrtmpt_protocol_select="ffrtmphttp_protocol"
++ffrtmpt_protocol_suggest="zlib"
++ffrtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol"
++ffrtmpte_protocol_suggest="zlib"
++ffrtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
++ffrtmpts_protocol_suggest="zlib"
+ rtp_protocol_select="udp_protocol"
+ schannel_conflict="openssl gnutls libtls"
+ sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags"
+--- a/libavformat/Makefile     2018-07-18 15:52:01.000000000 +0200
++++ b/libavformat/Makefile     2018-08-17 12:06:16.348291303 +0200
+@@ -594,12 +594,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 rtmpdigest.o rtmppkt.o
+-OBJS-$(CONFIG_RTMPE_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
+-OBJS-$(CONFIG_RTMPS_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
+-OBJS-$(CONFIG_RTMPT_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
+-OBJS-$(CONFIG_RTMPTE_PROTOCOL)           += rtmpproto.o rtmpdigest.o rtmppkt.o
+-OBJS-$(CONFIG_RTMPTS_PROTOCOL)           += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMP_PROTOCOL)             += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMPE_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMPS_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMPT_PROTOCOL)            += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMPTE_PROTOCOL)           += rtmpproto.o rtmpdigest.o rtmppkt.o
++OBJS-$(CONFIG_FFRTMPTS_PROTOCOL)           += rtmpproto.o rtmpdigest.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  2018-08-17 12:07:59.489872867 +0200
++++ b/libavformat/protocols.c  2018-08-17 12:08:24.450255607 +0200
+@@ -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;
+--- a/libavformat/rtmpproto.c  2018-07-18 15:52:02.000000000 +0200
++++ b/libavformat/rtmpproto.c  2018-08-17 12:11:43.844590847 +0200
+@@ -2592,7 +2592,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;
+@@ -2603,7 +2603,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);
+@@ -3137,9 +3139,9 @@
+ };
+-RTMP_PROTOCOL(rtmp)
+-RTMP_PROTOCOL(rtmpe)
+-RTMP_PROTOCOL(rtmps)
+-RTMP_PROTOCOL(rtmpt)
+-RTMP_PROTOCOL(rtmpte)
+-RTMP_PROTOCOL(rtmpts)
++RTMP_PROTOCOL(ffrtmp)
++RTMP_PROTOCOL(ffrtmpe)
++RTMP_PROTOCOL(ffrtmps)
++RTMP_PROTOCOL(ffrtmpt)
++RTMP_PROTOCOL(ffrtmpte)
++RTMP_PROTOCOL(ffrtmpts)
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_edit_list_parsing.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_edit_list_parsing.patch
new file mode 100644 (file)
index 0000000..f9e56fc
--- /dev/null
@@ -0,0 +1,16 @@
+Taapat: disable log to fix freezing on edit list parsing intruduced in:
+http://git.videolan.org/gitweb.cgi/ffmpeg.git/?p=ffmpeg.git;a=commitdiff;h=ca6cae73db207f17a0d5507609de12842d8f0ca3
+
+--- a/libavformat/mov.c
++++ b/libavformat/mov.c
+@@ -3543,8 +3543,10 @@
+             if (ctts_data_old && ctts_index_old < ctts_count_old) {
+                 curr_ctts = ctts_data_old[ctts_index_old].duration;
++                /*
+                 av_log(mov->fc, AV_LOG_DEBUG, "stts: %"PRId64" ctts: %"PRId64", ctts_index: %"PRId64", ctts_count: %"PRId64"\n",
+                        curr_cts, curr_ctts, ctts_index_old, ctts_count_old);
++                */
+                 curr_cts += curr_ctts;
+                 ctts_sample_old++;
+                 if (ctts_sample_old == ctts_data_old[ctts_index_old].count) {
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_hls.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_hls.patch
new file mode 100644 (file)
index 0000000..861d6ae
--- /dev/null
@@ -0,0 +1,15 @@
+--- a/libavformat/hls.c        2018-08-17 13:06:01.428702126 +0200
++++ b/libavformat/hls.c        2018-08-17 13:06:15.077944569 +0200
+@@ -2079,8 +2079,10 @@
+     HLSContext *c = s->priv_data;
+     int ret, i, minplaylist = -1;
+-    recheck_discard_flags(s, c->first_packet);
+-    c->first_packet = 0;
++    if (c->first_packet) {
++        recheck_discard_flags(s, 1);
++        c->first_packet = 0;
++    }
+     for (i = 0; i < c->n_playlists; i++) {
+         struct playlist *pls = c->playlists[i];
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_mpegts.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-fix_mpegts.patch
new file mode 100644 (file)
index 0000000..a78057f
--- /dev/null
@@ -0,0 +1,15 @@
+--- a/libavformat/mpegts.c     2018-02-12 01:29:06.000000000 +0100
++++ b/libavformat/mpegts.c     2018-02-14 19:36:28.175054407 +0100
+@@ -930,10 +930,12 @@
+     pes->buffer = NULL;
+     reset_pes_packet_state(pes);
++    /*
+     sd = av_packet_new_side_data(pkt, AV_PKT_DATA_MPEGTS_STREAM_ID, 1);
+     if (!sd)
+         return AVERROR(ENOMEM);
+     *sd = pes->stream_id;
++    */
+     return 0;
+ }
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-hls_replace_key_uri.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-hls_replace_key_uri.patch
new file mode 100644 (file)
index 0000000..f176282
--- /dev/null
@@ -0,0 +1,47 @@
+--- a/libavformat/hls.c        2018-08-17 13:16:57.721007600 +0200
++++ b/libavformat/hls.c        2018-08-17 13:33:57.530170057 +0200
+@@ -213,6 +213,8 @@
+     int max_reload;
+     int http_persistent;
+     int http_multiple;
++    char *key_uri_replace_old;
++    char *key_uri_replace_new;
+     AVIOContext *playlist_pb;
+ } HLSContext;
+@@ -1196,8 +1198,16 @@
+         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 = NULL;
+-            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",
+@@ -1209,6 +1219,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);
+@@ -2332,6 +2344,8 @@
+         OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
+     {"http_multiple", "Use multiple HTTP connections for fetching segments",
+         OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, FLAGS},
++    { "key_uri_old", "allow to replace part of AES key uri - old", OFFSET(key_uri_replace_old), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
++    { "key_uri_new", "allow to replace part of AES key uri - new", OFFSET(key_uri_replace_new), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
+     {NULL}
+ };
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-increase_buffer_size.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-increase_buffer_size.patch
new file mode 100644 (file)
index 0000000..dd80a06
--- /dev/null
@@ -0,0 +1,107 @@
+From 90aa7aea0baa100719456e6a5b6e6682a5401aa0 Mon Sep 17 00:00:00 2001
+From: Markus Volk <f_l_k@t-online.de>
+Date: Sat, 14 Oct 2017 17:39:14 +0200
+
+---
+ libavformat/avio.h    |  6 ------
+ libavformat/aviobuf.c | 12 +++++-------
+ libavformat/utils.c   | 19 +++++++++++++++++++
+ 3 files changed, 24 insertions(+), 13 deletions(-)
+
+diff --git a/libavformat/avio.h b/libavformat/avio.h
+index 75912ce..56f0a4d 100644
+--- a/libavformat/avio.h
++++ b/libavformat/avio.h
+@@ -290,12 +290,6 @@ typedef struct AVIOContext {
+      */
+     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.
+diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
+index e752d0e..108f089 100644
+--- 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
+@@ -90,7 +90,6 @@ int ffio_init_context(AVIOContext *s,
+     memset(s, 0, sizeof(AVIOContext));
+     s->buffer      = buffer;
+-    s->orig_buffer_size =
+     s->buffer_size = buffer_size;
+     s->buf_ptr     = buffer;
+     s->buf_ptr_max = buffer;
+@@ -570,16 +569,16 @@ static void fill_buffer(AVIOContext *s)
+     }
+     /* 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;
+     }
+     len = read_packet_wrapper(s, dst, len);
+@@ -1087,7 +1086,6 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size)
+     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);
+diff --git a/libavformat/utils.c b/libavformat/utils.c
+index c25eab4..02ce5e2 100644
+--- a/libavformat/utils.c
++++ b/libavformat/utils.c
+@@ -138,6 +138,25 @@ FF_ENABLE_DEPRECATION_WARNINGS
+ #endif
+ #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)
+ {
+     if (st->internal->priv_pts) {
diff --git a/archive-patches/ffmpeg/ffmpeg-4.0.3-optimize_aac.patch b/archive-patches/ffmpeg/ffmpeg-4.0.3-optimize_aac.patch
new file mode 100644 (file)
index 0000000..480b163
--- /dev/null
@@ -0,0 +1,53 @@
+--- a/libavcodec/aacdec_template.c
++++ b/libavcodec/aacdec_template.c
+@@ -2483,7 +2483,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;
index 38284aae33559d6e85439b88e9486295c5193602..31ce7b96eb6d65a68e1cdcf6c11a9d3bf4fbbb55 100644 (file)
@@ -437,18 +437,27 @@ FFMPEG_DEP = $(D)/libass $(D)/alsa-lib
 FFMPEG_CONFIGURE += --cpu=cortex-a15 --disable-vfp --extra-cflags="-Wno-deprecated-declarations -I$(TARGETPREFIX)/include"
 endif
 
+#
+# ffmpeg_patches
+#
+FFMPEG_PATCHES = \
+               ffmpeg-$(FFMPEG_VER)-fix_hls.patch \
+               ffmpeg-$(FFMPEG_VER)-increase_buffer_size.patch \
+               ffmpeg-$(FFMPEG_VER)-optimize_aac.patch \
+               ffmpeg-$(FFMPEG_VER)-fix_edit_list_parsing.patch \
+               ffmpeg-$(FFMPEG_VER)-fix_mpegts.patch \
+               ffmpeg-$(FFMPEG_VER)-allow_to_choose_rtmp_impl_at_runtime.patch \
+               ffmpeg-$(FFMPEG_VER)-hls_replace_key_uri.patch
+
 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)-increase_buffer_size.patch; \
-               $(PATCH)/ffmpeg/ffmpeg-$(FFMPEG_VER)-optimize_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)-hls_replace_key_uri.patch; \
+               for i in $(FFMPEG_PATCHES); do \
+                       echo -e "==> $(TERM_RED)Applying Patch:$(TERM_NORMAL) $$i"; \
+                       $(PATCH)/ffmpeg/$$i; \
+               done; \
                $(BUILDENV) \
                ./configure \
                        $(FFMPEG_CONFIGURE) \
index d248858ae5a6a6f364ffe834a0e5f7ff323feb48..337342a552e0ef433f4881409146caf2f06627ad 100644 (file)
@@ -63,7 +63,7 @@ FBSHOT_VER = 0.3
 
 # FFMPEG | A complete, cross-platform solution to record, convert and stream audio and video
 ifeq ($(BOXTYPE), armbox)
-FFMPEG_VER = 4.0.2
+FFMPEG_VER = 4.0.3
 else
 FFMPEG_GIT = 2ba896f
 endif