FFmpegfs Fuse Multi Media Filesystem 2.16
blurayio.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2024 Norbert Schlia (nschlia@oblivion-software.de)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * On Debian systems, the complete text of the GNU General Public License
19 * Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
20 */
21
22#ifdef USE_LIBBLURAY
23
34#include "blurayio.h"
35#include "logging.h"
36
37#include <libbluray/bluray.h>
38
40 : m_bd(nullptr)
41 , m_is_eof(false)
42 , m_errno(0)
43 , m_rest_size(0)
44 , m_rest_pos(0)
45 , m_cur_pos(0)
46 , m_start_pos(0)
47 , m_end_pos(AV_NOPTS_VALUE)
48 , m_full_title(false)
49 , m_title_idx(0)
50 , m_chapter_idx(0)
51 , m_angle_idx(0)
52 , m_duration(AV_NOPTS_VALUE)
53{
54 m_data.fill(0);
55}
56
58{
59 pvt_close();
60}
61
63{
65}
66
67size_t BlurayIO::bufsize() const
68{
69 return sizeof(m_data);
70}
71
73{
74 uint32_t title_count;
75 uint32_t chapter_end;
76 BLURAY_TITLE_INFO *ti;
77
79
80 if (virtualfile != nullptr)
81 {
87 }
88 else
89 {
90 m_full_title = false;
91 m_title_idx = 0;
92 m_chapter_idx = 0;
93 m_angle_idx = 0;
94 m_duration = AV_NOPTS_VALUE;
95 }
96
97 chapter_end = m_chapter_idx + 1;
98
99 Logging::debug(path(), "Opening input Blu-ray.");
100
101 m_bd = bd_open(path().c_str(), nullptr);
102
103 if (m_bd == nullptr)
104 {
105 Logging::error(path(), "Failed to open disc.");
106 return 1;
107 }
108
109 title_count = bd_get_titles(m_bd, TITLES_RELEVANT, 0);
110 if (title_count == 0)
111 {
112 Logging::error(path(), "There were no titles found.");
113 return 1;
114 }
115
116 if (!bd_select_title(m_bd, m_title_idx))
117 {
118 Logging::error(path(), "The Blu-ray title no. %1 could not be opened.", m_title_idx);
119 return 1;
120 }
121 ti = bd_get_title_info(m_bd, m_title_idx, m_angle_idx);
122
123 if (m_angle_idx >= ti->angle_count)
124 {
125 Logging::warning(path(), "The angle %1 is greater than the angle count %2. Using angle 1.", m_angle_idx + 1, ti->angle_count);
126 m_angle_idx = 0;
127 }
128
129 bd_select_angle(m_bd, m_angle_idx);
130
131 if (m_chapter_idx >= ti->chapter_count)
132 {
133 Logging::error(path(), "The first chapter %1 is greater than the chapter count %2.", m_chapter_idx + 1, ti->chapter_count);
134 return 1;
135 }
136
137 if (chapter_end >= ti->chapter_count)
138 {
139 chapter_end = 0;
140 }
141
142 if (chapter_end > 0 && !m_full_title)
143 {
144 m_end_pos = bd_chapter_pos(m_bd, chapter_end) - 1;
145 }
146 else
147 {
148 m_end_pos = static_cast<int64_t>(bd_get_title_size(m_bd));
149 }
150
151 if (m_full_title)
152 {
153 m_duration = static_cast<int64_t>(ti->duration * AV_TIME_BASE / 90000);
154 }
155 else
156 {
157 BLURAY_TITLE_CHAPTER *chapter = &ti->chapters[m_chapter_idx];
158 m_duration = static_cast<int64_t>(chapter->duration * AV_TIME_BASE / 90000);
159 }
160
161 bd_free_title_info(ti);
162
163 m_start_pos = bd_seek_chapter(m_bd, m_chapter_idx);
164
165 m_rest_size = 0;
166 m_rest_pos = 0;
167
168 return 0;
169}
170
171size_t BlurayIO::readio(void * data, size_t size)
172{
173 size_t result_len = 0;
174
175 if (m_rest_size)
176 {
177 result_len = m_rest_size;
178
179 if (m_rest_size > size)
180 {
181 errno = EINVAL;
182 return 0;
183 }
184
185 std::memcpy(data, &m_data[m_rest_pos], m_rest_size);
186
188
189 return result_len;
190 }
191
192 m_cur_pos = static_cast<int64_t>(bd_tell(m_bd));
193 if (m_end_pos < 0 || m_cur_pos < m_end_pos)
194 {
195 int maxsize = sizeof(m_data);
196
197 if (maxsize > (m_end_pos - m_cur_pos))
198 {
199 maxsize = static_cast<int>(m_end_pos - m_cur_pos);
200 }
201
202 int res = bd_read(m_bd, m_data.data(), maxsize);
203 if (res < 0)
204 {
205 Logging::error(path(), "bd_read has failed.");
206 return 0;
207 }
208
209 size_t bytes = static_cast<size_t>(res);
210
211 m_cur_pos = static_cast<int64_t>(bd_tell(m_bd));
212
213 if (bytes > size)
214 {
215 result_len = size;
216 std::memcpy(data, m_data.data(), result_len);
217
218 m_rest_size = bytes - size;
220 }
221 else
222 {
223 result_len = bytes;
224 std::memcpy(data, m_data.data(), result_len);
225 }
226 }
227
228 return result_len;
229}
230
232{
233 return m_errno;
234}
235
236int64_t BlurayIO::duration() const
237{
238 return m_duration;
239}
240
241size_t BlurayIO::size() const
242{
243 return static_cast<size_t>(m_end_pos - m_start_pos);
244}
245
246size_t BlurayIO::tell() const
247{
248 return static_cast<size_t>(static_cast<int64_t>(bd_tell(m_bd)) - m_start_pos);
249}
250
251int BlurayIO::seek(int64_t offset, int whence)
252{
253 int64_t seek_pos;
254
255 switch (whence)
256 {
257 case SEEK_SET:
258 {
259 seek_pos = m_start_pos + offset;
260 break;
261 }
262 case SEEK_CUR:
263 {
264 seek_pos = m_start_pos + offset + static_cast<int64_t>(bd_tell(m_bd));
265 break;
266 }
267 case SEEK_END:
268 {
269 seek_pos = m_end_pos + offset;
270 break;
271 }
272 default:
273 {
274 errno = EINVAL;
275 return (EOF);
276 }
277 }
278
279 if (seek_pos > m_end_pos)
280 {
281 m_cur_pos = m_end_pos; // Cannot go beyond EOF. Set position to end, leave errno untouched.
282 return 0;
283 }
284
285 if (seek_pos < 0) // Cannot go before head, set errno.
286 {
287 errno = EINVAL;
288 return (EOF);
289 }
290
291 m_cur_pos = bd_seek(m_bd, static_cast<uint64_t>(seek_pos));
292
293 return (m_cur_pos == seek_pos ? 0 : -1);
294}
295
296bool BlurayIO::eof() const
297{
298 return (m_cur_pos >= m_end_pos);
299}
300
302{
303 pvt_close();
304}
305
307{
308 BLURAY * bd = m_bd;
309 if (bd != nullptr)
310 {
311 m_bd = nullptr;
312 bd_close(bd);
313 }
314}
315
316#endif // USE_LIBBLURAY
Blu-ray I/O.
struct bluray BLURAY
Forward declaration of libbluray handle.
Definition: blurayio.h:45
virtual size_t readio(void *data, size_t size) override
Read data from file.
Definition: blurayio.cc:171
std::array< uint8_t, 192 *1024 > m_data
Buffer for readio() data.
Definition: blurayio.h:158
int64_t m_cur_pos
Current position in virtual file.
Definition: blurayio.h:149
size_t m_rest_pos
Position in buffer.
Definition: blurayio.h:148
int64_t m_end_pos
End offset in bytes (not including this byte)
Definition: blurayio.h:151
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Definition: blurayio.h:160
virtual int seek(int64_t offset, int whence) override
Seek to position in file.
Definition: blurayio.cc:251
virtual int error() const override
Get last error.
Definition: blurayio.cc:231
int m_errno
Last errno.
Definition: blurayio.h:146
BlurayIO()
Create BlurayIO object.
Definition: blurayio.cc:39
BLURAY * m_bd
Blu-ray disk handle.
Definition: blurayio.h:143
virtual ~BlurayIO()
Free BlurayIO object.
Definition: blurayio.cc:57
unsigned m_angle_idx
Selected angle index (angle number -1)
Definition: blurayio.h:156
uint32_t m_title_idx
Track index (track number - 1)
Definition: blurayio.h:154
bool m_full_title
If true, ignore m_chapter_no and provide full track.
Definition: blurayio.h:153
virtual int openio(LPVIRTUALFILE virtualfile) override
Open a virtual file.
Definition: blurayio.cc:72
size_t m_rest_size
Rest bytes in buffer.
Definition: blurayio.h:147
virtual size_t bufsize() const override
Get the ideal buffer size.
Definition: blurayio.cc:67
unsigned m_chapter_idx
Chapter index (chapter number - 1)
Definition: blurayio.h:155
virtual size_t size() const override
Get the file size.
Definition: blurayio.cc:241
void pvt_close()
Close virtual file. Non-virtual version to be safely called from constructor/destructor.
Definition: blurayio.cc:306
virtual bool eof() const override
Check if at end of file.
Definition: blurayio.cc:296
virtual void closeio() override
Close virtual file.
Definition: blurayio.cc:301
int64_t m_start_pos
Start offset in bytes.
Definition: blurayio.h:150
virtual int64_t duration() const override
Get the duration of the file, in AV_TIME_BASE fractional seconds.
Definition: blurayio.cc:236
virtual size_t tell() const override
Get current read position.
Definition: blurayio.cc:246
virtual VIRTUALTYPE type() const override
Get type of the virtual file.
Definition: blurayio.cc:62
const std::string & path() const
Path to source file (without file name)
Definition: fileio.cc:118
LPVIRTUALFILE virtualfile()
Get virtual file object.
Definition: fileio.cc:113
void set_virtualfile(LPVIRTUALFILE virtualfile)
Set the virtual file object.
Definition: fileio.cc:96
static void warning(const T filename, const std::string &format_string, Args &&...args)
Write warning level log entry.
Definition: logging.h:220
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
Definition: logging.h:182
static void error(const T filename, const std::string &format_string, Args &&...args)
Write error level log entry.
Definition: logging.h:239
VIRTUALTYPE
Virtual file types enum.
Definition: fileio.h:92
@ BLURAY
Blu-ray disk file.
Provide various log facilities to stderr, disk or syslog.
unsigned m_chapter_no
Chapter number (1...n)
Definition: fileio.h:214
uint32_t m_title_no
Track number (1...n)
Definition: fileio.h:212
unsigned m_angle_no
Selected angle number (1...n)
Definition: fileio.h:215
Virtual file definition.
Definition: fileio.h:123
bool m_full_title
If true, ignore m_chapter_no and provide full track.
Definition: fileio.h:155
struct VIRTUALFILE::BLURAY_CHAPTER m_bluray
Blu-ray title/chapter info.
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Definition: fileio.h:156