A lot of work for the coming VobSub reader and packetizer.

This commit is contained in:
Moritz Bunkus 2003-09-11 13:41:45 +00:00
parent a8ad6e621d
commit d42c0f0720
8 changed files with 436 additions and 289 deletions

View File

@ -22,6 +22,7 @@ mkvmerge_SOURCES = mkvmerge.cpp mkvmerge.h \
p_pcm.cpp p_pcm.h \
p_textsubs.cpp p_textsubs.h \
p_video.cpp p_video.h \
p_vobsub.cpp p_vobsub.h \
p_vorbis.cpp p_vorbis.h \
pr_generic.h pr_generic.cpp \
r_aac.cpp r_aac.h \
@ -35,6 +36,7 @@ mkvmerge_SOURCES = mkvmerge.cpp mkvmerge.h \
r_srt.cpp r_srt.h \
r_ssa.cpp r_ssa.h \
r_ogm.cpp r_ogm.h \
r_vobsub.cpp r_vobsub.h \
r_wav.cpp r_wav.h \
subtitles.cpp subtitles.h \
tagparser_start.cpp tagparser.h \
@ -65,13 +67,13 @@ base64tool_SOURCES = base64tool.cpp \
mkvmerge_LDADD = @AVILIB_LIBS@ @PROFILING_LIBS@ \
@MATROSKA_LIBS@ @EBML_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ \
@ICONV_LIBS@ @MINGW_LIBS@ @EXPAT_LIBS@ @ZLIB_LIBS@
@ICONV_LIBS@ @MINGW_LIBS@ @EXPAT_LIBS@ @ZLIB_LIBS@ @LZO_LIBS@
mkvinfo_LDADD = @PROFILING_LIBS@ @MATROSKA_LIBS@ @EBML_LIBS@ @ICONV_LIBS@ \
@WXWINDOWS_LIBS@ @MINGW_LIBS@
mkvextract_LDADD = @AVILIB_LIBS@ @PROFILING_LIBS@ @MATROSKA_LIBS@ @EBML_LIBS@ \
@VORBIS_LIBS@ @OGG_LIBS@ @ICONV_LIBS@
@VORBIS_LIBS@ @OGG_LIBS@ @ICONV_LIBS@ @LZO_LIBS@
base64tool_LDADD = @EBML_LIBS@ @ICONV_LIBS@

View File

@ -63,6 +63,12 @@ using namespace libebml;
#define TYPEREAL 14
#define TYPEQTMP4 15
/* compression types */
#define COMPRESSION_NONE 0
#define COMPRESSION_LZO 1
#define COMPRESSION_ZLIB 2
#define COMPRESSION_BZ2 3
#define FOURCC(a, b, c, d) (uint32_t)((((unsigned char)a) << 24) + \
(((unsigned char)b) << 16) + \
(((unsigned char)c) << 8) + \

View File

@ -53,5 +53,6 @@
#define MKV_S_TEXTSSA "S_TEXT/SSA"
#define MKV_S_TEXTASS "S_TEXT/ASS"
#define MKV_S_TEXTUSF "S_TEXT/USF"
#define MKV_S_VOBSUB "S_VOBSUB"
#endif // __MATROSKA_H

View File

@ -83,6 +83,7 @@
#include "r_real.h"
#include "r_srt.h"
#include "r_ssa.h"
#include "r_vobsub.h"
#include "r_wav.h"
#include "tagparser.h"
@ -202,6 +203,7 @@ file_type_t file_types[] =
{"rm ", TYPEREAL, "RealMedia audio and video"},
{"srt", TYPESRT, "SRT text subtitles"},
{"ssa", TYPESSA, "SSA/ASS text subtitles"},
{"idx", TYPEVOBSUB, "VobSub subtitles"},
{"wav", TYPEWAV, "WAVE (uncompressed PCM)"},
{"output modules:", -1, ""},
{" ", -1, "AAC audio"},
@ -368,6 +370,8 @@ static int get_type(char *filename) {
type = TYPESRT;
else if (ssa_reader_c::probe_file(mm_text_io, size))
type = TYPESSA;
else if (vobsub_reader_c::probe_file(mm_text_io, size))
type = TYPEVOBSUB;
else
type = TYPEUNKNOWN;
@ -931,6 +935,9 @@ static void create_readers() {
case TYPESSA:
file->reader = new ssa_reader_c(file->ti);
break;
case TYPEVOBSUB:
file->reader = new vobsub_reader_c(file->ti);
break;
case TYPEQTMP4:
file->reader = new qtmp4_reader_c(file->ti);
break;

123
src/p_vobsub.cpp Normal file
View File

@ -0,0 +1,123 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_vobsub.cpp
Written by Moritz Bunkus <moritz@bunkus.org>
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version $Id$
\brief VobSub packetizer
\author Moritz Bunkus <moritz@bunkus.org>
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <lzo1x.h>
#include "common.h"
#include "p_vobsub.h"
#include "matroska.h"
using namespace libmatroska;
vobsub_packetizer_c::vobsub_packetizer_c(generic_reader_c *nreader,
const void *nidx_data,
int nidx_data_size,
const void *nifo_data,
int nifo_data_size,
int ncompression_type,
int ncompressed_type,
track_info_t *nti) throw (error_c):
generic_packetizer_c(nreader, nti) {
idx_data = (unsigned char *)safememdup(nidx_data, nidx_data_size);
idx_data_size = nidx_data_size;
if ((nifo_data != NULL) && (nifo_data_size != 0)) {
ifo_data = (unsigned char *)safememdup(nifo_data, nifo_data_size);
ifo_data_size = nifo_data_size;
} else {
ifo_data = NULL;
ifo_data_size = 0;
}
compression_type = ncompression_type;
compressed_type = ncompressed_type;
set_track_type(track_subtitle);
}
void vobsub_packetizer_c::set_headers() {
string codec_id;
unsigned char *priv;
int priv_size, i, size_tmp;
codec_id = MKV_S_VOBSUB;
if (compression_type == COMPRESSION_LZO)
codec_id += "/LZO";
else if (compression_type == COMPRESSION_ZLIB)
codec_id += "/Z";
else if (compression_type == COMPRESSION_BZ2)
codec_id += "/BZ2";
set_codec_id(codec_id.c_str());
priv_size = idx_data_size + 1;
if (ifo_data_size > 0)
priv_size += ifo_data_size + idx_data_size / 255 + 1;
priv = (unsigned char *)safemalloc(priv_size);
i = 1;
if (ifo_data_size > 0) {
priv[0] = 1;
size_tmp = ifo_data_size;
while (size_tmp >= 255) {
priv[i] = 0xff;
i++;
size_tmp -= 255;
}
priv[i] = size_tmp;
i++;
memcpy(&priv[i + idx_data_size], ifo_data, ifo_data_size);
} else {
priv[0] = 0;
}
memcpy(&priv[i], idx_data, idx_data_size);
set_codec_private(priv, priv_size);
safefree(priv);
generic_packetizer_c::set_headers();
track_entry->EnableLacing(false);
}
int vobsub_packetizer_c::process(unsigned char *buf, int size,
int64_t timecode, int64_t duration,
int64_t, int64_t) {
debug_enter("vobsub_packetizer_c::process");
add_packet(buf, size, timecode, duration, true);
debug_leave("vobsub_packetizer_c::process");
return EMOREDATA;
}
vobsub_packetizer_c::~vobsub_packetizer_c() {
safefree(idx_data);
safefree(ifo_data);
}
void vobsub_packetizer_c::dump_debug_info() {
mxdebug("vobsub_packetizer_c: queue: %d\n", packet_queue.size());
}

52
src/p_vobsub.h Normal file
View File

@ -0,0 +1,52 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_vobsub.h
Written by Moritz Bunkus <moritz@bunkus.org>
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version $Id$
\brief class definition for the VobSub output module
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef __P_VOBSUB_H
#define __P_VOBSUB_H
#include "os.h"
#include "common.h"
#include "pr_generic.h"
class vobsub_packetizer_c: public generic_packetizer_c {
private:
unsigned char *idx_data, *ifo_data;
int idx_data_size, ifo_data_size;
bool compressed;
int compression_type, compressed_type;
public:
vobsub_packetizer_c(generic_reader_c *nreader,
const void *nidx_data, int nidx_data_size,
const void *nifo_data, int nifo_data_size,
int ncompression_type, int ncompressed_type,
track_info_t *nti) throw (error_c);
virtual ~vobsub_packetizer_c();
virtual int process(unsigned char *buf, int size, int64_t old_timecode = -1,
int64_t duration = -1, int64_t bref = -1,
int64_t fref = -1);
virtual void set_headers();
virtual void dump_debug_info();
};
#endif // __P_VOBSUB_H

View File

@ -1,33 +1,44 @@
/*
ogmmerge -- utility for splicing together ogg bitstreams
mkvmerge -- utility for splicing together matroska files
from component media subtypes
r_vobsub.cpp
VobSub text subtitle reader module
r_vobsub.h
Written by Moritz Bunkus <moritz@bunkus.org>
Based on Xiph.org's 'oggmerge' found in their CVS repository
See http://www.xiph.org
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version $Id$
\brief VobSub stream reader
\author Moritz Bunkus <moritz@bunkus.org>
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ogg/ogg.h>
#include "ogmmerge.h"
#include "ogmstreams.h"
#include "common.h"
#include "mm_io.h"
#include "p_vobsub.h"
#include "r_vobsub.h"
#include "subtitles.h"
#define istimecodestr(s) (!strncmp(s, "timecode: ", 11))
using namespace std;
#define hexvalue(c) (isdigit(c) ? (c) - '0' : \
tolower(c) == 'a' ? 10 : \
tolower(c) == 'b' ? 11 : \
tolower(c) == 'c' ? 12 : \
tolower(c) == 'd' ? 13 : \
tolower(c) == 'e' ? 14 : 15)
#define istimecodestr(s) (!strncmp(s, "timecode: ", 10))
#define istimestampstr(s) (!strncmp(s, "timestamp: ", 11))
#define iscommafileposstr(s) (!strncmp(s, ", filepos: ", 11))
#define iscolon(s) (*(s) == ':')
#define istwodigits(s) (isdigit(*(s)) && isdigit(*(s + 1)))
@ -48,292 +59,237 @@
ishexdigit(*(s + 6)) && \
ishexdigit(*(s + 7)) && \
ishexdigit(*(s + 8)))
#define isvobsubline(s) (istimecodestr(s) && istimecode(s + 11) && \
// timestamp: 00:01:43:603, filepos: 000000000
#define isvobsubline_v3(s) ((strlen(s) >= 43) && \
istimestampstr(s) && istimecode(s + 11) && \
iscommafileposstr(s + 23) && \
isfilepos(s + 34))
#define isvobsubline_v7(s) ((strlen(s) >= 42) && \
istimecodestr(s) && istimecode(s + 10) && \
iscommafileposstr(s + 22) && \
isfilepos(s + 33))
#define PFX "vobsub_reader: "
int vobsub_reader_c::probe_file(mm_io_c *mm_io, int64_t size) {
char chunk[2048];
char chunk[80];
if (mm_io->setFilePointer(0, seek_beginning) != 0)
return 0;
if (fgets(chunk, 2047) == NULL)
return 0;
if (strncmp(chunk, "# VobSub index file, v7",
strlen("# VobSub index file, v7")))
return 0;
if (mm_io->setFilePointer(0, seek_beginning) != 0)
try {
mm_io->setFilePointer(0, seek_beginning);
if (mm_io->read(chunk, 80) != 80)
return 0;
if (strncasecmp(chunk, "# VobSub index file, v",
strlen("# VobSub index file, v")))
return 0;
mm_io->setFilePointer(0, seek_beginning);
} catch (...) {
return 0;
}
return 1;
}
vobsub_reader_c::vobsub_reader_c(char *fname, audio_sync_t *nasync)
throw (error_c) {
char *name;
vobsub_reader_c::vobsub_reader_c(track_info_t *nti) throw (error_c):
generic_reader_c(nti) {
mm_io_c *ifo_file;
string sub_name, ifo_name, line;
int len;
if ((file = fopen(fname, "r")) == NULL)
throw error_c("vobsub_reader: Could not open source file.");
if (!vobsub_reader_c::probe_file(0))
throw error_c("vobsub_reader: Source is not a valid VobSub index file.");
try {
idx_file = new mm_text_io_c(ti->fname);
} catch (...) {
throw error_c(PFX "Cound not open the source file.");
}
name = safestrdup(fname);
if ((strlen(name) > 4) && (name[strlen(name) - 4] == '.'))
name[strlen(name) - 4] = 0;
else
name = (char *)saferealloc(name, strlen(name) + 5);
strcat(name, ".sub");
if ((subfile = fopen(name, "r")) == NULL)
throw error_c("vobsub_reader: Could not open the sub file.");
sub_name = ti->fname;
len = sub_name.rfind(".");
if (len >= 0)
sub_name.erase(len);
sub_name += ".sub";
vobsub_packetizer = NULL;
all_packetizers = NULL;
num_packetizers = 0;
if (verbose)
mxprint(stdout, "Using VobSub subtitle reader for %s/%s.\n+-> Using " \
"VobSub subtitle output module for subtitles.\n", fname, name);
safefree(name);
memcpy(&async, nasync, sizeof(audio_sync_t));
if (ncomments == NULL)
comments = ncomments;
else
comments = dup_comments(ncomments);
try {
sub_file = new mm_io_c(sub_name.c_str(), MODE_READ);
} catch (...) {
string emsg = PFX "Could not open the sub file '";
emsg += sub_name;
emsg += "'.";
throw error_c(emsg.c_str());
}
ifo_name = ti->fname;
len = ifo_name.rfind(".");
if (len >= 0)
ifo_name.erase(len);
ifo_name += ".ifo";
ifo_file = NULL;
try {
ifo_file = new mm_io_c(ifo_name.c_str(), MODE_READ);
ifo_file->setFilePointer(0, seek_end);
ifo_data_size = ifo_file->getFilePointer();
ifo_file->setFilePointer(0);
ifo_data = (unsigned char *)safemalloc(ifo_data_size);
if (ifo_file->read(ifo_data, ifo_data_size) != ifo_data_size)
mxerror(PFX "Could not read the IFO file.\n");
delete ifo_file;
} catch (...) {
if (ifo_file != NULL)
delete ifo_file;
ifo_data = NULL;
ifo_data_size = 0;
}
idx_data = "";
last_filepos = -1;
last_timestamp = -1;
len = strlen("# VobSub index file, v");
if (!idx_file->getline2(line) ||
strncasecmp(line.c_str(), "# VobSub index file, v", len) ||
(line.length() < (len + 1)))
mxerror(PFX "No version number found.\n");
version = line[len] - '0';
len++;
while ((len < line.length()) && isdigit(line[len])) {
version = version * 10 + line[len] - '0';
len++;
}
mxverb(2, PFX "Version: %u\n", version);
if ((version != 3) && (version != 7))
mxerror(PFX "Unsupported file type version %d.\n", version);
if (!parse_headers())
throw error_c(PFX "The input file is not a valid VobSub file.");
packetizer = new vobsub_packetizer_c(this, idx_data.c_str(),
idx_data.length(), ifo_data,
ifo_data_size, COMPRESSION_LZO,
COMPRESSION_NONE, ti);
if (verbose) {
mxinfo("Using VobSub subtitle reader for '%s'/'%s'. ", ti->fname,
sub_name.c_str());
if (ifo_data_size != 0)
mxinfo("Using IFO file '%s'.", ifo_name.c_str());
else
mxinfo("No IFO file found.");
mxinfo("\n+-> Using VobSub subtitle output module for subtitles.\n");
}
}
vobsub_reader_c::~vobsub_reader_c() {
int i;
for (i = 0; i < num_packetizers; i++)
if (all_packetizers[i] != NULL)
delete all_packetizers[i];
if (comments != NULL)
free_comments(comments);
delete sub_file;
delete idx_file;
safefree(ifo_data);
delete packetizer;
}
void vobsub_reader_c::add_vobsub_packetizer(int width, int height,
char *palette, int langidx,
char *id, int index) {
all_packetizers = (vobsub_packetizer_c **)saferealloc(all_packetizers,
(num_packetizers + 1) *
sizeof(void *));
try {
vobsub_packetizer = new vobsub_packetizer_c(this, width, height, palette,
langidx, id, index,
&async);
} catch (error_c error) {
mxprint(stderr, "Error: vobsub_reader: Could not create a new "
"vobsub_packetizer: %s\n", error.get_error());
exit(1);
}
all_packetizers[num_packetizers] = vobsub_packetizer;
num_packetizers++;
}
bool vobsub_reader_c::parse_headers() {
int64_t pos;
string line;
const char *sline;
int vobsub_reader_c::read() {
ogg_int64_t start, filepos, last_start, last_filepos;
char *s, *s2;
int width = -1, height = -1;
char *palette = NULL;
int langidx = -1;
char *id = NULL;
int index = -1;
int lineno;
chunk[2047] = 0;
lineno = 0;
last_start = -1;
last_filepos = -1;
while (1) {
if (fgets(chunk, 2047) == NULL)
break;
lineno++;
if ((*chunk == 0) || (strchr("#\n\r", *chunk) != NULL))
pos = idx_file->getFilePointer();
if (!idx_file->getline2(line))
return false;
if ((line.length() == 0) || (line[0] == '#')) {
idx_data += line;
idx_data += "\n";
continue;
if (!strncmp(chunk, "size: ", 6)) {
if (sscanf(&chunk[6], "%dx%d", &width, &height) != 2) {
width = -1;
height = -1;
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"size:\" entry "
"on line %d. Ignored.\n", lineno);
}
} else if (!strncmp(chunk, "palette: ", 9)) {
if (strlen(chunk) < 10)
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"palette:\" entry "
"on line %d. Ignored.\n", lineno);
else
palette = safestrdup(&chunk[9]);
} else if (!strncmp(chunk, "langidx: ", 9)) {
langidx = strtol(&chunk[9], NULL, 10);
if ((langidx < 0) || (errno != 0)) {
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"langidx:\" entry "
"on line %d. Ignored.\n", lineno);
langidx = -1;
}
} else if (!strncmp(chunk, "id:", 3)) {
s = &chunk[3];
while (isblank(*s))
s++;
s2 = strchr(s, ',');
if (s2 == NULL) {
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"id:\" entry "
"on line %d. Ignored.\n", lineno);
continue;
}
*s2 = 0;
id = safestrdup(s);
s = s2 + 1;
while (isblank(*s))
s++;
if (strncmp(s, "index:", 6)) {
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"id:\" entry "
"on line %d. Ignored.\n", lineno);
continue;
}
s += 6;
while (isblank(*s))
s++;
index = strtol(s, NULL, 10);
if ((index < 0) || (errno != 0)) {
mxprint(stdout, "vobsub_reader: Warning: Incorrect \"id:\" entry "
"on line %d. Ignored.\n", lineno);
continue;
}
} else if (!isvobsubline(chunk))
mxprint(stdout, "vobsub_reader: Warning: Unknown line format on line "
"%d. Ignored.\n", lineno);
else if (vobsub_packetizer == NULL) {
if ((width == -1) || (height == -1)) {
mxprint(stdout, "vobsub_reader: No \"size:\" entry found. File seems "
"to be defect. Aborting.\n");
exit(1);
}
if (palette == NULL) {
mxprint(stdout, "vobsub_reader: No \"palette:\" entry found. File "
"seems to be defect. Aborting.\n");
exit(1);
}
if (langidx == -1) {
mxprint(stdout, "vobsub_reader: No \"langidx:\" entry found. File "
"seems to be defect. Aborting.\n");
exit(1);
}
if ((id == NULL) || (index == -1)) {
mxprint(stdout, "vobsub_reader: No \"id:\" entry found. File "
"seems to be defect. Aborting.\n");
exit(1);
}
add_vobsub_packetizer(width, height, palette, langidx, id, index);
width = -1;
height = -1;
if (palette != NULL) {
safefree(palette);
palette = NULL;
}
langidx = -1;
if (id != NULL) {
safefree(id);
id = NULL;
}
index = -1;
} else {
// timecode: 00:00:03:440, filepos: 000000000
// 0123456789012345678901234567890123456789012
// 1 2 3 4
chunk[13] = 0;
chunk[16] = 0;
chunk[19] = 0;
chunk[23] = 0;
start = atol(&chunk[11]) * 3600000 + atol(&chunk[14]) * 60000 +
atol(&chunk[17]) * 1000 + atol(&chunk[20]);
filepos = strtoll(&chunk[34], NULL, 16);
if ((last_start != -1) && (last_filepos != -1)) {
if (mm_io->setFilePointer(subfile, last_filepos, seek_beginning) != 0)
mxprint(stderr, "Warning: vobsub_reader: Could not seek to position "
"%lld. Ignoring this entry.\n", last_filepos);
else if (last_filepos == filepos)
mxprint(stderr, "Warning: vobsub_reader: This entry and the last "
"entry start at the same position in the file. Ignored.\n");
else {
s = (char *)safemalloc(filepos - last_filepos);
if (mm_io->read(s, 1, filepos - last_filepos, subfile) !=
(filepos - last_filepos))
mxprint(stderr, "Warning: vobsub_reader: Could not read entry "
"from the sub file. Ignored.\n");
else
vobsub_packetizer->process(last_start, start - last_start, s,
filepos - last_filepos, 0);
safefree(s);
}
}
last_start = start;
last_filepos = filepos;
mxprint(stdout, "line %d, start %lld, filepos %lld\n", lineno,
start, filepos);
}
sline = line.c_str();
if (((version == 3) && isvobsubline_v3(sline)) ||
((version == 7) && isvobsubline_v7(sline))) {
idx_file->setFilePointer(pos);
return true;
}
idx_data += line;
idx_data += "\n";
}
if ((last_start != -1) && (last_filepos != -1) &&
(vobsub_packetizer != NULL)) {
if (mm_io->setFilePointer(subfile, 0, seek_end) != 0) {
mxprint(stderr, "Warning: vobsub_reader: Could not seek to end of "
"the sub file. Ignoring last entry.\n");
vobsub_packetizer->produce_eos_packet();
return 0;
}
filepos = mm_io->getFilePointer();
if (mm_io->setFilePointer(subfile, last_filepos, seek_beginning) != 0)
mxprint(stderr, "Warning: vobsub_reader: Could not seek to position "
"%lld. Ignoring this entry.\n", last_filepos);
else if (last_filepos == filepos)
mxprint(stderr, "Warning: vobsub_reader: This entry and the last "
"entry start at the same position in the file. Ignored.\n");
else {
s = (char *)safemalloc(filepos - last_filepos);
if (mm_io->read(s, 1, filepos - last_filepos, subfile) !=
(filepos - last_filepos))
mxprint(stderr, "Warning: vobsub_reader: Could not read entry "
"from the sub file. Ignored.\n");
else
vobsub_packetizer->process(last_start, start - last_start, s,
filepos - last_filepos, 1);
safefree(s);
}
int vobsub_reader_c::read(generic_packetizer_c *) {
string line;
const char *s;
int64_t filepos, timestamp;
int hour, minute, second, msecond, timestamp_offset, filepos_offset, idx;
if (done)
return 0;
if (!idx_file->getline2(line)) {
if (last_filepos != -1) {
}
done = true;
return 0;
}
return 0;
}
s = line.c_str();
int vobsub_reader_c::serial_in_use(int serial) {
// return vobsubpacketizer->serial_in_use(serial);
return 0;
}
if ((version == 3) && !isvobsubline_v3(s))
return EMOREDATA;
if ((version == 7) && !isvobsubline_v7(s))
return EMOREDATA;
ogmmerge_page_t *vobsub_reader_c::get_header_page(int header_type) {
// return vobsubpacketizer->get_header_page(header_type);
return NULL;
}
if (version == 3) {
// timestamp: 00:01:43:603, filepos: 000000000
timestamp_offset = 11;
filepos_offset = 34;
} else if (version == 7) {
die(PFX "Version 7 has not been implemented yet.");
} else
die(PFX "Unknown version. Should not have happened.");
ogmmerge_page_t *vobsub_reader_c::get_page() {
// return vobsubpacketizer->get_page();
return NULL;
sscanf(&s[timestamp_offset], "%02d:%02d:%02d:%03d", &hour, &minute, &second,
&msecond);
timestamp = (int64_t)hour * 60 * 60 * 1000 +
(int64_t)minute * 60 * 1000 + (int64_t)second * 1000 + (int64_t)msecond;
idx = filepos_offset;
filepos = hexvalue(s[idx]);
idx++;
while ((idx < line.length()) && ishexdigit(s[idx])) {
filepos = filepos * 16 + hexvalue(s[idx]);
idx++;
}
mxverb(2, PFX "Timestamp: %lld, file pos: %lld\n", timestamp, filepos);
if (last_filepos == -1) {
last_filepos = filepos;
last_timestamp = timestamp;
return EMOREDATA;
}
// Now process the stuff...
return EMOREDATA;
}
int vobsub_reader_c::display_priority() {
return DISPLAYPRIORITY_LOW;
}
void vobsub_reader_c::reset() {
// if (vobsubpacketizer != NULL)
// vobsubpacketizer->reset();
}
static char wchar[] = "-\\|/-\\|/-";
void vobsub_reader_c::display_progress(bool final) {
mxprint(stdout, "working... %c\r", wchar[act_wchar]);
mxinfo("working... %c\r", wchar[act_wchar]);
act_wchar++;
if (act_wchar == strlen(wchar))
act_wchar = 0;
}
void vobsub_reader_c::identify() {
mxinfo("File '%s': container: VobSub\n", ti->fname);
mxinfo("Track ID 0: subtitles (VobSub)\n");
}
void vobsub_reader_c::set_headers() {
}

View File

@ -1,20 +1,23 @@
/*
ogmmerge -- utility for splicing together ogg bitstreams
mkvmerge -- utility for splicing together matroska files
from component media subtypes
r_vobsub.h
class definitions for the VobSub subtitle reader
Written by Moritz Bunkus <moritz@bunkus.org>
Based on Xiph.org's 'oggmerge' found in their CVS repository
See http://www.xiph.org
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version $Id$
\brief class definitions for the VobSub stream reader
\author Moritz Bunkus <moritz@bunkus.org>
*/
#ifndef __R_VOBSUB_H
#define __R_VOBSUB_H
@ -22,42 +25,39 @@
#include <stdio.h>
#include <ogg/ogg.h>
#include "ogmmerge.h"
#include "common.h"
#include "mm_io.h"
#include "pr_generic.h"
#include "p_vobsub.h"
class vobsub_reader_c: public generic_reader_c {
private:
char chunk[2048];
mm_io_c *mm_io, *subfile;
vobsub_packetizer_c *vobsub_packetizer, **all_packetizers;
int num_packetizers, act_wchar;
char **comments;
mm_io_c *sub_file;
mm_text_io_c *idx_file;
unsigned char *ifo_data;
int act_wchar, version, ifo_data_size;
string idx_data;
int64_t last_filepos, last_timestamp;
bool done;
vobsub_packetizer_c *packetizer;
public:
vobsub_reader_c(char *fname, track_info_t *nti) throw (error_c);
vobsub_reader_c(track_info_t *nti) throw (error_c);
virtual ~vobsub_reader_c();
virtual int read();
virtual int serial_in_use(int);
virtual ogmmerge_page_t *get_page();
virtual ogmmerge_page_t *get_header_page(int header_type =
PACKET_TYPE_HEADER);
virtual void reset();
virtual int display_priority();
virtual void display_progress();
virtual int read(generic_packetizer_c *ptzr);
virtual void set_headers();
virtual void identify();
virtual int display_priority();
virtual void display_progress(bool final = false);
static int probe_file(mm_io_c *mm_io, int64_t size);
private:
virtual void add_vobsub_packetizer(int width, int height,
char *palette, int langidx,
char *id, int index);
protected:
virtual bool parse_headers();
};
#endif // __R_VOBSUB_H