FFmpegfs Fuse Multi Media Filesystem 2.14
blurayio.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2023 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 "ffmpeg_utils.h"
36#include "logging.h"
37
38#include <libbluray/bluray.h>
39
41 : m_bd(nullptr)
42 , m_is_eof(false)
43 , m_errno(0)
44 , m_rest_size(0)
45 , m_rest_pos(0)
46 , m_cur_pos(0)
47 , m_start_pos(0)
48 , m_end_pos(AV_NOPTS_VALUE)
49 , m_full_title(false)
50 , m_title_idx(0)
51 , m_chapter_idx(0)
52 , m_angle_idx(0)
53 , m_duration(AV_NOPTS_VALUE)
54{
55 std::memset(&m_data, 0, sizeof(m_data));
56}
57
59{
60 pvt_close();
61}
62
64{
65 return VIRTUALTYPE_BLURAY;
66}
67
68size_t BlurayIO::bufsize() const
69{
70 return sizeof(m_data);
71}
72
74{
75 const char *bdpath = nullptr;
76 uint32_t title_count;
77 uint32_t chapter_end;
78 char *keyfile = nullptr;
79 BLURAY_TITLE_INFO *ti;
80
82
83 bdpath = path().c_str();
84
85 if (virtualfile != nullptr)
86 {
92 }
93 else
94 {
95 m_full_title = false;
96 m_title_idx = 0;
97 m_chapter_idx = 0;
98 m_angle_idx = 0;
99 m_duration = AV_NOPTS_VALUE;
100 }
101
102 chapter_end = m_chapter_idx + 1;
103
104 Logging::debug(bdpath, "Opening input Blu-ray.");
105
106 m_bd = bd_open(bdpath, keyfile);
107 if (m_bd == nullptr)
108 {
109 Logging::error(bdpath, "Failed to open disc.");
110 return 1;
111 }
112
113 title_count = bd_get_titles(m_bd, TITLES_RELEVANT, 0);
114 if (title_count == 0)
115 {
116 Logging::error(bdpath, "There were no titles found.");
117 return 1;
118 }
119
120 if (!bd_select_title(m_bd, m_title_idx))
121 {
122 Logging::error(bdpath, "The Blu-ray title no. %1 could not be opened.", m_title_idx);
123 return 1;
124 }
125 ti = bd_get_title_info(m_bd, m_title_idx, m_angle_idx);
126
127 if (m_angle_idx >= ti->angle_count)
128 {
129 Logging::warning(bdpath, "The angle %1 is greater than the angle count %2. Using angle 1.", m_angle_idx + 1, ti->angle_count);
130 m_angle_idx = 0;
131 }
132
133 bd_select_angle(m_bd, m_angle_idx);
134
135 if (m_chapter_idx >= ti->chapter_count)
136 {
137 Logging::error(bdpath, "The first chapter %1 is greater than the chapter count %2.", m_chapter_idx + 1, ti->chapter_count);
138 return 1;
139 }
140
141 if (chapter_end >= ti->chapter_count)
142 {
143 chapter_end = 0;
144 }
145
146 if (chapter_end > 0 && !m_full_title)
147 {
148 m_end_pos = bd_chapter_pos(m_bd, chapter_end) - 1;
149 }
150 else
151 {
152 m_end_pos = static_cast<int64_t>(bd_get_title_size(m_bd));
153 }
154
155 if (m_full_title)
156 {
157 m_duration = static_cast<int64_t>(ti->duration * AV_TIME_BASE / 90000);
158 }
159 else
160 {
161 BLURAY_TITLE_CHAPTER *chapter = &ti->chapters[m_chapter_idx];
162 m_duration = static_cast<int64_t>(chapter->duration * AV_TIME_BASE / 90000);
163 }
164
165 bd_free_title_info(ti);
166
167 m_start_pos = bd_seek_chapter(m_bd, m_chapter_idx);
168
169 m_rest_size = 0;
170 m_rest_pos = 0;
171
172 return 0;
173}
174
175size_t BlurayIO::readio(void * data, size_t size)
176{
177 size_t result_len = 0;
178
179 if (m_rest_size)
180 {
181 result_len = m_rest_size;
182
183 if (m_rest_size > size)
184 {
185 errno = EINVAL;
186 return 0;
187 }
188
189 std::memcpy(data, &m_data[m_rest_pos], m_rest_size);
190
192
193 return result_len;
194 }
195
196 m_cur_pos = static_cast<int64_t>(bd_tell(m_bd));
197 if (m_end_pos < 0 || m_cur_pos < m_end_pos)
198 {
199 int maxsize = sizeof(m_data);
200
201 if (maxsize > (m_end_pos - m_cur_pos))
202 {
203 maxsize = static_cast<int>(m_end_pos - m_cur_pos);
204 }
205
206 int res = bd_read(m_bd, m_data, maxsize);
207 if (res < 0)
208 {
209 Logging::error(path(), "bd_read has failed.");
210 return 0;
211 }
212
213 size_t bytes = static_cast<size_t>(res);
214
215 m_cur_pos = static_cast<int64_t>(bd_tell(m_bd));
216
217 if (bytes > size)
218 {
219 result_len = size;
220 std::memcpy(data, m_data, result_len);
221
222 m_rest_size = bytes - size;
224 }
225 else
226 {
227 result_len = bytes;
228 std::memcpy(data, m_data, result_len);
229 }
230 }
231
232 return result_len;
233}
234
236{
237 return m_errno;
238}
239
240int64_t BlurayIO::duration() const
241{
242 return m_duration;
243}
244
245size_t BlurayIO::size() const
246{
247 return static_cast<size_t>(m_end_pos - m_start_pos);
248}
249
250size_t BlurayIO::tell() const
251{
252 return static_cast<size_t>(static_cast<int64_t>(bd_tell(m_bd)) - m_start_pos);
253}
254
255int BlurayIO::seek(int64_t offset, int whence)
256{
257 int64_t seek_pos;
258
259 switch (whence)
260 {
261 case SEEK_SET:
262 {
263 seek_pos = m_start_pos + offset;
264 break;
265 }
266 case SEEK_CUR:
267 {
268 seek_pos = m_start_pos + offset + static_cast<int64_t>(bd_tell(m_bd));
269 break;
270 }
271 case SEEK_END:
272 {
273 seek_pos = m_end_pos + offset;
274 break;
275 }
276 default:
277 {
278 errno = EINVAL;
279 return (EOF);
280 }
281 }
282
283 if (seek_pos > m_end_pos)
284 {
285 m_cur_pos = m_end_pos; // Cannot go beyond EOF. Set position to end, leave errno untouched.
286 return 0;
287 }
288
289 if (seek_pos < 0) // Cannot go before head, set errno.
290 {
291 errno = EINVAL;
292 return (EOF);
293 }
294
295 m_cur_pos = bd_seek(m_bd, static_cast<uint64_t>(seek_pos));
296
297 return (m_cur_pos == seek_pos ? 0 : -1);
298}
299
300bool BlurayIO::eof() const
301{
302 return (m_cur_pos >= m_end_pos);
303}
304
306{
307 pvt_close();
308}
309
311{
312 BLURAY * bd = m_bd;
313 if (bd != nullptr)
314 {
315 m_bd = nullptr;
316 bd_close(bd);
317 }
318}
319
320#endif // USE_LIBBLURAY
Blu-ray I/O.
struct bluray BLURAY
Forward declaration of libbluray handle.
Definition: blurayio.h:43
virtual size_t readio(void *data, size_t size) override
Read data from file.
Definition: blurayio.cc:175
int64_t m_cur_pos
Current position in virtual file.
Definition: blurayio.h:147
size_t m_rest_pos
Position in buffer.
Definition: blurayio.h:146
int64_t m_end_pos
End offset in bytes (not including this byte)
Definition: blurayio.h:149
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
Definition: blurayio.h:158
virtual int seek(int64_t offset, int whence) override
Seek to position in file.
Definition: blurayio.cc:255
virtual int error() const override
Get last error.
Definition: blurayio.cc:235
int m_errno
Last errno.
Definition: blurayio.h:144
uint8_t m_data[192 *1024]
Buffer for readio() data.
Definition: blurayio.h:156
BlurayIO()
Create BlurayIO object.
Definition: blurayio.cc:40
BLURAY * m_bd
Blu-ray disk handle.
Definition: blurayio.h:141
virtual ~BlurayIO()
Free BlurayIO object.
Definition: blurayio.cc:58
unsigned m_angle_idx
Selected angle index (angle number -1)
Definition: blurayio.h:154
uint32_t m_title_idx
Track index (track number - 1)
Definition: blurayio.h:152
bool m_full_title
If true, ignore m_chapter_no and provide full track.
Definition: blurayio.h:151
virtual int openio(LPVIRTUALFILE virtualfile) override
Open a virtual file.
Definition: blurayio.cc:73
size_t m_rest_size
Rest bytes in buffer.
Definition: blurayio.h:145
virtual size_t bufsize() const override
Get the ideal buffer size.
Definition: blurayio.cc:68
unsigned m_chapter_idx
Chapter index (chapter number - 1)
Definition: blurayio.h:153
virtual size_t size() const override
Get the file size.
Definition: blurayio.cc:245
void pvt_close()
Close virtual file. Non-virtual version to be safely called from constructor/destructor.
Definition: blurayio.cc:310
virtual bool eof() const override
Check if at end of file.
Definition: blurayio.cc:300
virtual void closeio() override
Close virtual file.
Definition: blurayio.cc:305
int64_t m_start_pos
Start offset in bytes.
Definition: blurayio.h:148
virtual int64_t duration() const override
Get the duration of the file, in AV_TIME_BASE fractional seconds.
Definition: blurayio.cc:240
virtual size_t tell() const override
Get current read position.
Definition: blurayio.cc:250
virtual VIRTUALTYPE type() const override
Get type of the virtual file.
Definition: blurayio.cc:63
const std::string & path() const
Path to source file (without file name)
Definition: fileio.cc:119
LPVIRTUALFILE virtualfile()
Get virtual file object.
Definition: fileio.cc:114
void set_virtualfile(LPVIRTUALFILE virtualfile)
Set the virtual file object.
Definition: fileio.cc:97
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
Various FFmpegfs utility functions.
VIRTUALTYPE
Virtual file types enum.
Definition: fileio.h:90
@ VIRTUALTYPE_BLURAY
Blu-ray disk file.
Definition: fileio.h:101
Provide various log facilities to stderr, disk or syslog.
unsigned m_chapter_no
Chapter number (1...n)
Definition: fileio.h:212
uint32_t m_title_no
Track number (1...n)
Definition: fileio.h:210
unsigned m_angle_no
Selected angle number (1...n)
Definition: fileio.h:213
Virtual file definition.
Definition: fileio.h:121
bool m_full_title
If true, ignore m_chapter_no and provide full track.
Definition: fileio.h:153
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:154