Skip to content

Commit 5ea03e5

Browse files
qgewfgdebugly
authored andcommitted
ffmpeg7: split Blu-ray language parsing and fix PID mapping
1 parent 7783f0e commit 5ea03e5

2 files changed

Lines changed: 208 additions & 89 deletions

File tree

patches/ffmpeg-n7.1.1/0027-custom-bluray-fs-for-network-Blu-ray-Disc-and-BDMV.patch

Lines changed: 12 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
From 5582bd1c8aa667f9dc0ca6c14ffb916e7a666c0e Mon Sep 17 00:00:00 2001
1+
From 4fd069b5ab73b35872f01657cb274db8afae5663 Mon Sep 17 00:00:00 2001
22
From: qianlongxu <qianlongxu@gmail.com>
33
Date: Tue, 12 May 2026 16:26:37 +0800
44
Subject: [PATCH] custom bluray fs for network Blu-ray Disc and BDMV
55

66
---
77
libavformat/Makefile | 2 +-
8-
libavformat/bluray.c | 128 ++++++++-
8+
libavformat/bluray.c | 63 ++++-
99
libavformat/bluray_custom_fs.c | 459 +++++++++++++++++++++++++++++++++
1010
libavformat/bluray_custom_fs.h | 33 +++
11-
4 files changed, 610 insertions(+), 12 deletions(-)
11+
4 files changed, 544 insertions(+), 13 deletions(-)
1212
create mode 100644 libavformat/bluray_custom_fs.c
1313
create mode 100644 libavformat/bluray_custom_fs.h
1414

@@ -26,10 +26,10 @@ index e299e72..1f32e4c 100644
2626
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
2727
OBJS-$(CONFIG_CONCATF_PROTOCOL) += concat.o
2828
diff --git a/libavformat/bluray.c b/libavformat/bluray.c
29-
index 1845551..eb43340 100644
29+
index 1845551..f23bfa4 100644
3030
--- a/libavformat/bluray.c
3131
+++ b/libavformat/bluray.c
32-
@@ -21,23 +21,27 @@
32+
@@ -21,19 +21,21 @@
3333
*/
3434

3535
#include <libbluray/bluray.h>
@@ -40,7 +40,6 @@ index 1845551..eb43340 100644
4040
#include "libavutil/opt.h"
4141
+#include "bluray_custom_fs.h"
4242
+#include "libavutil/dict.h"
43-
+#include "libavformat/avformat.h"
4443

4544
-#define BLURAY_PROTO_PREFIX "bluray:"
4645
+#define BLURAY_PROTO_PREFIX "bluray://"
@@ -55,12 +54,7 @@ index 1845551..eb43340 100644
5554
int playlist;
5655
int angle;
5756
int chapter;
58-
/*int region;*/
59-
+ int title_idx;
60-
} BlurayContext;
61-
62-
#define OFFSET(x) offsetof(BlurayContext, x)
63-
@@ -106,23 +110,58 @@ static int bluray_close(URLContext *h)
57+
@@ -106,23 +108,57 @@ static int bluray_close(URLContext *h)
6458
if (bd->bd) {
6559
bd_close(bd->bd);
6660
}
@@ -75,16 +69,15 @@ index 1845551..eb43340 100644
7569
+#define BLURAY_DEBUG_MASK 0xFFFFF //(0xFFFFF & ~DBG_STREAM)
7670
+
7771
+static void bluray_DebugHandler(const char *psz)
78-
{
72+
+{
7973
+ size_t len = strlen(psz);
8074
+ if(len < 1) return;
8175
+ av_log(NULL, AV_LOG_INFO, "[bluray] %s\n",psz);
8276
+}
8377
+#endif
8478
+
85-
+
8679
+static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary **options)
87-
+{
80+
{
8881
+#ifdef DEBUG_BLURAY
8982
+ bd_set_debug_mask(BLURAY_DEBUG_MASK);
9083
+ bd_set_debug_handler(bluray_DebugHandler);
@@ -123,7 +116,7 @@ index 1845551..eb43340 100644
123116

124117
/* check if disc can be played */
125118
if (check_disc_info(h) < 0) {
126-
@@ -150,6 +189,9 @@ static int bluray_open(URLContext *h, const char *path, int flags)
119+
@@ -150,6 +186,9 @@ static int bluray_open(URLContext *h, const char *path, int flags)
127120
int i;
128121
for (i = 0; i < num_title_idx; i++) {
129122
BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0);
@@ -133,13 +126,7 @@ index 1845551..eb43340 100644
133126

134127
av_log(h, AV_LOG_INFO, "playlist %05d.mpls (%d:%02d:%02d)\n",
135128
info->playlist,
136-
@@ -159,17 +201,19 @@ static int bluray_open(URLContext *h, const char *path, int flags)
137-
138-
if (info->duration > duration) {
139-
bd->playlist = info->playlist;
140-
+ bd->title_idx = i;
141-
duration = info->duration;
142-
}
129+
@@ -164,12 +203,13 @@ static int bluray_open(URLContext *h, const char *path, int flags)
143130

144131
bd_free_title_info(info);
145132
}
@@ -156,83 +143,19 @@ index 1845551..eb43340 100644
156143
return AVERROR(EIO);
157144
}
158145

159-
@@ -222,13 +266,75 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
146+
@@ -222,11 +262,10 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
160147
return AVERROR(EINVAL);
161148
}
162149

163-
+static int bluray_parse_priv(AVFormatContext *ic, URLContext *h)
164-
+{
165-
+ BlurayContext *bd = h->priv_data;
166-
+ BLURAY_TITLE_INFO *title_info = NULL;
167-
+ BLURAY_CLIP_INFO clip_info;
168-
+
169-
+ int v_idx = 0;
170-
+ int a_idx = 0;
171-
+ int s_idx = 0;
172-
+ int ret = 0;
173-
+
174-
+ if (!bd || !bd->bd) {
175-
+ return AVERROR(EFAULT);
176-
+ }
177-
+
178-
+ title_info = bd_get_title_info(bd->bd, bd->title_idx, 0);
179-
+ if (!title_info) {
180-
+ return AVERROR(EFAULT);
181-
+ }
182-
+
183-
+ if (title_info->clip_count <= 0) {
184-
+ ret = EFAULT;
185-
+ goto fail;
186-
+ }
187-
+ clip_info = title_info->clips[0];
188-
+
189-
+ for (int i = 0; i < ic->nb_streams; i++) {
190-
+ if (ic->streams[i] && ic->streams[i]->codecpar) {
191-
+ switch (ic->streams[i]->codecpar->codec_type) {
192-
+ case AVMEDIA_TYPE_VIDEO:
193-
+ if (v_idx < clip_info.video_stream_count) {
194-
+ av_log(h, AV_LOG_INFO, "video stream %d lang = %s\n", v_idx, clip_info.video_streams[v_idx].lang);
195-
+ av_dict_set(&ic->streams[i]->metadata, "language", clip_info.video_streams[v_idx].lang, AV_DICT_DONT_OVERWRITE);
196-
+ v_idx++;
197-
+ }
198-
+ break;
199-
+ case AVMEDIA_TYPE_AUDIO:
200-
+ if (a_idx < clip_info.audio_stream_count) {
201-
+ av_log(h, AV_LOG_INFO, "audio stream %d lang = %s\n", a_idx, clip_info.audio_streams[a_idx].lang);
202-
+ av_dict_set(&ic->streams[i]->metadata, "language", clip_info.audio_streams[a_idx].lang, AV_DICT_DONT_OVERWRITE);
203-
+ a_idx++;
204-
+ }
205-
+ break;
206-
+ case AVMEDIA_TYPE_SUBTITLE:
207-
+ if (s_idx < clip_info.pg_stream_count) {
208-
+ av_log(h, AV_LOG_INFO, "subtitle stream %d lang = %s\n", s_idx, clip_info.pg_streams[s_idx].lang);
209-
+ av_dict_set(&ic->streams[i]->metadata, "language", clip_info.pg_streams[s_idx].lang, AV_DICT_DONT_OVERWRITE);
210-
+ s_idx++;
211-
+ }
212-
+ break;
213-
+ default:
214-
+ break;
215-
+ }
216-
+ }
217-
+ }
218-
+
219-
+fail:
220-
+ bd_free_title_info(title_info);
221-
+
222-
+ return ret != 0 ? AVERROR(ret) : 0;
223-
+}
224-
150+
-
225151
const URLProtocol ff_bluray_protocol = {
226152
.name = "bluray",
227153
.url_close = bluray_close,
228154
- .url_open = bluray_open,
229155
+ .url_open2 = bluray_open,
230156
.url_read = bluray_read,
231157
.url_seek = bluray_seek,
232-
+ .url_parse_priv = bluray_parse_priv,
233158
.priv_data_size = sizeof(BlurayContext),
234-
.priv_data_class = &bluray_context_class,
235-
};
236159
diff --git a/libavformat/bluray_custom_fs.c b/libavformat/bluray_custom_fs.c
237160
new file mode 100644
238161
index 0000000..b82e0b2
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
From fac36cc918fb56cc1057d6d94dec6977ceaec462 Mon Sep 17 00:00:00 2001
2+
From: Justin <qianyoushi@gmail.com>
3+
Date: Mon, 27 Jul 2026 11:09:03 +0800
4+
Subject: [PATCH] bluray map stream languages by PID
5+
6+
---
7+
libavformat/bluray.c | 126 +++++++++++++++++++++++++++++++++++++++++++
8+
1 file changed, 126 insertions(+)
9+
10+
diff --git a/libavformat/bluray.c b/libavformat/bluray.c
11+
index f23bfa4..2bed615 100644
12+
--- a/libavformat/bluray.c
13+
+++ b/libavformat/bluray.c
14+
@@ -27,6 +27,7 @@
15+
#include "libavutil/opt.h"
16+
#include "bluray_custom_fs.h"
17+
#include "libavutil/dict.h"
18+
+#include "libavformat/avformat.h"
19+
20+
#define BLURAY_PROTO_PREFIX "bluray://"
21+
#define MIN_PLAYLIST_LENGTH 180 /* 3 min */
22+
@@ -40,6 +41,7 @@ typedef struct {
23+
int angle;
24+
int chapter;
25+
/*int region;*/
26+
+ int title_idx;
27+
} BlurayContext;
28+
29+
#define OFFSET(x) offsetof(BlurayContext, x)
30+
@@ -102,6 +104,81 @@ static int check_disc_info(URLContext *h)
31+
return 0;
32+
}
33+
34+
+static int bluray_lang_is_unknown(const char *lang)
35+
+{
36+
+ return !lang || !lang[0] ||
37+
+ !av_strcasecmp(lang, "und") ||
38+
+ !av_strcasecmp(lang, "unknown");
39+
+}
40+
+
41+
+static const char *bluray_find_stream_language(const BLURAY_TITLE_INFO *title_info,
42+
+ enum AVMediaType type, int pid)
43+
+{
44+
+ uint32_t clip_idx;
45+
+
46+
+ for (clip_idx = 0; clip_idx < title_info->clip_count; clip_idx++) {
47+
+ const BLURAY_CLIP_INFO *clip = &title_info->clips[clip_idx];
48+
+ const BLURAY_STREAM_INFO *streams = NULL;
49+
+ int stream_count = 0;
50+
+ int stream_idx;
51+
+
52+
+ switch (type) {
53+
+ case AVMEDIA_TYPE_VIDEO:
54+
+ streams = clip->video_streams;
55+
+ stream_count = clip->video_stream_count;
56+
+ break;
57+
+ case AVMEDIA_TYPE_AUDIO:
58+
+ streams = clip->audio_streams;
59+
+ stream_count = clip->audio_stream_count;
60+
+ break;
61+
+ case AVMEDIA_TYPE_SUBTITLE:
62+
+ streams = clip->pg_streams;
63+
+ stream_count = clip->pg_stream_count;
64+
+ break;
65+
+ default:
66+
+ continue;
67+
+ }
68+
+
69+
+ for (stream_idx = 0; stream_idx < stream_count; stream_idx++) {
70+
+ const char *lang = (const char *)streams[stream_idx].lang;
71+
+
72+
+ if (streams[stream_idx].pid == pid &&
73+
+ !bluray_lang_is_unknown(lang)) {
74+
+ return lang;
75+
+ }
76+
+ }
77+
+ }
78+
+
79+
+ return NULL;
80+
+}
81+
+
82+
+static void bluray_set_stream_language(URLContext *h, AVStream *st,
83+
+ const BLURAY_TITLE_INFO *title_info)
84+
+{
85+
+ const AVDictionaryEntry *old_lang;
86+
+ const char *lang;
87+
+
88+
+ if (!st || !st->codecpar) {
89+
+ return;
90+
+ }
91+
+
92+
+ lang = bluray_find_stream_language(title_info, st->codecpar->codec_type,
93+
+ st->id);
94+
+ if (!lang) {
95+
+ return;
96+
+ }
97+
+
98+
+ old_lang = av_dict_get(st->metadata, "language", NULL, 0);
99+
+ if (old_lang && !bluray_lang_is_unknown(old_lang->value)) {
100+
+ return;
101+
+ }
102+
+
103+
+ av_log(h, AV_LOG_INFO,
104+
+ "bluray stream %d pid=0x%x language %s -> %s\n",
105+
+ st->index, st->id, old_lang ? old_lang->value : "unset", lang);
106+
+ av_dict_set(&st->metadata, "language", lang, 0);
107+
+}
108+
+
109+
static int bluray_close(URLContext *h)
110+
{
111+
BlurayContext *bd = h->priv_data;
112+
@@ -124,6 +201,7 @@ static void bluray_DebugHandler(const char *psz)
113+
}
114+
#endif
115+
116+
+
117+
static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary **options)
118+
{
119+
#ifdef DEBUG_BLURAY
120+
@@ -198,12 +276,29 @@ static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary
121+
122+
if (info->duration > duration) {
123+
bd->playlist = info->playlist;
124+
+ bd->title_idx = i;
125+
duration = info->duration;
126+
}
127+
128+
bd_free_title_info(info);
129+
}
130+
av_log(h, AV_LOG_INFO, "select longest playlist: %05d.mpls\n", bd->playlist);
131+
+ } else {
132+
+ int i;
133+
+
134+
+ for (i = 0; i < num_title_idx; i++) {
135+
+ BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0);
136+
+
137+
+ if (!info) {
138+
+ continue;
139+
+ }
140+
+ if (info->playlist == bd->playlist) {
141+
+ bd->title_idx = i;
142+
+ bd_free_title_info(info);
143+
+ break;
144+
+ }
145+
+ bd_free_title_info(info);
146+
+ }
147+
}
148+
149+
/* select playlist */
150+
@@ -262,12 +357,43 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
151+
return AVERROR(EINVAL);
152+
}
153+
154+
+static int bluray_parse_priv(AVFormatContext *ic, URLContext *h)
155+
+{
156+
+ BlurayContext *bd = h->priv_data;
157+
+ BLURAY_TITLE_INFO *title_info = NULL;
158+
+ unsigned int i;
159+
+ int ret = 0;
160+
+
161+
+ if (!bd || !bd->bd) {
162+
+ return AVERROR(EFAULT);
163+
+ }
164+
+
165+
+ title_info = bd_get_title_info(bd->bd, bd->title_idx, 0);
166+
+ if (!title_info) {
167+
+ return AVERROR(EFAULT);
168+
+ }
169+
+
170+
+ if (title_info->clip_count <= 0) {
171+
+ ret = EFAULT;
172+
+ goto fail;
173+
+ }
174+
+
175+
+ for (i = 0; i < ic->nb_streams; i++) {
176+
+ bluray_set_stream_language(h, ic->streams[i], title_info);
177+
+ }
178+
+
179+
+fail:
180+
+ bd_free_title_info(title_info);
181+
+ return ret != 0 ? AVERROR(ret) : 0;
182+
+}
183+
+
184+
const URLProtocol ff_bluray_protocol = {
185+
.name = "bluray",
186+
.url_close = bluray_close,
187+
.url_open2 = bluray_open,
188+
.url_read = bluray_read,
189+
.url_seek = bluray_seek,
190+
+ .url_parse_priv = bluray_parse_priv,
191+
.priv_data_size = sizeof(BlurayContext),
192+
.priv_data_class = &bluray_context_class,
193+
};
194+
--
195+
2.50.1 (Apple Git-155)
196+

0 commit comments

Comments
 (0)