2
mkvmerge -- utility for splicing together matroska files
3
from component media subtypes
5
Distributed under the GPL
6
see the file COPYING for details
7
or visit http://www.gnu.org/copyleft/gpl.html
9
$Id: r_srt.cpp 2951 2005-06-10 07:12:50Z mosu $
11
Subripper subtitle reader
13
Written by Moritz Bunkus <moritz@bunkus.org>.
22
#include "pr_generic.h"
24
#include "subtitles.h"
29
#define iscolon(s) (*(s) == ':')
30
#define iscomma(s) (*(s) == ',')
31
#define istwodigits(s) (isdigit(*(s)) && isdigit(*(s + 1)))
32
#define isthreedigits(s) (isdigit(*(s)) && isdigit(*(s + 1)) && \
34
#define isarrow(s) (!strncmp((s), " --> ", 5))
35
#define istimecode(s) (istwodigits(s) && iscolon(s + 2) && \
36
istwodigits(s + 3) && iscolon(s + 5) && \
37
istwodigits(s + 6) && iscomma(s + 8) && \
39
#define issrttimecode(s) (istimecode(s) && isarrow(s + 12) && \
43
srt_reader_c::probe_file(mm_text_io_c *io,
49
io->setFilePointer(0, seek_beginning);
52
if (!parse_int(s, dummy))
55
if ((s.length() < 29) || !issrttimecode(s.c_str()))
58
io->setFilePointer(0, seek_beginning);
65
srt_reader_c::srt_reader_c(track_info_c &_ti)
67
generic_reader_c(_ti) {
70
io = new mm_text_io_c(new mm_file_io_c(ti.fname));
71
if (!srt_reader_c::probe_file(io, 0))
72
throw error_c("srt_reader: Source is not a valid SRT file.");
73
ti.id = 0; // ID for this track.
75
throw error_c("srt_reader: Could not open the source file.");
78
mxinfo(FMT_FN "Using the SRT subtitle reader.\n", ti.fname.c_str());
82
srt_reader_c::~srt_reader_c() {
87
srt_reader_c::create_packetizer(int64_t) {
93
is_utf8 = io->get_byte_order() != BO_NONE;
94
add_packetizer(new textsubs_packetizer_c(this, MKV_S_TEXTUTF8, NULL, 0,
96
mxinfo(FMT_TID "Using the text subtitle output module.\n", ti.fname.c_str(),
100
#define STATE_INITIAL 0
102
#define STATE_SUBS_OR_NUMBER 2
106
srt_reader_c::parse_file() {
107
int64_t start, end, previous_start;
110
int state, i, line_number;
111
bool non_number_found, timecode_warning_printed;
116
timecode_warning_printed = false;
117
state = STATE_INITIAL;
121
if (!io->getline2(s))
126
if (s.length() == 0) {
127
if ((state == STATE_INITIAL) || (state == STATE_TIME))
129
state = STATE_SUBS_OR_NUMBER;
130
if (subtitles.length() > 0)
136
if (state == STATE_INITIAL) {
137
non_number_found = false;
138
for (i = 0; i < s.length(); i++)
139
if (!isdigit(s[i])) {
140
mxwarn(FMT_FN "Error in line %d: expected subtitle number "
141
"and found some text.\n", ti.fname.c_str(), line_number);
142
non_number_found = true;
145
if (non_number_found)
149
} else if (state == STATE_TIME) {
150
if ((s.length() < 29) || !issrttimecode(s.c_str())) {
151
mxwarn(FMT_FN "Error in line %d: expected a SRT timecode "
152
"line but found something else. Aborting this file.\n",
153
ti.fname.c_str(), line_number);
157
if (subtitles.length() > 0) {
158
strip(subtitles, true);
159
subs.add(start, end, subtitles.c_str());
162
// 00:00:00,000 --> 00:00:00,000
163
// 01234567890123456789012345678
165
chunk = safestrdup(s.c_str());
175
start = atol(chunk) * 3600000 + atol(&chunk[3]) * 60000 +
176
atol(&chunk[6]) * 1000 + atol(&chunk[9]);
178
end = atol(&chunk[17]) * 3600000 + atol(&chunk[20]) * 60000 +
179
atol(&chunk[23]) * 1000 + atol(&chunk[26]);
182
if (!timecode_warning_printed && (start < previous_start)) {
183
mxwarn(FMT_FN "Warning in line %d: The start timecode is smaller "
184
"than that of the previous entry. All entries from this file "
185
"will be sorted by their start time.\n", ti.fname.c_str(),
187
timecode_warning_printed = true;
189
previous_start = start;
196
} else if (state == STATE_SUBS) {
197
if (subtitles.length() > 0)
202
non_number_found = false;
203
for (i = 0; i < s.length(); i++)
204
if (!isdigit(s[i])) {
205
non_number_found = true;
209
if (!non_number_found)
212
if (subtitles.length() > 0)
219
if (subtitles.length() > 0) {
220
strip(subtitles, true);
221
subs.add(start, end, subtitles.c_str());
228
srt_reader_c::read(generic_packetizer_c *,
231
return FILE_STATUS_DONE;
237
return FILE_STATUS_DONE;
239
return FILE_STATUS_MOREDATA;
243
srt_reader_c::get_progress() {
246
num_entries = subs.get_num_entries();
247
if (num_entries == 0)
249
return 100 * subs.get_num_processed() / num_entries;
253
srt_reader_c::identify() {
254
mxinfo("File '%s': container: SRT\nTrack ID 0: subtitles (SRT)\n",