]> git.webhop.me Git - bs-cst-neutrino-hd.git/commitdiff
add hls and dash ffmpeg patches
authorMarkham <markham001@gmx.de>
Sun, 12 Feb 2023 17:52:02 +0000 (18:52 +0100)
committerMarkham <markham001@gmx.de>
Sun, 12 Feb 2023 17:52:02 +0000 (18:52 +0100)
archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-dash-hacks.patch [new file with mode: 0644]
archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-hls-changes.patch [new file with mode: 0644]

diff --git a/archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-dash-hacks.patch b/archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-dash-hacks.patch
new file mode 100644 (file)
index 0000000..5668bbd
--- /dev/null
@@ -0,0 +1,142 @@
+diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
+index 2ca91bea8b..ecaf50047d 100644
+--- a/libavformat/dashdec.c
++++ b/libavformat/dashdec.c
+@@ -441,8 +441,12 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
+         return AVERROR_INVALIDDATA;
+     av_freep(pb);
++
+     av_dict_copy(&tmp, *opts, 0);
+     av_dict_copy(&tmp, opts2, 0);
++    av_dict_set_int(&tmp, "reconnect", 1, 0);
++    av_dict_set_int(&tmp, "icy", 0, 0);
++
+     ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+     if (ret >= 0) {
+         // update cookies on http response with setcookies.
+@@ -768,7 +772,8 @@ static int resolve_content_path(AVFormatContext *s, const char *url, int *max_ur
+     baseurl = xmlNodeGetContent(node);
+     root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
+     if (node) {
+-        xmlNodeSetContent(node, root_url);
++        // HACK: SetContent fails if the URL happens to include '&', which isn't that uncommon...
++        //xmlNodeSetContent(node, root_url);
+         updated = 1;
+     }
+@@ -802,7 +807,7 @@ static int resolve_content_path(AVFormatContext *s, const char *url, int *max_ur
+                 memset(p + 1, 0, strlen(p));
+             }
+             av_strlcat(tmp_str, text + start, tmp_max_url_size);
+-            xmlNodeSetContent(baseurl_nodes[i], tmp_str);
++            //xmlNodeSetContent(baseurl_nodes[i], tmp_str);
+             updated = 1;
+             xmlFree(text);
+         }
+@@ -1217,6 +1222,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
+     char *val  = NULL;
+     uint32_t period_duration_sec = 0;
+     uint32_t period_start_sec = 0;
++    char *nfcs_key = NULL;
+     if (!in) {
+         close_in = 1;
+@@ -1335,6 +1341,12 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
+             } else if (!av_strcasecmp(node->name, "ProgramInformation")) {
+                 parse_programinformation(s, node);
+             }
++            // HACK: libvodstream stores decrypted keys in a custom tag.
++            if (!av_strcasecmp(node->name, (const char*)"nfcskey")) {
++                nfcs_key = xmlNodeGetContent(node->children);
++                c->cenc_decryption_key = av_strdup(nfcs_key);
++                xmlFree(nfcs_key);
++            }
+             node = xmlNextElementSibling(node);
+         }
+         if (!period_node) {
+@@ -1879,7 +1891,8 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
+     }
+     ffio_init_context(&pls->pb, avio_ctx_buffer, INITIAL_BUFFER_SIZE, 0,
+                       pls, read_data, NULL, c->is_live ? NULL : seek_data);
+-    pls->pb.pub.seekable = 0;
++    // PATCH: If this is 0, seeking in VOD streams downloads the entire content between origin and target.
++    pls->pb.pub.seekable = 1;
+     if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
+         goto fail;
+@@ -2167,6 +2180,7 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
+     int ret = 0, i;
+     int64_t mints = 0;
+     struct representation *cur = NULL;
++    struct representation *curHack = NULL;
+     struct representation *rep = NULL;
+     recheck_discard_flags(s, c->videos, c->n_videos);
+@@ -2188,6 +2202,7 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
+             continue;
+         if (!cur || rep->cur_timestamp < mints) {
+             cur = rep;
++            curHack = rep;
+             mints = rep->cur_timestamp;
+         }
+     }
+@@ -2203,6 +2218,7 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
+     }
+     if (!cur) {
++        av_log(s, AV_LOG_WARNING, "INVALIDDATA\n");
+         return AVERROR_INVALIDDATA;
+     }
+     while (!ff_check_interrupt(c->interrupt_callback) && !ret) {
+@@ -2221,6 +2237,26 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
+             cur->is_restart_needed = 0;
+         }
+     }
++    if (curHack && curHack != cur) {
++        cur = curHack;
++        ret = 0;
++        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;
++                ff_format_io_close(cur->parent, &cur->input);
++                ret = reopen_demux_for_component(s, cur);
++                cur->is_restart_needed = 0;
++            }
++        }
++    }
+     return AVERROR_EOF;
+ }
+@@ -2232,6 +2268,7 @@ static int dash_close(AVFormatContext *s)
+     free_subtitle_list(c);
+     av_dict_free(&c->avio_opts);
+     av_freep(&c->base_url);
++    av_freep(&c->cenc_decryption_key);
+     return 0;
+ }
+@@ -2319,10 +2356,11 @@ static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestam
+         if (!ret)
+             ret = dash_seek(s, c->audios[i], seek_pos_msec, flags, !c->audios[i]->ctx);
+     }
+-    for (i = 0; i < c->n_subtitles; i++) {
+-        if (!ret)
+-            ret = dash_seek(s, c->subtitles[i], seek_pos_msec, flags, !c->subtitles[i]->ctx);
+-    }
++    // PATCH: Seeking in subtitle streams breaks things, and it doesn't seem necessary.
++    //for (i = 0; i < c->n_subtitles; i++) {
++    //    if (!ret)
++    //        ret = dash_seek(s, c->subtitles[i], seek_pos_msec, flags, !c->subtitles[i]->ctx);
++    //}
+     return ret;
+ }
diff --git a/archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-hls-changes.patch b/archive-patches/ffmpeg-cst/5.1.2/ffmpeg51-hls-changes.patch
new file mode 100644 (file)
index 0000000..ea96739
--- /dev/null
@@ -0,0 +1,57 @@
+diff --git a/libavformat/hls.c b/libavformat/hls.c
+index e622425e80..faf92804a2 100644
+--- a/libavformat/hls.c
++++ b/libavformat/hls.c
+@@ -46,7 +46,7 @@
+ #include "hls_sample_encryption.h"
+-#define INITIAL_BUFFER_SIZE 32768
++#define INITIAL_BUFFER_SIZE 1048576
+ #define MAX_FIELD_LEN 64
+ #define MAX_CHARACTERISTICS_LEN 512
+@@ -1580,7 +1580,7 @@ reload:
+     seg = next_segment(v);
+     if (c->http_multiple == 1 && !v->input_next_requested &&
+-        seg && seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) {
++        seg && seg->key_type != KEY_AES_128 && av_strstart(seg->url, "http", NULL)) {
+         ret = open_input(c, v, seg, &v->input_next);
+         if (ret < 0) {
+             if (ff_check_interrupt(c->interrupt_callback))
+@@ -1613,7 +1613,7 @@ reload:
+         return ret;
+     }
+     if (c->http_persistent &&
+-        seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) {
++        seg->key_type != KEY_AES_128 && av_strstart(seg->url, "http", NULL)) {
+         v->input_read_done = 1;
+     } else {
+         ff_format_io_close(v->parent, &v->input);
+@@ -2475,6 +2475,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
+     /* set segment now so we do not need to search again below */
+     seek_pls->cur_seq_no = seq_no;
+     seek_pls->seek_stream_index = stream_subdemuxer_index;
++    //av_log(s, AV_LOG_INFO, "Seek to %d in %d\n", seq_no, stream_subdemuxer_index);
+     for (i = 0; i < c->n_playlists; i++) {
+         /* Reset reading */
+@@ -2535,7 +2536,7 @@ static const AVOption hls_options[] = {
+         OFFSET(prefer_x_start), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS},
+     {"allowed_extensions", "List of file extensions that hls is allowed to access",
+         OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
+-        {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"},
++        {.str = "3gp,aac,avi,ac3,eac3,flac,key,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"},
+         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},
+@@ -2544,7 +2545,7 @@ static const AVOption hls_options[] = {
+     {"http_persistent", "Use persistent HTTP connections",
+         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},
++        OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, FLAGS},
+     {"http_seekable", "Use HTTP partial requests, 0 = disable, 1 = enable, -1 = auto",
+         OFFSET(http_seekable), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, FLAGS},
+     {"seg_format_options", "Set options for segment demuxer",