39#include <dvdread/dvd_reader.h>
40#include <dvdread/ifo_read.h>
43#include <libavutil/rational.h>
66static int64_t
BCDtime(
const dvd_time_t * dvd_time);
67static bool create_dvd_virtualfile(
const ifo_handle_t *vts_file,
const std::string & path,
const struct stat *statbuf,
void *buf, fuse_fill_dir_t filler,
bool full_title,
int title_idx,
int chapter_idx,
int angles,
int ttnnum,
int audio_stream,
const AUDIO_SETTINGS & audio_settings,
const VIDEO_SETTINGS & video_settings);
68static int parse_dvd(
const std::string & path,
const struct stat *statbuf,
void *buf, fuse_fill_dir_t filler);
80 int best_application_mode = INT_MAX;
81 int best_lang_extension = INT_MAX;
82 int best_quantization = 0;
85 *best_sample_frequency = 0;
87 for(
int i = 0; i < vtsi_mat->nr_of_vts_audio_streams; i++)
89 const audio_attr_t *attr = &vtsi_mat->vts_audio_attr[i];
91 if (attr->audio_format == 0
92 && attr->multichannel_extension == 0
93 && attr->lang_type == 0
94 && attr->application_mode == 0
95 && attr->quantization == 0
96 && attr->sample_frequency == 0
97 && attr->unknown1 == 0
98 && attr->channels == 0
99 && attr->lang_extension == 0
100 && attr->unknown3 == 0)
134 int sample_frequency = 48000;
136 if ((best_application_mode < attr->application_mode) ||
137 (best_application_mode == attr->application_mode && best_lang_extension < attr->lang_extension) ||
138 (best_application_mode == attr->application_mode && best_lang_extension == attr->lang_extension && *best_sample_frequency > sample_frequency) ||
139 (best_application_mode == attr->application_mode && best_lang_extension == attr->lang_extension && *best_sample_frequency == sample_frequency && *best_channels > attr->channels) ||
140 (best_application_mode == attr->application_mode && best_lang_extension == attr->lang_extension && *best_sample_frequency == sample_frequency && *best_channels == attr->channels && best_quantization > attr->quantization)
147 best_application_mode = attr->application_mode;
148 best_lang_extension = attr->lang_extension;
149 *best_sample_frequency = sample_frequency;
150 *best_channels = attr->channels;
151 best_quantization = attr->quantization;
154 if (best_stream > -1)
169 AVRational framerate = { 0, 0 };
172 unsigned fps = ((ptr[3] & 0xC0) >> 6) & 0x03;
178 framerate = av_make_q(25000, 1000);
183 framerate = av_make_q(30000, 10001);
189 framerate = av_make_q(25000, 1000);
202static int64_t
BCDtime(
const dvd_time_t * dvd_time)
204 std::array<int64_t, 4> time;
209 framerate = av_make_q(25000, 1000);
211 time[0] = dvd_time->hour;
212 time[1] = dvd_time->minute;
213 time[2] = dvd_time->second;
214 time[3] = dvd_time->frame_u & 0x3F;
217 for (int64_t & tm : time)
219 tm = ((tm & 0xf0) >> 4) * 10 + (tm & 0x0f);
222 return (AV_TIME_BASE * (time[0] * 3600 + time[1] * 60 + time[2]) +
static_cast<int64_t
>(
static_cast<double>(AV_TIME_BASE * time[3]) / av_q2d(framerate)));
242static bool create_dvd_virtualfile(
const ifo_handle_t *vts_file,
const std::string & path,
const struct stat *statbuf,
void *buf, fuse_fill_dir_t filler,
bool full_title,
int title_idx,
int chapter_idx,
int angles,
int ttnnum,
int audio_stream,
const AUDIO_SETTINGS & audio_settings,
const VIDEO_SETTINGS & video_settings)
244 const vts_ptt_srpt_t *vts_ptt_srpt = vts_file->vts_ptt_srpt;
245 int title_no = title_idx + 1;
246 int chapter_no = chapter_idx + 1;
247 int pgcnum = vts_ptt_srpt->title[ttnnum - 1].ptt[chapter_idx].pgcn;
248 int pgn = vts_ptt_srpt->title[ttnnum - 1].ptt[chapter_idx].pgn;
249 const pgc_t *cur_pgc = vts_file->vts_pgcit->pgci_srp[pgcnum - 1].pgc;
250 AVRational framerate;
251 int64_t duration = 0;
253 bool interleaved =
false;
254 int start_cell = cur_pgc->program_map[pgn - 1] - 1;
257 if (pgn < cur_pgc->nr_of_programs && !full_title)
259 end_cell = cur_pgc->program_map[pgn] - 1;
263 end_cell = cur_pgc->nr_of_cells;
266 interleaved = cur_pgc->cell_playback[start_cell].interleaved ? true :
false;
267 framerate =
dvd_frame_rate(&cur_pgc->cell_playback[start_cell].playback_time.frame_u);
269 bool has_angles =
false;
271 for (
int cell_no = start_cell; cell_no < end_cell; cell_no++)
273 cell_playback_t *cell_playback = &cur_pgc->cell_playback[cell_no];
276 if (cell_playback->block_mode ==
static_cast<unsigned int>(BLOCK_MODE_NOT_IN_BLOCK) || cell_playback->block_mode ==
static_cast<unsigned int>(BLOCK_MODE_FIRST_CELL))
278 size += (cell_playback->last_sector - cell_playback->first_sector) * 2048;
279 duration +=
BCDtime(&cell_playback->playback_time);
282 if (cell_playback->block_type ==
static_cast<unsigned int>(BLOCK_TYPE_ANGLE_BLOCK))
301 for (
int angle_idx = 0; angle_idx < angles; angle_idx++)
303 std::string title_buf;
304 int angle_no = angle_idx + 1;
312 strsprintf(&title_buf,
"%02d. Chapter %03d (Angle %d) [%s].%s",
321 strsprintf(&title_buf,
"%02d. Chapter %03d [%s].%s",
333 strsprintf(&title_buf,
"%02d. Title (Angle %d) [%s].%s",
358 if (virtualfile ==
nullptr)
360 Logging::error(path,
"Failed to create virtual path: %1", (path + title_buf).c_str());
382 BITRATE video_bit_rate = 8*1024*1024;
390 video_bit_rate =
static_cast<BITRATE>(size * 8LL * AV_TIME_BASE /
static_cast<uint64_t
>(duration));
399 if (audio_stream > -1)
407 transcoder_set_filesize(virtualfile, duration, audio_settings.
m_audio_bit_rate, audio_settings.
m_channels, audio_settings.
m_sample_rate, AV_SAMPLE_FMT_NONE, video_bit_rate, video_settings.
m_width, video_settings.
m_height, interleaved, framerate);
409 virtualfile->
m_video_frame_count =
static_cast<uint32_t
>(av_rescale_q(duration, av_get_time_base_q(), av_inv_q(framerate)));
425static int parse_dvd(
const std::string & path,
const struct stat *statbuf,
void *buf, fuse_fill_dir_t filler)
428 ifo_handle_t *ifo_file;
435 dvd = DVDOpen(path.c_str());
442 ifo_file = ifoOpen(dvd, 0);
443 if (ifo_file ==
nullptr)
449 tt_srpt = ifo_file->tt_srpt;
451 titles = tt_srpt->nr_of_srpts;
455 for (
int title_idx = 0; title_idx < titles && success; ++title_idx)
457 ifo_handle_t *vts_file;
458 int vtsnum = tt_srpt->title[title_idx].title_set_nr;
459 int ttnnum = tt_srpt->title[title_idx].vts_ttn;
460 int chapters = tt_srpt->title[title_idx].nr_of_ptts;
461 int angles = tt_srpt->title[title_idx].nr_of_angles;
463 Logging::trace(path,
"Title: %1 VTS: %2 TTN: %3", title_idx + 1, vtsnum, ttnnum);
464 Logging::trace(path,
"DVD title has %1 chapters and %2 angles.", chapters, angles);
466 vts_file = ifoOpen(dvd, vtsnum);
467 if (vts_file ==
nullptr)
469 Logging::error(path,
"Can't open info file for title %1.", vtsnum);
479 int audio_stream = 0;
486 if (vts_file->vtsi_mat)
490 video_settings.
m_height = (vts_file->vtsi_mat->vts_video_attr.video_format != 0) ? 576 : 480;
492 switch(vts_file->vtsi_mat->vts_video_attr.picture_size)
517 Logging::warning(path,
"DVD video contains invalid picture size attribute.");
523 for (
int chapter_idx = 0; chapter_idx < chapters && success; ++chapter_idx)
525 success =
create_dvd_virtualfile(vts_file, path, statbuf, buf, filler,
false, title_idx, chapter_idx, angles, ttnnum, audio_stream, audio_settings, video_settings);
528 if (success && chapters > 1)
531 success =
create_dvd_virtualfile(vts_file, path, statbuf, buf, filler,
true, title_idx, 0, 1, ttnnum, audio_stream, audio_settings, video_settings);
550int check_dvd(
const std::string & path,
void *buf, fuse_fill_dir_t filler)
552 std::string _path(path);
558 if (stat((_path +
"VIDEO_TS.IFO").c_str(), &stbuf) == 0 || stat((_path +
"VIDEO_TS/VIDEO_TS.IFO").c_str(), &stbuf) == 0)
563 res =
parse_dvd(_path, &stbuf, buf, filler);
568 res =
load_path(_path, &stbuf, buf, filler);
static void warning(const T filename, const std::string &format_string, Args &&...args)
Write warning level log entry.
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
static void error(const T filename, const std::string &format_string, Args &&...args)
Write error level log entry.
VIDEO_SETTINGS const * LPCVIDEO_SETTINGS
Pointer to const version of VIDEO_SETTINGS.
AUDIO_SETTINGS const * LPCAUDIO_SETTINGS
Pointer to const version of AUDIO_SETTINGS.
AUDIO_SETTINGS * LPAUDIO_SETTINGS
Pointer version of AUDIO_SETTINGS.
static int64_t BCDtime(const dvd_time_t *dvd_time)
Convert a time in BCD format into AV_TIMEBASE fractional seconds.
static bool create_dvd_virtualfile(const ifo_handle_t *vts_file, const std::string &path, const struct stat *statbuf, void *buf, fuse_fill_dir_t filler, bool full_title, int title_idx, int chapter_idx, int angles, int ttnnum, int audio_stream, const AUDIO_SETTINGS &audio_settings, const VIDEO_SETTINGS &video_settings)
Create a virtual file for a DVD.
static AVRational dvd_frame_rate(const uint8_t *ptr)
Get the frame rate of the DVD. Can be 25 fps (PAL) or 29.97 (NTCS).
VIDEO_SETTINGS * LPVIDEO_SETTINGS
Pointer version of VIDEO_SETTINGS.
struct AUDIO_SETTINGS AUDIO_SETTINGS
Audio stream settings.
int check_dvd(const std::string &path, void *buf, fuse_fill_dir_t filler)
Get number of titles on DVD.
static int dvd_find_best_audio_stream(const vtsi_mat_t *vtsi_mat, int *best_channels, int *best_sample_frequency)
Locate best matching audio stream.
static int parse_dvd(const std::string &path, const struct stat *statbuf, void *buf, fuse_fill_dir_t filler)
Parse DVD directory and get all DVD titles and chapters as virtual files.
struct VIDEO_SETTINGS VIDEO_SETTINGS
Video stream settings.
std::string format_duration(int64_t value, uint32_t fracs)
Format a time in format HH:MM:SS.fract.
std::string format_bitrate(BITRATE value)
Format a bit rate.
const std::string & append_sep(std::string *path)
Add / to the path if required.
std::string format_size(uint64_t value)
Format size.
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Same as std::string replace(), but replaces all occurrences.
#define BITRATE
For FFmpeg bit rate is an int.
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
@ VIDEO
FFmpegfs_Format info, 0: video file.
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
FFMPEGFS_FORMAT_ARR ffmpeg_format
Two FFmpegfs_Format infos, 0: video file, 1: audio file.
Main include for FFmpegfs project.
int add_dotdot(void *buf, fuse_fill_dir_t filler, const struct stat *stbuf, off_t off)
Make dot and double dot entries for a virtual directory.
LPVIRTUALFILE insert_dir(VIRTUALTYPE type, const std::string &virtdir, const struct stat *stbuf, int flags=VIRTUALFLAG_NONE)
Add new virtual directory to the internal list. If the file already exists, it will be updated.
int add_fuse_entry(void *buf, fuse_fill_dir_t filler, const std::string &name, const struct stat *stbuf, off_t off)
Wrapper to the Fuse filler function.
int load_path(const std::string &path, const struct stat *statbuf, void *buf, fuse_fill_dir_t filler)
Load a path with virtual files for FUSE.
bool check_path(const std::string &path)
Check if the path has already been parsed. Only useful if for DVD, Blu-ray or VCD where it is guarant...
LPVIRTUALFILE insert_file(VIRTUALTYPE type, const std::string &virtfile, const struct stat *stbuf, int flags=VIRTUALFLAG_NONE)
Add new virtual file to internal list.
Provide various log facilities to stderr, disk or syslog.
int m_sample_rate
number of audio samples per second
int m_channels
number of channels (1: mono, 2: stereo, or more)
BITRATE m_audio_bit_rate
average bitrate of audio data (in bits per second)
int m_min_dvd_chapter_duration
Min. DVD chapter duration. Shorter chapters will be ignored.
int m_height
video height in pixels
BITRATE m_video_bit_rate
average bitrate of video data (in bits per second)
int m_width
video width in pixels
int m_angle_no
Selected angle number (1...n)
int m_title_no
Track number (1...n)
int m_chapter_no
Chapter number (1...n)
int m_sample_rate
Audio sample rate - Filled in for the DVD/Blu-ray directory.
struct VIRTUALFILE::DVD_CHAPTER m_dvd
DVD title/chapter info.
bool m_full_title
If true, ignore m_chapter_no and provide full track.
std::string m_destfile
Name and path of destination file.
size_t m_predicted_size
Use this as the size instead of computing it over and over.
int m_width
Video width - Filled in for the DVD/Blu-ray directory.
int m_height
Video height - Filled in for the DVD/Blu-ray directory.
int m_channels
Audio channels - Filled in for the DVD/Blu-ray directory.
AVRational m_framerate
Video frame rate - Filled in for the DVD/Blu-ray directory.
struct stat m_st
stat structure with size etc.
size_t m_format_idx
Index into params.format[] array.
uint32_t m_video_frame_count
Number of frames in video or 0 if not a video.
int64_t m_duration
Track/chapter duration, in AV_TIME_BASE fractional seconds.
bool transcoder_set_filesize(LPVIRTUALFILE virtualfile, int64_t duration, BITRATE audio_bit_rate, int channels, int sample_rate, AVSampleFormat sample_format, BITRATE video_bit_rate, int width, int height, bool interleaved, const AVRational &framerate)
Set the file size.
bool transcoder_cached_filesize(LPVIRTUALFILE virtualfile, struct stat *stbuf)
Simply get encoded file size (do not create the whole encoder/decoder objects)
File transcoder interface (for use with by FUSE)