~ubuntu-branches/ubuntu/wily/mkvtoolnix/wily

« back to all changes in this revision

Viewing changes to src/input/r_srt.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Clément Stenac
  • Date: 2005-09-07 19:54:42 UTC
  • Revision ID: james.westby@ubuntu.com-20050907195442-funmigmy8ua340hq
Tags: upstream-1.5.6
Import upstream version 1.5.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   mkvmerge -- utility for splicing together matroska files
 
3
   from component media subtypes
 
4
 
 
5
   Distributed under the GPL
 
6
   see the file COPYING for details
 
7
   or visit http://www.gnu.org/copyleft/gpl.html
 
8
 
 
9
   $Id: r_srt.cpp 2951 2005-06-10 07:12:50Z mosu $
 
10
 
 
11
   Subripper subtitle reader
 
12
 
 
13
   Written by Moritz Bunkus <moritz@bunkus.org>.
 
14
*/
 
15
 
 
16
#include <ctype.h>
 
17
#include <stdlib.h>
 
18
#include <stdio.h>
 
19
#include <string.h>
 
20
#include <errno.h>
 
21
 
 
22
#include "pr_generic.h"
 
23
#include "r_srt.h"
 
24
#include "subtitles.h"
 
25
#include "matroska.h"
 
26
 
 
27
using namespace std;
 
28
 
 
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)) && \
 
33
                          isdigit(*(s + 2)))
 
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) && \
 
38
                        isthreedigits(s + 9))
 
39
#define issrttimecode(s) (istimecode(s) && isarrow(s + 12) && \
 
40
                           istimecode(s + 17))
 
41
 
 
42
int
 
43
srt_reader_c::probe_file(mm_text_io_c *io,
 
44
                         int64_t) {
 
45
  string s;
 
46
  int64_t dummy;
 
47
 
 
48
  try {
 
49
    io->setFilePointer(0, seek_beginning);
 
50
    s = io->getline();
 
51
    strip(s);
 
52
    if (!parse_int(s, dummy))
 
53
      return 0;
 
54
    s = io->getline();
 
55
    if ((s.length() < 29) || !issrttimecode(s.c_str()))
 
56
      return 0;
 
57
    s = io->getline();
 
58
    io->setFilePointer(0, seek_beginning);
 
59
  } catch (...) {
 
60
    return 0;
 
61
  }
 
62
  return 1;
 
63
}
 
64
 
 
65
srt_reader_c::srt_reader_c(track_info_c &_ti)
 
66
  throw (error_c):
 
67
  generic_reader_c(_ti) {
 
68
 
 
69
  try {
 
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.
 
74
  } catch (...) {
 
75
    throw error_c("srt_reader: Could not open the source file.");
 
76
  }
 
77
  if (verbose)
 
78
    mxinfo(FMT_FN "Using the SRT subtitle reader.\n", ti.fname.c_str());
 
79
  parse_file();
 
80
}
 
81
 
 
82
srt_reader_c::~srt_reader_c() {
 
83
  delete io;
 
84
}
 
85
 
 
86
void
 
87
srt_reader_c::create_packetizer(int64_t) {
 
88
  bool is_utf8;
 
89
 
 
90
  if (NPTZR() != 0)
 
91
    return;
 
92
 
 
93
  is_utf8 = io->get_byte_order() != BO_NONE;
 
94
  add_packetizer(new textsubs_packetizer_c(this, MKV_S_TEXTUTF8, NULL, 0,
 
95
                                           true, is_utf8, ti));
 
96
  mxinfo(FMT_TID "Using the text subtitle output module.\n", ti.fname.c_str(),
 
97
         (int64_t)0);
 
98
}
 
99
 
 
100
#define STATE_INITIAL         0
 
101
#define STATE_SUBS            1
 
102
#define STATE_SUBS_OR_NUMBER  2
 
103
#define STATE_TIME            3
 
104
 
 
105
void
 
106
srt_reader_c::parse_file() {
 
107
  int64_t start, end, previous_start;
 
108
  char *chunk;
 
109
  string s, subtitles;
 
110
  int state, i, line_number;
 
111
  bool non_number_found, timecode_warning_printed;
 
112
 
 
113
  start = 0;
 
114
  end = 0;
 
115
  previous_start = 0;
 
116
  timecode_warning_printed = false;
 
117
  state = STATE_INITIAL;
 
118
  line_number = 0;
 
119
  subtitles = "";
 
120
  while (1) {
 
121
    if (!io->getline2(s))
 
122
      break;
 
123
    line_number++;
 
124
    strip(s);
 
125
 
 
126
    if (s.length() == 0) {
 
127
      if ((state == STATE_INITIAL) || (state == STATE_TIME))
 
128
        continue;
 
129
      state = STATE_SUBS_OR_NUMBER;
 
130
      if (subtitles.length() > 0)
 
131
        subtitles += "\n";
 
132
      subtitles += "\n";
 
133
      continue;
 
134
    }
 
135
 
 
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;
 
143
          break;
 
144
        }
 
145
      if (non_number_found)
 
146
        break;
 
147
      state = STATE_TIME;
 
148
 
 
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);
 
154
        break;
 
155
      }
 
156
 
 
157
      if (subtitles.length() > 0) {
 
158
        strip(subtitles, true);
 
159
        subs.add(start, end, subtitles.c_str());
 
160
      }
 
161
 
 
162
      // 00:00:00,000 --> 00:00:00,000
 
163
      // 01234567890123456789012345678
 
164
      //           1         2
 
165
      chunk = safestrdup(s.c_str());
 
166
      chunk[2] = 0;
 
167
      chunk[5] = 0;
 
168
      chunk[8] = 0;
 
169
      chunk[12] = 0;
 
170
      chunk[19] = 0;
 
171
      chunk[22] = 0;
 
172
      chunk[25] = 0;
 
173
      chunk[29] = 0;
 
174
 
 
175
      start = atol(chunk) * 3600000 + atol(&chunk[3]) * 60000 +
 
176
        atol(&chunk[6]) * 1000 + atol(&chunk[9]);
 
177
      start *= 1000000;
 
178
      end = atol(&chunk[17]) * 3600000 + atol(&chunk[20]) * 60000 +
 
179
        atol(&chunk[23]) * 1000 + atol(&chunk[26]);
 
180
      end *= 1000000;
 
181
 
 
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(),
 
186
               line_number);
 
187
        timecode_warning_printed = true;
 
188
      }
 
189
      previous_start = start;
 
190
 
 
191
      safefree(chunk);
 
192
 
 
193
      subtitles = "";
 
194
      state = STATE_SUBS;
 
195
 
 
196
    } else if (state == STATE_SUBS) {
 
197
      if (subtitles.length() > 0)
 
198
        subtitles += "\n";
 
199
      subtitles += s;
 
200
 
 
201
    } else {
 
202
      non_number_found = false;
 
203
      for (i = 0; i < s.length(); i++)
 
204
        if (!isdigit(s[i])) {
 
205
          non_number_found = true;
 
206
          break;
 
207
        }
 
208
 
 
209
      if (!non_number_found)
 
210
        state = STATE_TIME;
 
211
      else {
 
212
        if (subtitles.length() > 0)
 
213
          subtitles += "\n";
 
214
        subtitles += s;
 
215
      }
 
216
    }
 
217
  }
 
218
 
 
219
  if (subtitles.length() > 0) {
 
220
    strip(subtitles, true);
 
221
    subs.add(start, end, subtitles.c_str());
 
222
  }
 
223
 
 
224
  subs.sort();
 
225
}
 
226
 
 
227
file_status_e
 
228
srt_reader_c::read(generic_packetizer_c *,
 
229
                   bool) {
 
230
  if (subs.empty())
 
231
    return FILE_STATUS_DONE;
 
232
 
 
233
  subs.process(PTZR0);
 
234
 
 
235
  if (subs.empty()) {
 
236
    flush_packetizers();
 
237
    return FILE_STATUS_DONE;
 
238
  }
 
239
  return FILE_STATUS_MOREDATA;
 
240
}
 
241
 
 
242
int
 
243
srt_reader_c::get_progress() {
 
244
  int num_entries;
 
245
 
 
246
  num_entries = subs.get_num_entries();
 
247
  if (num_entries == 0)
 
248
    return 100;
 
249
  return 100 * subs.get_num_processed() / num_entries;
 
250
}
 
251
 
 
252
void
 
253
srt_reader_c::identify() {
 
254
  mxinfo("File '%s': container: SRT\nTrack ID 0: subtitles (SRT)\n",
 
255
         ti.fname.c_str());
 
256
}