|
| 1 | +From 65624c5e5a0427461d43feaadec6d780de71fcbb Mon Sep 17 00:00:00 2001 |
| 2 | +From: Justin <qianyoushi@gmail.com> |
| 3 | +Date: Wed, 19 Aug 2026 12:06:29 +0800 |
| 4 | +Subject: [PATCH] bluray probe streams from later playlist clips |
| 5 | + |
| 6 | +--- |
| 7 | + libavformat/bluray.c | 121 +++++++++++++++++++++++++++++++++++++++++++ |
| 8 | + libavformat/demux.c | 14 +++++ |
| 9 | + 2 files changed, 135 insertions(+) |
| 10 | + |
| 11 | +diff --git a/libavformat/bluray.c b/libavformat/bluray.c |
| 12 | +index 2bed615..c171b96 100644 |
| 13 | +--- a/libavformat/bluray.c |
| 14 | ++++ b/libavformat/bluray.c |
| 15 | +@@ -179,6 +179,125 @@ static void bluray_set_stream_language(URLContext *h, AVStream *st, |
| 16 | + av_dict_set(&st->metadata, "language", lang, 0); |
| 17 | + } |
| 18 | + |
| 19 | ++static int bluray_pid_seen_before(const BLURAY_TITLE_INFO *title_info, |
| 20 | ++ enum AVMediaType type, uint32_t clip_idx, |
| 21 | ++ int pid) |
| 22 | ++{ |
| 23 | ++ uint32_t i; |
| 24 | ++ |
| 25 | ++ for (i = 0; i < clip_idx; i++) { |
| 26 | ++ const BLURAY_CLIP_INFO *clip = &title_info->clips[i]; |
| 27 | ++ const BLURAY_STREAM_INFO *streams; |
| 28 | ++ int stream_count; |
| 29 | ++ int j; |
| 30 | ++ |
| 31 | ++ if (type == AVMEDIA_TYPE_AUDIO) { |
| 32 | ++ streams = clip->audio_streams; |
| 33 | ++ stream_count = clip->audio_stream_count; |
| 34 | ++ } else { |
| 35 | ++ streams = clip->pg_streams; |
| 36 | ++ stream_count = clip->pg_stream_count; |
| 37 | ++ } |
| 38 | ++ |
| 39 | ++ for (j = 0; j < stream_count; j++) { |
| 40 | ++ if (streams[j].pid == pid) |
| 41 | ++ return 1; |
| 42 | ++ } |
| 43 | ++ } |
| 44 | ++ |
| 45 | ++ return 0; |
| 46 | ++} |
| 47 | ++ |
| 48 | ++static uint64_t bluray_latest_deferred_stream_time(const BLURAY_TITLE_INFO *title_info) |
| 49 | ++{ |
| 50 | ++ uint64_t latest_start_time = 0; |
| 51 | ++ uint32_t clip_idx; |
| 52 | ++ |
| 53 | ++ for (clip_idx = 1; clip_idx < title_info->clip_count; clip_idx++) { |
| 54 | ++ const BLURAY_CLIP_INFO *clip = &title_info->clips[clip_idx]; |
| 55 | ++ const BLURAY_STREAM_INFO *streams[] = { |
| 56 | ++ clip->audio_streams, |
| 57 | ++ clip->pg_streams, |
| 58 | ++ }; |
| 59 | ++ const int stream_counts[] = { |
| 60 | ++ clip->audio_stream_count, |
| 61 | ++ clip->pg_stream_count, |
| 62 | ++ }; |
| 63 | ++ const enum AVMediaType types[] = { |
| 64 | ++ AVMEDIA_TYPE_AUDIO, |
| 65 | ++ AVMEDIA_TYPE_SUBTITLE, |
| 66 | ++ }; |
| 67 | ++ int group_idx; |
| 68 | ++ |
| 69 | ++ for (group_idx = 0; group_idx < FF_ARRAY_ELEMS(streams); group_idx++) { |
| 70 | ++ int stream_idx; |
| 71 | ++ |
| 72 | ++ for (stream_idx = 0; stream_idx < stream_counts[group_idx]; stream_idx++) { |
| 73 | ++ int pid = streams[group_idx][stream_idx].pid; |
| 74 | ++ |
| 75 | ++ if (pid > 0 && |
| 76 | ++ !bluray_pid_seen_before(title_info, types[group_idx], |
| 77 | ++ clip_idx, pid)) { |
| 78 | ++ latest_start_time = FFMAX(latest_start_time, |
| 79 | ++ clip->start_time); |
| 80 | ++ } |
| 81 | ++ } |
| 82 | ++ } |
| 83 | ++ } |
| 84 | ++ |
| 85 | ++ return latest_start_time; |
| 86 | ++} |
| 87 | ++ |
| 88 | ++#define BLURAY_PROBE_MARGIN (3LL * AV_TIME_BASE) |
| 89 | ++#define BLURAY_PROBE_BITRATE 64000000LL |
| 90 | ++#define BLURAY_MAX_PROBE_SIZE (256LL * 1024 * 1024) |
| 91 | ++ |
| 92 | ++static void bluray_configure_stream_probe(URLContext *h, AVFormatContext *ic, |
| 93 | ++ const BLURAY_TITLE_INFO *title_info) |
| 94 | ++{ |
| 95 | ++ uint64_t deferred_start_time; |
| 96 | ++ int64_t analyze_duration; |
| 97 | ++ int64_t probe_size; |
| 98 | ++ int64_t uncapped_probe_size; |
| 99 | ++ |
| 100 | ++ deferred_start_time = bluray_latest_deferred_stream_time(title_info); |
| 101 | ++ if (!deferred_start_time) |
| 102 | ++ return; |
| 103 | ++ |
| 104 | ++ analyze_duration = av_rescale_q(deferred_start_time, |
| 105 | ++ (AVRational){ 1, 90000 }, |
| 106 | ++ AV_TIME_BASE_Q); |
| 107 | ++ analyze_duration = FFMIN(analyze_duration, INT64_MAX - BLURAY_PROBE_MARGIN) + |
| 108 | ++ BLURAY_PROBE_MARGIN; |
| 109 | ++ uncapped_probe_size = av_rescale(analyze_duration, BLURAY_PROBE_BITRATE, |
| 110 | ++ 8LL * AV_TIME_BASE); |
| 111 | ++ probe_size = FFMIN(uncapped_probe_size, BLURAY_MAX_PROBE_SIZE); |
| 112 | ++ |
| 113 | ++ if (ic->max_analyze_duration >= analyze_duration && |
| 114 | ++ ic->probesize >= probe_size) |
| 115 | ++ return; |
| 116 | ++ |
| 117 | ++ if (uncapped_probe_size > BLURAY_MAX_PROBE_SIZE) { |
| 118 | ++ av_log(h, AV_LOG_WARNING, |
| 119 | ++ "bluray deferred streams require probe size %"PRId64 |
| 120 | ++ ", capped at %"PRId64" bytes\n", |
| 121 | ++ uncapped_probe_size, BLURAY_MAX_PROBE_SIZE); |
| 122 | ++ } |
| 123 | ++ |
| 124 | ++ av_log(h, AV_LOG_INFO, |
| 125 | ++ "bluray deferred streams start by %.3f seconds; " |
| 126 | ++ "analyzeduration %"PRId64" -> %"PRId64 |
| 127 | ++ ", probesize %"PRId64" -> %"PRId64"\n", |
| 128 | ++ deferred_start_time / 90000.0, |
| 129 | ++ ic->max_analyze_duration, |
| 130 | ++ FFMAX(ic->max_analyze_duration, analyze_duration), |
| 131 | ++ ic->probesize, FFMAX(ic->probesize, probe_size)); |
| 132 | ++ |
| 133 | ++ ic->max_analyze_duration = FFMAX(ic->max_analyze_duration, |
| 134 | ++ analyze_duration); |
| 135 | ++ ic->probesize = FFMAX(ic->probesize, probe_size); |
| 136 | ++} |
| 137 | ++ |
| 138 | + static int bluray_close(URLContext *h) |
| 139 | + { |
| 140 | + BlurayContext *bd = h->priv_data; |
| 141 | +@@ -378,6 +497,8 @@ static int bluray_parse_priv(AVFormatContext *ic, URLContext *h) |
| 142 | + goto fail; |
| 143 | + } |
| 144 | + |
| 145 | ++ bluray_configure_stream_probe(h, ic, title_info); |
| 146 | ++ |
| 147 | + for (i = 0; i < ic->nb_streams; i++) { |
| 148 | + bluray_set_stream_language(h, ic->streams[i], title_info); |
| 149 | + } |
| 150 | +diff --git a/libavformat/demux.c b/libavformat/demux.c |
| 151 | +index f40defa..1d10292 100644 |
| 152 | +--- a/libavformat/demux.c |
| 153 | ++++ b/libavformat/demux.c |
| 154 | +@@ -50,6 +50,18 @@ |
| 155 | + #include "internal.h" |
| 156 | + #include "url.h" |
| 157 | + |
| 158 | ++static void call_url_parse_priv(AVFormatContext *s) |
| 159 | ++{ |
| 160 | ++ URLContext *url_context; |
| 161 | ++ |
| 162 | ++ if (!s->pb) |
| 163 | ++ return; |
| 164 | ++ |
| 165 | ++ url_context = ffio_geturlcontext(s->pb); |
| 166 | ++ if (url_context && url_context->prot && url_context->prot->url_parse_priv) |
| 167 | ++ url_context->prot->url_parse_priv(s, url_context); |
| 168 | ++} |
| 169 | ++ |
| 170 | + static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp) |
| 171 | + { |
| 172 | + const FFStream *const sti = cffstream(st); |
| 173 | +@@ -3245,6 +3257,8 @@ find_stream_info_err: |
| 174 | + av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n", |
| 175 | + avio_tell(ic->pb), ctx->bytes_read, ctx->seek_count, count); |
| 176 | + } |
| 177 | ++ if (ret >= 0) |
| 178 | ++ call_url_parse_priv(ic); |
| 179 | + return ret; |
| 180 | + |
| 181 | + unref_then_goto_end: |
0 commit comments