1- From e6fdbabaf8902e834a745705c851db193b8d553f Mon Sep 17 00:00:00 2001
1+ From f5e07437aa5f9da451c83bd38fb35808a4e2960c Mon Sep 17 00:00:00 2001
22From: qianlongxu <
[email protected] >
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: Fri, 21 Mar 2025 19:00:28 +0800
4+ Subject: [PATCH 27 ] custom bluray fs for network Blu-ray Disc and BDMV
55
66---
77 libavformat/Makefile | 2 +-
8- libavformat/bluray.c | 32 ++-
8+ libavformat/bluray.c | 116 ++++++ ++-
99 libavformat/bluray_custom_fs.c | 413 +++++++++++++++++++++++++++++++++
1010 libavformat/bluray_custom_fs.h | 29 +++
11- 4 files changed, 468 insertions(+), 8 deletions(-)
11+ 4 files changed, 552 insertions(+), 8 deletions(-)
1212 create mode 100644 libavformat/bluray_custom_fs.c
1313 create mode 100644 libavformat/bluray_custom_fs.h
1414
1515diff --git a/libavformat/Makefile b/libavformat/Makefile
16- index 427c45a..ffc32b9 100644
16+ index 19ba54e..9ad6d87 100644
1717--- a/libavformat/Makefile
1818+++ 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
2020 # protocols I/O
2121 OBJS-$(CONFIG_ASYNC_PROTOCOL) += async.o
2222 OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o
@@ -26,10 +26,10 @@ index 427c45a..ffc32b9 100644
2626 OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
2727 OBJS-$(CONFIG_CONCATF_PROTOCOL) += concat.o
2828diff --git a/libavformat/bluray.c b/libavformat/bluray.c
29- index bf5b88d..96a799a 100644
29+ index 1845551..c3cdc03 100644
3030--- a/libavformat/bluray.c
3131+++ b/libavformat/bluray.c
32- @@ -21,21 +21,22 @@
32+ @@ -21,10 +21,13 @@
3333 */
3434
3535 #include <libbluray/bluray.h>
@@ -38,15 +38,13 @@ index bf5b88d..96a799a 100644
3838 #include "libavutil/avstring.h"
3939 #include "libavformat/url.h"
4040 #include "libavutil/opt.h"
41- #include "libavutil/dict.h"
42- #include "libavformat/avformat.h"
4341+ #include "bluray_custom_fs.h"
42+ + #include "libavutil/dict.h"
43+ + #include "libavformat/avformat.h"
4444
45- - #define BLURAY_PROTO_PREFIX "bluray:"
46- + #define BLURAY_PROTO_PREFIX "bluray://"
45+ #define BLURAY_PROTO_PREFIX "bluray:"
4746 #define MIN_PLAYLIST_LENGTH 180 /* 3 min */
48-
49- typedef struct {
47+ @@ -33,11 +36,12 @@ typedef struct {
5048 const AVClass *class;
5149
5250 BLURAY *bd;
@@ -55,7 +53,12 @@ index bf5b88d..96a799a 100644
5553 int playlist;
5654 int angle;
5755 int chapter;
58- @@ -110,7 +111,7 @@ static int bluray_close(URLContext *h)
56+ /*int region;*/
57+ + int title_idx;
58+ } BlurayContext;
59+
60+ #define OFFSET(x) offsetof(BlurayContext, x)
61+ @@ -106,23 +110,58 @@ static int bluray_close(URLContext *h)
5962 if (bd->bd) {
6063 bd_close(bd->bd);
6164 }
@@ -64,24 +67,38 @@ index bf5b88d..96a799a 100644
6467 return 0;
6568 }
6669
67- @@ -126,7 +127,7 @@ static void bluray_DebugHandler(const char *psz)
68- }
69- #endif
70-
7170- 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)
71+ + #ifdef DEBUG_BLURAY
72+ + #include <libbluray/log_control.h>
73+ + #define BLURAY_DEBUG_MASK 0xFFFFF //(0xFFFFF & ~DBG_STREAM)
74+ +
75+ + static void bluray_DebugHandler(const char *psz)
7376 {
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)
77+ + size_t len = strlen(psz);
78+ + if(len < 1) return;
79+ + av_log(NULL, AV_LOG_INFO, "[bluray] %s\n",psz);
80+ + }
81+ + #endif
82+ +
83+ +
84+ + static int bluray_open(URLContext *h, const char *path, int flags, AVDictionary **options)
85+ + {
86+ + #ifdef DEBUG_BLURAY
87+ + bd_set_debug_mask(BLURAY_DEBUG_MASK);
88+ + bd_set_debug_handler(bluray_DebugHandler);
89+ + #endif
90+ +
91+ BlurayContext *bd = h->priv_data;
92+ int num_title_idx;
93+ const char *diskname = path;
7794
7895 av_strstart(path, BLURAY_PROTO_PREFIX, &diskname);
7996
8097- bd->bd = bd_open(diskname, NULL);
8198+ fs_access *access = NULL;
8299+
83100+ diskname = ff_urldecode(diskname, 0);
84- +
101+ +
85102+ if (av_strstart(diskname, "file://", NULL) || av_strstart(diskname, "/", NULL)) {
86103+ access = NULL;
87104+ } else {
@@ -103,18 +120,101 @@ index bf5b88d..96a799a 100644
103120
104121 /* check if disc can be played */
105122 if (check_disc_info(h) < 0) {
106- @@ -321,7 +339,7 @@ fail:
123+ @@ -159,12 +198,13 @@ static int bluray_open(URLContext *h, const char *path, int flags)
124+
125+ if (info->duration > duration) {
126+ bd->playlist = info->playlist;
127+ + bd->title_idx = i;
128+ duration = info->duration;
129+ }
130+
131+ bd_free_title_info(info);
132+ }
133+ - av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist);
134+ + av_log(h, AV_LOG_INFO, "select longest playlist: %05d.mpls\n", bd->playlist);
135+ }
136+
137+ /* select playlist */
138+ @@ -222,13 +262,75 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
139+ return AVERROR(EINVAL);
140+ }
141+
142+ + static int bluray_parse_priv(AVFormatContext *ic, URLContext *h)
143+ + {
144+ + BlurayContext *bd = h->priv_data;
145+ + BLURAY_TITLE_INFO *title_info = NULL;
146+ + BLURAY_CLIP_INFO clip_info;
147+ +
148+ + int v_idx = 0;
149+ + int a_idx = 0;
150+ + int s_idx = 0;
151+ + int ret = 0;
152+ +
153+ + if (!bd || !bd->bd) {
154+ + return AVERROR(EFAULT);
155+ + }
156+ +
157+ + title_info = bd_get_title_info(bd->bd, bd->title_idx, 0);
158+ + if (!title_info) {
159+ + return AVERROR(EFAULT);
160+ + }
161+ +
162+ + if (title_info->clip_count <= 0) {
163+ + ret = EFAULT;
164+ + goto fail;
165+ + }
166+ + clip_info = title_info->clips[0];
167+ +
168+ + for (int i = 0; i < ic->nb_streams; i++) {
169+ + if (ic->streams[i] && ic->streams[i]->codecpar) {
170+ + switch (ic->streams[i]->codecpar->codec_type) {
171+ + case AVMEDIA_TYPE_VIDEO:
172+ + if (v_idx < clip_info.video_stream_count) {
173+ + av_log(h, AV_LOG_INFO, "video stream %d lang = %s\n", v_idx, clip_info.video_streams[v_idx].lang);
174+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.video_streams[v_idx].lang, AV_DICT_DONT_OVERWRITE);
175+ + v_idx++;
176+ + }
177+ + break;
178+ + case AVMEDIA_TYPE_AUDIO:
179+ + if (a_idx < clip_info.audio_stream_count) {
180+ + av_log(h, AV_LOG_INFO, "audio stream %d lang = %s\n", a_idx, clip_info.audio_streams[a_idx].lang);
181+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.audio_streams[a_idx].lang, AV_DICT_DONT_OVERWRITE);
182+ + a_idx++;
183+ + }
184+ + break;
185+ + case AVMEDIA_TYPE_SUBTITLE:
186+ + if (s_idx < clip_info.pg_stream_count) {
187+ + av_log(h, AV_LOG_INFO, "subtitle stream %d lang = %s\n", s_idx, clip_info.pg_streams[s_idx].lang);
188+ + av_dict_set(&ic->streams[i]->metadata, "language", clip_info.pg_streams[s_idx].lang, AV_DICT_DONT_OVERWRITE);
189+ + s_idx++;
190+ + }
191+ + break;
192+ + default:
193+ + break;
194+ + }
195+ + }
196+ + }
197+ +
198+ + fail:
199+ + bd_free_title_info(title_info);
200+ +
201+ + return ret != 0 ? AVERROR(ret) : 0;
202+ + }
203+
107204 const URLProtocol ff_bluray_protocol = {
108205 .name = "bluray",
109206 .url_close = bluray_close,
110207- .url_open = bluray_open,
111208+ .url_open2 = bluray_open,
112209 .url_read = bluray_read,
113210 .url_seek = bluray_seek,
114- .url_parse_priv = bluray_parse_priv,
211+ + .url_parse_priv = bluray_parse_priv,
212+ .priv_data_size = sizeof(BlurayContext),
213+ .priv_data_class = &bluray_context_class,
214+ };
115215diff --git a/libavformat/bluray_custom_fs.c b/libavformat/bluray_custom_fs.c
116216new file mode 100644
117- index 0000000..9062a2b
217+ index 0000000..bdf2451
118218--- /dev/null
119219+++ b/libavformat/bluray_custom_fs.c
120220@@ -0,0 +1,413 @@
@@ -181,7 +281,7 @@ index 0000000..9062a2b
181281+ if (!io) {
182282+ return -1;
183283+ }
184- +
284+ +
185285+ ff_builtin_io * app = av_mallocz(sizeof(ff_builtin_io));
186286+ if (!app) {
187287+ return -2;
@@ -215,7 +315,7 @@ index 0000000..9062a2b
215315+ if (is_dir) {
216316+ flags |= AVIO_FLAG_DIRECT;
217317+ }
218- +
318+ +
219319+ int ret = ffurl_open_whitelist(&app->url_context,
220320+ url,
221321+ flags,
@@ -226,8 +326,8 @@ index 0000000..9062a2b
226326+ NULL);
227327+
228328+ 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) {
329+ +
330+ + if (ret < 0) {
231331+ close_builtin_io(app);
232332+ av_freep(&app);
233333+ }
@@ -246,11 +346,11 @@ index 0000000..9062a2b
246346+ }
247347+
248348+ av_application_will_http_seek(io->app_ctx, (void*)io->url_context, io->url_context->filename, offset);
249- +
349+ +
250350+ int64_t pos = io->url_context->prot->url_seek(io->url_context, offset, origin);
251351+ if (pos < 0) {
252352+ av_application_did_http_seek(io->app_ctx, (void*)io->url_context, io->url_context->filename, offset, AVERROR(errno), 500);
253- + return AVERROR(errno);
353+ + return AVERROR(errno);
254354+ }
255355+ io->offset = pos;
256356+
@@ -282,7 +382,7 @@ index 0000000..9062a2b
282382+
283383+ int bytes = buf_size - buf_size1;
284384+ if (bytes == 0 && read == AVERROR_EOF) {
285- + return AVERROR_EOF;
385+ + return AVERROR_EOF;
286386+ } else {
287387+ av_application_did_io_tcp_read(io->app_ctx, (void*)io->url_context, bytes);
288388+ return bytes;
@@ -404,12 +504,12 @@ index 0000000..9062a2b
404504+ }
405505+ AVDictionary *opts = NULL;
406506+ av_dict_copy(&opts, access->opts, 0);
407- +
507+ +
408508+ ff_builtin_io *io = NULL;
409509+ int ret = create_builtin_io(&io, url, &opts, 0);
410510+ av_dict_free(&opts);
411511+ av_free(url);
412- +
512+ +
413513+ if (0 != ret) {
414514+ av_log(NULL, AV_LOG_ERROR, "can't open url %s,error:%s", url, av_err2str(ret));
415515+ return NULL;
@@ -455,11 +555,11 @@ index 0000000..9062a2b
455555+ }
456556+
457557+ AVIODirEntry *next = NULL;
458- +
558+ +
459559+ if (io->url_context->prot->url_read_dir(io->url_context, &next) < 0 || !next) {
460560+ return -2;
461561+ }
462- +
562+ +
463563+ strncpy(entry->d_name, next->name, sizeof(entry->d_name));
464564+ entry->d_name[sizeof(entry->d_name) - 1] = 0;
465565+
@@ -477,12 +577,12 @@ index 0000000..9062a2b
477577+ }
478578+ AVDictionary *opts = NULL;
479579+ av_dict_copy(&opts, access->opts, 0);
480- +
580+ +
481581+ ff_builtin_io *io = NULL;
482582+ int ret = create_builtin_io(&io, url, &opts, 1);
483583+ av_dict_free(&opts);
484584+ av_free(url);
485- +
585+ +
486586+ if (0 != ret) {
487587+ av_log(NULL, AV_LOG_ERROR, "can't open dir %s,error:%s", url, av_err2str(ret));
488588+ return NULL;
@@ -498,7 +598,7 @@ index 0000000..9062a2b
498598+ dir->internal = io;
499599+ dir->close = _dir_close;
500600+ dir->read = _dir_read;
501- +
601+ +
502602+ return dir;
503603+ }
504604+
@@ -513,9 +613,9 @@ index 0000000..9062a2b
513613+ if (opaque) {
514614+ opaque->url = av_strdup(url);
515615+ if (options) {
516- + av_dict_copy(&opaque->opts, *options, 0);
616+ + av_dict_copy(&opaque->opts, *options, 0);
517617+ }
518- +
618+ +
519619+ int ret = create_builtin_io(&opaque->io, url, options, 0);
520620+ if (0 != ret) {
521621+ av_log(NULL, AV_LOG_ERROR, "can't open file %s,error:%s", url, av_err2str(ret));
@@ -526,7 +626,7 @@ index 0000000..9062a2b
526626+ access->read_blocks = read_blocks;
527627+ access->open_file = open_file;
528628+ access->open_dir = open_dir;
529- +
629+ +
530630+ return access;
531631+ }
532632+ return NULL;
0 commit comments