1
- From e6fdbabaf8902e834a745705c851db193b8d553f Mon Sep 17 00:00:00 2001
1
+ From 22d3925e8fec79ca0dd23dbdb7eb6f9a9d53ee96 Mon Sep 17 00:00:00 2001
2
2
From: qianlongxu <qianlongxu@gmail.com>
3
- Date: Tue, 17 Dec 2024 18:59:49 +0800
4
- Subject: [PATCH 21] custom bluray fs for network Blu-ray Disc and BDMV
3
+ Date: Mon, 24 Mar 2025 09:31:42 +0800
4
+ Subject: [PATCH 27] custom bluray fs for network Blu-ray Disc and BDMV
5
5
6
6
---
7
7
libavformat/Makefile | 2 +-
8
- libavformat/bluray.c | 32 ++-
8
+ libavformat/bluray.c | 118 +++++++ ++-
9
9
libavformat/bluray_custom_fs.c | 413 +++++++++++++++++++++++++++++++++
10
10
libavformat/bluray_custom_fs.h | 29 +++
11
- 4 files changed, 468 insertions(+), 8 deletions(-)
11
+ 4 files changed, 553 insertions(+), 9 deletions(-)
12
12
create mode 100644 libavformat/bluray_custom_fs.c
13
13
create mode 100644 libavformat/bluray_custom_fs.h
14
14
15
15
diff --git a/libavformat/Makefile b/libavformat/Makefile
16
- index 427c45a..ffc32b9 100644
16
+ index 19ba54e..9ad6d87 100644
17
17
--- a/libavformat/Makefile
18
18
+++ b/libavformat/Makefile
19
- @@ -666 ,7 +666 ,7 @@ OBJS-$(CONFIG_VAPOURSYNTH_DEMUXER) += vapoursynth.o
19
+ @@ -667 ,7 +667 ,7 @@ OBJS-$(CONFIG_VAPOURSYNTH_DEMUXER) += vapoursynth.o
20
20
# protocols I/O
21
21
OBJS-$(CONFIG_ASYNC_PROTOCOL) += async.o
22
22
OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o
@@ -26,10 +26,10 @@ index 427c45a..ffc32b9 100644
26
26
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
27
27
OBJS-$(CONFIG_CONCATF_PROTOCOL) += concat.o
28
28
diff --git a/libavformat/bluray.c b/libavformat/bluray.c
29
- index bf5b88d..96a799a 100644
29
+ index 1845551..cd50523 100644
30
30
--- a/libavformat/bluray.c
31
31
+++ b/libavformat/bluray.c
32
- @@ -21,21 +21,22 @@
32
+ @@ -21,23 +21,27 @@
33
33
*/
34
34
35
35
#include <libbluray/bluray.h>
@@ -38,9 +38,9 @@ index bf5b88d..96a799a 100644
38
38
#include "libavutil/avstring.h"
39
39
#include "libavformat/url.h"
40
40
#include "libavutil/opt.h"
41
- #include "libavutil/dict.h"
42
- #include "libavformat/avformat.h"
43
41
+ #include "bluray_custom_fs.h"
42
+ + #include "libavutil/dict.h"
43
+ + #include "libavformat/avformat.h"
44
44
45
45
- #define BLURAY_PROTO_PREFIX "bluray:"
46
46
+ #define BLURAY_PROTO_PREFIX "bluray://"
@@ -55,7 +55,12 @@ index bf5b88d..96a799a 100644
55
55
int playlist;
56
56
int angle;
57
57
int chapter;
58
- @@ -110,7 +111,7 @@ static int bluray_close(URLContext *h)
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)
59
64
if (bd->bd) {
60
65
bd_close(bd->bd);
61
66
}
@@ -64,24 +69,38 @@ index bf5b88d..96a799a 100644
64
69
return 0;
65
70
}
66
71
67
- @@ -126,7 +127,7 @@ static void bluray_DebugHandler(const char *psz)
68
- }
69
- #endif
70
-
71
72
- static int bluray_open(URLContext *h, const char *path, int flags)
72
- + static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary **options)
73
+ + #ifdef DEBUG_BLURAY
74
+ + #include <libbluray/log_control.h>
75
+ + #define BLURAY_DEBUG_MASK 0xFFFFF //(0xFFFFF & ~DBG_STREAM)
76
+ +
77
+ + static void bluray_DebugHandler(const char *psz)
73
78
{
74
- #ifdef DEBUG_BLURAY
75
- bd_set_debug_mask(BLURAY_DEBUG_MASK);
76
- @@ -138,11 +139,28 @@ static int bluray_open(URLContext *h, const char *path, int flags)
79
+ + size_t len = strlen(psz);
80
+ + if(len < 1) return;
81
+ + av_log(NULL, AV_LOG_INFO, "[bluray] %s\n",psz);
82
+ + }
83
+ + #endif
84
+ +
85
+ +
86
+ + static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary **options)
87
+ + {
88
+ + #ifdef DEBUG_BLURAY
89
+ + bd_set_debug_mask(BLURAY_DEBUG_MASK);
90
+ + bd_set_debug_handler(bluray_DebugHandler);
91
+ + #endif
92
+ +
93
+ BlurayContext *bd = h->priv_data;
94
+ int num_title_idx;
95
+ const char *diskname = path;
77
96
78
97
av_strstart(path, BLURAY_PROTO_PREFIX, &diskname);
79
98
80
99
- bd->bd = bd_open(diskname, NULL);
81
100
+ fs_access *access = NULL;
82
101
+
83
102
+ diskname = ff_urldecode(diskname, 0);
84
- +
103
+ +
85
104
+ if (av_strstart(diskname, "file://", NULL) || av_strstart(diskname, "/", NULL)) {
86
105
+ access = NULL;
87
106
+ } else {
@@ -103,18 +122,101 @@ index bf5b88d..96a799a 100644
103
122
104
123
/* check if disc can be played */
105
124
if (check_disc_info(h) < 0) {
106
- @@ -321,7 +339,7 @@ fail:
125
+ @@ -159,12 +198,13 @@ static int bluray_open(URLContext *h, const char *path, int flags)
126
+
127
+ if (info->duration > duration) {
128
+ bd->playlist = info->playlist;
129
+ + bd->title_idx = i;
130
+ duration = info->duration;
131
+ }
132
+
133
+ bd_free_title_info(info);
134
+ }
135
+ - av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist);
136
+ + av_log(h, AV_LOG_INFO, "select longest playlist: %05d.mpls\n", bd->playlist);
137
+ }
138
+
139
+ /* select playlist */
140
+ @@ -222,13 +262,75 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
141
+ return AVERROR(EINVAL);
142
+ }
143
+
144
+ + static int bluray_parse_priv(AVFormatContext *ic, URLContext *h)
145
+ + {
146
+ + BlurayContext *bd = h->priv_data;
147
+ + BLURAY_TITLE_INFO *title_info = NULL;
148
+ + BLURAY_CLIP_INFO clip_info;
149
+ +
150
+ + int v_idx = 0;
151
+ + int a_idx = 0;
152
+ + int s_idx = 0;
153
+ + int ret = 0;
154
+ +
155
+ + if (!bd || !bd->bd) {
156
+ + return AVERROR(EFAULT);
157
+ + }
158
+ +
159
+ + title_info = bd_get_title_info(bd->bd, bd->title_idx, 0);
160
+ + if (!title_info) {
161
+ + return AVERROR(EFAULT);
162
+ + }
163
+ +
164
+ + if (title_info->clip_count <= 0) {
165
+ + ret = EFAULT;
166
+ + goto fail;
167
+ + }
168
+ + clip_info = title_info->clips[0];
169
+ +
170
+ + for (int i = 0; i < ic->nb_streams; i++) {
171
+ + if (ic->streams[i] && ic->streams[i]->codecpar) {
172
+ + switch (ic->streams[i]->codecpar->codec_type) {
173
+ + case AVMEDIA_TYPE_VIDEO:
174
+ + if (v_idx < clip_info.video_stream_count) {
175
+ + av_log(h, AV_LOG_INFO, "video stream %d lang = %s\n", v_idx, clip_info.video_streams[v_idx].lang);
176
+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.video_streams[v_idx].lang, AV_DICT_DONT_OVERWRITE);
177
+ + v_idx++;
178
+ + }
179
+ + break;
180
+ + case AVMEDIA_TYPE_AUDIO:
181
+ + if (a_idx < clip_info.audio_stream_count) {
182
+ + av_log(h, AV_LOG_INFO, "audio stream %d lang = %s\n", a_idx, clip_info.audio_streams[a_idx].lang);
183
+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.audio_streams[a_idx].lang, AV_DICT_DONT_OVERWRITE);
184
+ + a_idx++;
185
+ + }
186
+ + break;
187
+ + case AVMEDIA_TYPE_SUBTITLE:
188
+ + if (s_idx < clip_info.pg_stream_count) {
189
+ + av_log(h, AV_LOG_INFO, "subtitle stream %d lang = %s\n", s_idx, clip_info.pg_streams[s_idx].lang);
190
+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.pg_streams[s_idx].lang, AV_DICT_DONT_OVERWRITE);
191
+ + s_idx++;
192
+ + }
193
+ + break;
194
+ + default:
195
+ + break;
196
+ + }
197
+ + }
198
+ + }
199
+ +
200
+ + fail:
201
+ + bd_free_title_info(title_info);
202
+ +
203
+ + return ret != 0 ? AVERROR(ret) : 0;
204
+ + }
205
+
107
206
const URLProtocol ff_bluray_protocol = {
108
207
.name = "bluray",
109
208
.url_close = bluray_close,
110
209
- .url_open = bluray_open,
111
210
+ .url_open2 = bluray_open,
112
211
.url_read = bluray_read,
113
212
.url_seek = bluray_seek,
114
- .url_parse_priv = bluray_parse_priv,
213
+ + .url_parse_priv = bluray_parse_priv,
214
+ .priv_data_size = sizeof(BlurayContext),
215
+ .priv_data_class = &bluray_context_class,
216
+ };
115
217
diff --git a/libavformat/bluray_custom_fs.c b/libavformat/bluray_custom_fs.c
116
218
new file mode 100644
117
- index 0000000..9062a2b
219
+ index 0000000..bdf2451
118
220
--- /dev/null
119
221
+++ b/libavformat/bluray_custom_fs.c
120
222
@@ -0,0 +1,413 @@
@@ -181,7 +283,7 @@ index 0000000..9062a2b
181
283
+ if (!io) {
182
284
+ return -1;
183
285
+ }
184
- +
286
+ +
185
287
+ ff_builtin_io * app = av_mallocz(sizeof(ff_builtin_io));
186
288
+ if (!app) {
187
289
+ return -2;
@@ -215,7 +317,7 @@ index 0000000..9062a2b
215
317
+ if (is_dir) {
216
318
+ flags |= AVIO_FLAG_DIRECT;
217
319
+ }
218
- +
320
+ +
219
321
+ int ret = ffurl_open_whitelist(&app->url_context,
220
322
+ url,
221
323
+ flags,
@@ -226,8 +328,8 @@ index 0000000..9062a2b
226
328
+ NULL);
227
329
+
228
330
+ av_application_did_http_open(app->app_ctx, (void*)app->url_context, url, ret < 0 ? AVERROR(errno) : 0, ret < 0 ? 500 : 200, 0);
229
- +
230
- + if (ret < 0) {
331
+ +
332
+ + if (ret < 0) {
231
333
+ close_builtin_io(app);
232
334
+ av_freep(&app);
233
335
+ }
@@ -246,11 +348,11 @@ index 0000000..9062a2b
246
348
+ }
247
349
+
248
350
+ av_application_will_http_seek(io->app_ctx, (void*)io->url_context, io->url_context->filename, offset);
249
- +
351
+ +
250
352
+ int64_t pos = io->url_context->prot->url_seek(io->url_context, offset, origin);
251
353
+ if (pos < 0) {
252
354
+ av_application_did_http_seek(io->app_ctx, (void*)io->url_context, io->url_context->filename, offset, AVERROR(errno), 500);
253
- + return AVERROR(errno);
355
+ + return AVERROR(errno);
254
356
+ }
255
357
+ io->offset = pos;
256
358
+
@@ -282,7 +384,7 @@ index 0000000..9062a2b
282
384
+
283
385
+ int bytes = buf_size - buf_size1;
284
386
+ if (bytes == 0 && read == AVERROR_EOF) {
285
- + return AVERROR_EOF;
387
+ + return AVERROR_EOF;
286
388
+ } else {
287
389
+ av_application_did_io_tcp_read(io->app_ctx, (void*)io->url_context, bytes);
288
390
+ return bytes;
@@ -404,12 +506,12 @@ index 0000000..9062a2b
404
506
+ }
405
507
+ AVDictionary *opts = NULL;
406
508
+ av_dict_copy(&opts, access->opts, 0);
407
- +
509
+ +
408
510
+ ff_builtin_io *io = NULL;
409
511
+ int ret = create_builtin_io(&io, url, &opts, 0);
410
512
+ av_dict_free(&opts);
411
513
+ av_free(url);
412
- +
514
+ +
413
515
+ if (0 != ret) {
414
516
+ av_log(NULL, AV_LOG_ERROR, "can't open url %s,error:%s", url, av_err2str(ret));
415
517
+ return NULL;
@@ -455,11 +557,11 @@ index 0000000..9062a2b
455
557
+ }
456
558
+
457
559
+ AVIODirEntry *next = NULL;
458
- +
560
+ +
459
561
+ if (io->url_context->prot->url_read_dir(io->url_context, &next) < 0 || !next) {
460
562
+ return -2;
461
563
+ }
462
- +
564
+ +
463
565
+ strncpy(entry->d_name, next->name, sizeof(entry->d_name));
464
566
+ entry->d_name[sizeof(entry->d_name) - 1] = 0;
465
567
+
@@ -477,12 +579,12 @@ index 0000000..9062a2b
477
579
+ }
478
580
+ AVDictionary *opts = NULL;
479
581
+ av_dict_copy(&opts, access->opts, 0);
480
- +
582
+ +
481
583
+ ff_builtin_io *io = NULL;
482
584
+ int ret = create_builtin_io(&io, url, &opts, 1);
483
585
+ av_dict_free(&opts);
484
586
+ av_free(url);
485
- +
587
+ +
486
588
+ if (0 != ret) {
487
589
+ av_log(NULL, AV_LOG_ERROR, "can't open dir %s,error:%s", url, av_err2str(ret));
488
590
+ return NULL;
@@ -498,7 +600,7 @@ index 0000000..9062a2b
498
600
+ dir->internal = io;
499
601
+ dir->close = _dir_close;
500
602
+ dir->read = _dir_read;
501
- +
603
+ +
502
604
+ return dir;
503
605
+ }
504
606
+
@@ -513,9 +615,9 @@ index 0000000..9062a2b
513
615
+ if (opaque) {
514
616
+ opaque->url = av_strdup(url);
515
617
+ if (options) {
516
- + av_dict_copy(&opaque->opts, *options, 0);
618
+ + av_dict_copy(&opaque->opts, *options, 0);
517
619
+ }
518
- +
620
+ +
519
621
+ int ret = create_builtin_io(&opaque->io, url, options, 0);
520
622
+ if (0 != ret) {
521
623
+ av_log(NULL, AV_LOG_ERROR, "can't open file %s,error:%s", url, av_err2str(ret));
@@ -526,7 +628,7 @@ index 0000000..9062a2b
526
628
+ access->read_blocks = read_blocks;
527
629
+ access->open_file = open_file;
528
630
+ access->open_dir = open_dir;
529
- +
631
+ +
530
632
+ return access;
531
633
+ }
532
634
+ return NULL;
0 commit comments