diff --git a/patches/5.1/0032-hls-support-segments-pretend-to-be-gif-png.patch b/patches/5.1/0032-hls-support-segments-pretend-to-be-gif-png.patch index 235eeb9..5492dde 100644 --- a/patches/5.1/0032-hls-support-segments-pretend-to-be-gif-png.patch +++ b/patches/5.1/0032-hls-support-segments-pretend-to-be-gif-png.patch @@ -1,25 +1,17 @@ -From bbaa08785c93082c71f18cbd4cbd46bab4609e22 Mon Sep 17 00:00:00 2001 +From 99a96ed5d19e4d5656941369624c5d97c1061694 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sun, 29 Sep 2024 15:59:13 +0800 Subject: [PATCH 32/32] hls: support segments pretend to be gif & png --- - libavformat/hls.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) + libavformat/hls.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c -index bf7fdc1553..4b9bfa082b 100644 +index bf7fdc1553..3be4c267af 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c -@@ -45,6 +45,7 @@ - #include "id3v2.h" - - #include "hls_sample_encryption.h" -+#include "libavcodec/gif.h" - - #define INITIAL_BUFFER_SIZE 32768 - -@@ -220,6 +221,7 @@ typedef struct HLSContext { +@@ -220,6 +220,7 @@ typedef struct HLSContext { AVIOInterruptCB *interrupt_callback; AVDictionary *avio_opts; AVDictionary *seg_format_opts; @@ -27,23 +19,31 @@ index bf7fdc1553..4b9bfa082b 100644 char *allowed_extensions; int max_reload; int http_persistent; -@@ -2101,7 +2103,22 @@ static int hls_read_header(AVFormatContext *s) +@@ -2101,7 +2102,30 @@ static int hls_read_header(AVFormatContext *s) pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; pls->ctx->interrupt_callback = s->interrupt_callback; url = av_strdup(pls->segments[0]->url); - ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0); + unsigned skip = 0; + if (!c->seg_allow_img) { -+ uint8_t b[10] = { 0 }; ++ uint8_t b[10] = { 0 }; // probe at most 10 + avio_read(&pls->pb.pub, b, sizeof(b)); + avio_seek(&pls->pb.pub, 0, SEEK_SET); -+ if (AV_RB64(b) == 0x89504e470d0a1a0a) { -+ skip = 3; -+ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); -+ } else if ((memcmp(b, gif87a_sig, 6) == 0 || memcmp(b, gif89a_sig, 6) == 0) -+ && (AV_RL16(&b[6]) && AV_RL16(&b[8]))) { -+ skip = 10; -+ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ const AVProbeData pd = { ++ .buf = b, // png, gif read_probe only use this field ++ .buf_size = sizeof(b), ++ }; ++// optional: ffifmt(av_find_input_format("gif" or "gif_pipe" or "png_pipe"))->read_probe ++ int max_score = AVPROBE_SCORE_MAX - 2; // png_pipe, gif, gif_pipe score >= AVPROBE_SCORE_MAX - 1 ++ const AVInputFormat* img_fmt = av_probe_input_format2(&pd, 1, &max_score); // ++ if (img_fmt) { ++ if (av_strstart(img_fmt->name, "png", NULL)) { // "png_pipe" ++ skip = 3; // skip until ts sync byte 'G'(0x47) ++ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); ++ } else if (av_strstart(img_fmt->name, "gif", NULL)) { // "gif", "gif_pipe" ++ skip = 10; ++ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ } + } + } + @@ -51,11 +51,11 @@ index bf7fdc1553..4b9bfa082b 100644 if (ret < 0) { /* Free the ctx - it isn't initialized properly at this point, * so avformat_close_input shouldn't be called. If -@@ -2549,6 +2566,8 @@ static const AVOption hls_options[] = { +@@ -2549,6 +2573,8 @@ static const AVOption hls_options[] = { OFFSET(http_seekable), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, FLAGS}, {"seg_format_options", "Set options for segment demuxer", OFFSET(seg_format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, -+ {"seg_allow_img", "Allow segments detected as images, 0 = disable, 1 = enable", ++ {"seg_allow_img", "Allow segments detected as gif and png images, 0 = disable, 1 = enable", + OFFSET(seg_allow_img), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS}, {NULL} }; diff --git a/patches/6.0/0031-hls-support-segments-pretend-to-be-gif-png.patch b/patches/6.0/0031-hls-support-segments-pretend-to-be-gif-png.patch new file mode 100644 index 0000000..cb07f28 --- /dev/null +++ b/patches/6.0/0031-hls-support-segments-pretend-to-be-gif-png.patch @@ -0,0 +1,65 @@ +From fb0d157faac343e02a02689f799bc16523f6ca75 Mon Sep 17 00:00:00 2001 +From: wang-bin +Date: Sun, 29 Sep 2024 15:59:13 +0800 +Subject: [PATCH 31/31] hls: support segments pretend to be gif & png + +--- + libavformat/hls.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/libavformat/hls.c b/libavformat/hls.c +index ce791e0123..38b37bf70a 100644 +--- a/libavformat/hls.c ++++ b/libavformat/hls.c +@@ -220,6 +220,7 @@ typedef struct HLSContext { + AVIOInterruptCB *interrupt_callback; + AVDictionary *avio_opts; + AVDictionary *seg_format_opts; ++ int seg_allow_img; + char *allowed_extensions; + int max_reload; + int http_persistent; +@@ -2112,7 +2113,30 @@ static int hls_read_header(AVFormatContext *s) + pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; + pls->ctx->interrupt_callback = s->interrupt_callback; + url = av_strdup(pls->segments[0]->url); +- ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0); ++ unsigned skip = 0; ++ if (!c->seg_allow_img) { ++ uint8_t b[10] = { 0 }; // probe at most 10 ++ avio_read(&pls->pb.pub, b, sizeof(b)); ++ avio_seek(&pls->pb.pub, 0, SEEK_SET); ++ const AVProbeData pd = { ++ .buf = b, // png, gif read_probe only use this field ++ .buf_size = sizeof(b), ++ }; ++// optional: ffifmt(av_find_input_format("gif" or "gif_pipe" or "png_pipe"))->read_probe ++ int max_score = AVPROBE_SCORE_MAX - 2; // png_pipe, gif, gif_pipe score >= AVPROBE_SCORE_MAX - 1 ++ const AVInputFormat* img_fmt = av_probe_input_format2(&pd, 1, &max_score); // ++ if (img_fmt) { ++ if (av_strstart(img_fmt->name, "png", NULL)) { // "png_pipe" ++ skip = 3; // skip until ts sync byte 'G'(0x47) ++ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); ++ } else if (av_strstart(img_fmt->name, "gif", NULL)) { // "gif", "gif_pipe" ++ skip = 10; ++ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ } ++ } ++ } ++ ++ ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, skip, 0); + if (ret < 0) { + /* Free the ctx - it isn't initialized properly at this point, + * so avformat_close_input shouldn't be called. If +@@ -2562,6 +2586,8 @@ static const AVOption hls_options[] = { + OFFSET(seg_format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, + {"seg_max_retry", "Maximum number of times to reload a segment on error.", + OFFSET(seg_max_retry), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS}, ++ {"seg_allow_img", "Allow segments detected as gif and png images, 0 = disable, 1 = enable", ++ OFFSET(seg_allow_img), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS}, + {NULL} + }; + +-- +2.39.5 (Apple Git-154) + diff --git a/patches/6.1/0032-hls-support-segments-pretend-to-be-gif-png.patch b/patches/6.1/0032-hls-support-segments-pretend-to-be-gif-png.patch index f331f0a..1cc33c3 100644 --- a/patches/6.1/0032-hls-support-segments-pretend-to-be-gif-png.patch +++ b/patches/6.1/0032-hls-support-segments-pretend-to-be-gif-png.patch @@ -1,25 +1,17 @@ -From 5b5b8a4c8a8af68d20bf3f60a47bfef62c5d5adc Mon Sep 17 00:00:00 2001 +From d61748699d0f0fcdb6136d81fc41b026b9bfcf9b Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sun, 29 Sep 2024 15:59:13 +0800 Subject: [PATCH 32/32] hls: support segments pretend to be gif & png --- - libavformat/hls.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) + libavformat/hls.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c -index f5f549b24d..c14676f1d5 100644 +index f5f549b24d..e9c1698e0d 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c -@@ -46,6 +46,7 @@ - #include "url.h" - - #include "hls_sample_encryption.h" -+#include "libavcodec/gif.h" - - #define INITIAL_BUFFER_SIZE 32768 - -@@ -221,6 +222,7 @@ typedef struct HLSContext { +@@ -221,6 +221,7 @@ typedef struct HLSContext { AVIOInterruptCB *interrupt_callback; AVDictionary *avio_opts; AVDictionary *seg_format_opts; @@ -27,23 +19,31 @@ index f5f549b24d..c14676f1d5 100644 char *allowed_extensions; int max_reload; int http_persistent; -@@ -2104,7 +2106,22 @@ static int hls_read_header(AVFormatContext *s) +@@ -2104,7 +2105,30 @@ static int hls_read_header(AVFormatContext *s) pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; pls->ctx->interrupt_callback = s->interrupt_callback; url = av_strdup(pls->segments[0]->url); - ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0); + unsigned skip = 0; + if (!c->seg_allow_img) { -+ uint8_t b[10] = { 0 }; ++ uint8_t b[10] = { 0 }; // probe at most 10 + avio_read(&pls->pb.pub, b, sizeof(b)); + avio_seek(&pls->pb.pub, 0, SEEK_SET); -+ if (AV_RB64(b) == 0x89504e470d0a1a0a) { -+ skip = 3; -+ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); -+ } else if ((memcmp(b, gif87a_sig, 6) == 0 || memcmp(b, gif89a_sig, 6) == 0) -+ && (AV_RL16(&b[6]) && AV_RL16(&b[8]))) { -+ skip = 10; -+ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ const AVProbeData pd = { ++ .buf = b, // png, gif read_probe only use this field ++ .buf_size = sizeof(b), ++ }; ++// optional: ffifmt(av_find_input_format("gif" or "gif_pipe" or "png_pipe"))->read_probe ++ int max_score = AVPROBE_SCORE_MAX - 2; // png_pipe, gif, gif_pipe score >= AVPROBE_SCORE_MAX - 1 ++ const AVInputFormat* img_fmt = av_probe_input_format2(&pd, 1, &max_score); // ++ if (img_fmt) { ++ if (av_strstart(img_fmt->name, "png", NULL)) { // "png_pipe" ++ skip = 3; // skip until ts sync byte 'G'(0x47) ++ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); ++ } else if (av_strstart(img_fmt->name, "gif", NULL)) { // "gif", "gif_pipe" ++ skip = 10; ++ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ } + } + } + @@ -51,11 +51,11 @@ index f5f549b24d..c14676f1d5 100644 if (ret < 0) { /* Free the ctx - it isn't initialized properly at this point, * so avformat_close_input shouldn't be called. If -@@ -2579,6 +2596,8 @@ static const AVOption hls_options[] = { +@@ -2579,6 +2603,8 @@ static const AVOption hls_options[] = { OFFSET(seg_format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, {"seg_max_retry", "Maximum number of times to reload a segment on error.", OFFSET(seg_max_retry), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS}, -+ {"seg_allow_img", "Allow segments detected as images, 0 = disable, 1 = enable", ++ {"seg_allow_img", "Allow segments detected as gif and png images, 0 = disable, 1 = enable", + OFFSET(seg_allow_img), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS}, {NULL} }; diff --git a/patches/master/0030-hls-support-segments-pretend-to-be-gif-png.patch b/patches/master/0030-hls-support-segments-pretend-to-be-gif-png.patch index 750afad..cebf706 100644 --- a/patches/master/0030-hls-support-segments-pretend-to-be-gif-png.patch +++ b/patches/master/0030-hls-support-segments-pretend-to-be-gif-png.patch @@ -1,25 +1,17 @@ -From ecda273842418e9827cab2a193138060a4224629 Mon Sep 17 00:00:00 2001 +From a5c5359023c696e002f9c52721452c3c4d719a1f Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sun, 29 Sep 2024 15:59:13 +0800 Subject: [PATCH 30/30] hls: support segments pretend to be gif & png --- - libavformat/hls.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) + libavformat/hls.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/libavformat/hls.c b/libavformat/hls.c -index 62473a15dd..2fd7f8ca2f 100644 +index 62473a15dd..7aa18079d9 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c -@@ -47,6 +47,7 @@ - #include "url.h" - - #include "hls_sample_encryption.h" -+#include "libavcodec/gif.h" - - #define INITIAL_BUFFER_SIZE 32768 - -@@ -222,6 +223,7 @@ typedef struct HLSContext { +@@ -222,6 +222,7 @@ typedef struct HLSContext { AVIOInterruptCB *interrupt_callback; AVDictionary *avio_opts; AVDictionary *seg_format_opts; @@ -27,23 +19,31 @@ index 62473a15dd..2fd7f8ca2f 100644 char *allowed_extensions; int max_reload; int http_persistent; -@@ -2113,7 +2115,22 @@ static int hls_read_header(AVFormatContext *s) +@@ -2113,7 +2114,30 @@ static int hls_read_header(AVFormatContext *s) pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; pls->ctx->interrupt_callback = s->interrupt_callback; url = av_strdup(pls->segments[0]->url); - ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0); + unsigned skip = 0; + if (!c->seg_allow_img) { -+ uint8_t b[10] = { 0 }; ++ uint8_t b[10] = { 0 }; // probe at most 10 + avio_read(&pls->pb.pub, b, sizeof(b)); + avio_seek(&pls->pb.pub, 0, SEEK_SET); -+ if (AV_RB64(b) == 0x89504e470d0a1a0a) { -+ skip = 3; -+ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); -+ } else if ((memcmp(b, gif87a_sig, 6) == 0 || memcmp(b, gif89a_sig, 6) == 0) -+ && (AV_RL16(&b[6]) && AV_RL16(&b[8]))) { -+ skip = 10; -+ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ const AVProbeData pd = { ++ .buf = b, // png, gif read_probe only use this field ++ .buf_size = sizeof(b), ++ }; ++// optional: ffifmt(av_find_input_format("gif" or "gif_pipe" or "png_pipe"))->read_probe ++ int max_score = AVPROBE_SCORE_MAX - 2; // png_pipe, gif, gif_pipe score >= AVPROBE_SCORE_MAX - 1 ++ const AVInputFormat* img_fmt = av_probe_input_format2(&pd, 1, &max_score); // ++ if (img_fmt) { ++ if (av_strstart(img_fmt->name, "png", NULL)) { // "png_pipe" ++ skip = 3; // skip until ts sync byte 'G'(0x47) ++ av_log(s, AV_LOG_INFO, "segments pretend to be png\n"); ++ } else if (av_strstart(img_fmt->name, "gif", NULL)) { // "gif", "gif_pipe" ++ skip = 10; ++ av_log(s, AV_LOG_INFO, "segments pretend to be gif\n"); ++ } + } + } + @@ -51,11 +51,11 @@ index 62473a15dd..2fd7f8ca2f 100644 if (ret < 0) { /* Free the ctx - it isn't initialized properly at this point, * so avformat_close_input shouldn't be called. If -@@ -2590,6 +2607,8 @@ static const AVOption hls_options[] = { +@@ -2590,6 +2614,8 @@ static const AVOption hls_options[] = { OFFSET(seg_format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, {"seg_max_retry", "Maximum number of times to reload a segment on error.", OFFSET(seg_max_retry), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS}, -+ {"seg_allow_img", "Allow segments detected as images, 0 = disable, 1 = enable", ++ {"seg_allow_img", "Allow segments detected as gif and png images, 0 = disable, 1 = enable", + OFFSET(seg_allow_img), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS}, {NULL} };