Skip to content

Commit 782ffe3

Browse files
qgewfgdebugly
authored andcommitted
ffmpeg: probe streams from later Blu-ray clips
Extend the probe budget when audio or subtitle streams first appear in later playlist clips. This allows the MPEG-TS demuxer to discover those streams normally and updates their language metadata after probing.
1 parent f632420 commit 782ffe3

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
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

Comments
 (0)