Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
From 65624c5e5a0427461d43feaadec6d780de71fcbb Mon Sep 17 00:00:00 2001
From: Justin <qianyoushi@gmail.com>
Date: Wed, 19 Aug 2026 12:06:29 +0800
Subject: [PATCH] bluray probe streams from later playlist clips

---
libavformat/bluray.c | 121 +++++++++++++++++++++++++++++++++++++++++++
libavformat/demux.c | 14 +++++
2 files changed, 135 insertions(+)

diff --git a/libavformat/bluray.c b/libavformat/bluray.c
index 2bed615..c171b96 100644
--- a/libavformat/bluray.c
+++ b/libavformat/bluray.c
@@ -179,6 +179,125 @@ static void bluray_set_stream_language(URLContext *h, AVStream *st,
av_dict_set(&st->metadata, "language", lang, 0);
}

+static int bluray_pid_seen_before(const BLURAY_TITLE_INFO *title_info,
+ enum AVMediaType type, uint32_t clip_idx,
+ int pid)
+{
+ uint32_t i;
+
+ for (i = 0; i < clip_idx; i++) {
+ const BLURAY_CLIP_INFO *clip = &title_info->clips[i];
+ const BLURAY_STREAM_INFO *streams;
+ int stream_count;
+ int j;
+
+ if (type == AVMEDIA_TYPE_AUDIO) {
+ streams = clip->audio_streams;
+ stream_count = clip->audio_stream_count;
+ } else {
+ streams = clip->pg_streams;
+ stream_count = clip->pg_stream_count;
+ }
+
+ for (j = 0; j < stream_count; j++) {
+ if (streams[j].pid == pid)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static uint64_t bluray_latest_deferred_stream_time(const BLURAY_TITLE_INFO *title_info)
+{
+ uint64_t latest_start_time = 0;
+ uint32_t clip_idx;
+
+ for (clip_idx = 1; clip_idx < title_info->clip_count; clip_idx++) {
+ const BLURAY_CLIP_INFO *clip = &title_info->clips[clip_idx];
+ const BLURAY_STREAM_INFO *streams[] = {
+ clip->audio_streams,
+ clip->pg_streams,
+ };
+ const int stream_counts[] = {
+ clip->audio_stream_count,
+ clip->pg_stream_count,
+ };
+ const enum AVMediaType types[] = {
+ AVMEDIA_TYPE_AUDIO,
+ AVMEDIA_TYPE_SUBTITLE,
+ };
+ int group_idx;
+
+ for (group_idx = 0; group_idx < FF_ARRAY_ELEMS(streams); group_idx++) {
+ int stream_idx;
+
+ for (stream_idx = 0; stream_idx < stream_counts[group_idx]; stream_idx++) {
+ int pid = streams[group_idx][stream_idx].pid;
+
+ if (pid > 0 &&
+ !bluray_pid_seen_before(title_info, types[group_idx],
+ clip_idx, pid)) {
+ latest_start_time = FFMAX(latest_start_time,
+ clip->start_time);
+ }
+ }
+ }
+ }
+
+ return latest_start_time;
+}
+
+#define BLURAY_PROBE_MARGIN (3LL * AV_TIME_BASE)
+#define BLURAY_PROBE_BITRATE 64000000LL
+#define BLURAY_MAX_PROBE_SIZE (256LL * 1024 * 1024)
+
+static void bluray_configure_stream_probe(URLContext *h, AVFormatContext *ic,
+ const BLURAY_TITLE_INFO *title_info)
+{
+ uint64_t deferred_start_time;
+ int64_t analyze_duration;
+ int64_t probe_size;
+ int64_t uncapped_probe_size;
+
+ deferred_start_time = bluray_latest_deferred_stream_time(title_info);
+ if (!deferred_start_time)
+ return;
+
+ analyze_duration = av_rescale_q(deferred_start_time,
+ (AVRational){ 1, 90000 },
+ AV_TIME_BASE_Q);
+ analyze_duration = FFMIN(analyze_duration, INT64_MAX - BLURAY_PROBE_MARGIN) +
+ BLURAY_PROBE_MARGIN;
+ uncapped_probe_size = av_rescale(analyze_duration, BLURAY_PROBE_BITRATE,
+ 8LL * AV_TIME_BASE);
+ probe_size = FFMIN(uncapped_probe_size, BLURAY_MAX_PROBE_SIZE);
+
+ if (ic->max_analyze_duration >= analyze_duration &&
+ ic->probesize >= probe_size)
+ return;
+
+ if (uncapped_probe_size > BLURAY_MAX_PROBE_SIZE) {
+ av_log(h, AV_LOG_WARNING,
+ "bluray deferred streams require probe size %"PRId64
+ ", capped at %"PRId64" bytes\n",
+ uncapped_probe_size, BLURAY_MAX_PROBE_SIZE);
+ }
+
+ av_log(h, AV_LOG_INFO,
+ "bluray deferred streams start by %.3f seconds; "
+ "analyzeduration %"PRId64" -> %"PRId64
+ ", probesize %"PRId64" -> %"PRId64"\n",
+ deferred_start_time / 90000.0,
+ ic->max_analyze_duration,
+ FFMAX(ic->max_analyze_duration, analyze_duration),
+ ic->probesize, FFMAX(ic->probesize, probe_size));
+
+ ic->max_analyze_duration = FFMAX(ic->max_analyze_duration,
+ analyze_duration);
+ ic->probesize = FFMAX(ic->probesize, probe_size);
+}
+
static int bluray_close(URLContext *h)
{
BlurayContext *bd = h->priv_data;
@@ -378,6 +497,8 @@ static int bluray_parse_priv(AVFormatContext *ic, URLContext *h)
goto fail;
}

+ bluray_configure_stream_probe(h, ic, title_info);
+
for (i = 0; i < ic->nb_streams; i++) {
bluray_set_stream_language(h, ic->streams[i], title_info);
}
diff --git a/libavformat/demux.c b/libavformat/demux.c
index f40defa..1d10292 100644
--- a/libavformat/demux.c
+++ b/libavformat/demux.c
@@ -50,6 +50,18 @@
#include "internal.h"
#include "url.h"

+static void call_url_parse_priv(AVFormatContext *s)
+{
+ URLContext *url_context;
+
+ if (!s->pb)
+ return;
+
+ url_context = ffio_geturlcontext(s->pb);
+ if (url_context && url_context->prot && url_context->prot->url_parse_priv)
+ url_context->prot->url_parse_priv(s, url_context);
+}
+
static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp)
{
const FFStream *const sti = cffstream(st);
@@ -3245,6 +3257,8 @@ find_stream_info_err:
av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
avio_tell(ic->pb), ctx->bytes_read, ctx->seek_count, count);
}
+ if (ret >= 0)
+ call_url_parse_priv(ic);
return ret;

unref_then_goto_end:
Loading