FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
srtdec.c
Go to the documentation of this file.
1 /*
2  * SubRip subtitle demuxer
3  * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
4  * Copyright (c) 2015 Clément Bœsch <u pkh me>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "avformat.h"
24 #include "internal.h"
25 #include "subtitles.h"
26 #include "libavutil/bprint.h"
27 #include "libavutil/intreadwrite.h"
28 
29 typedef struct {
31 } SRTContext;
32 
33 static int srt_probe(AVProbeData *p)
34 {
35  int v;
36  char buf[64], *pbuf;
37  FFTextReader tr;
38 
39  ff_text_init_buf(&tr, p->buf, p->buf_size);
40 
41  while (ff_text_peek_r8(&tr) == '\r' || ff_text_peek_r8(&tr) == '\n')
42  ff_text_r8(&tr);
43 
44  /* Check if the first non-empty line is a number. We do not check what the
45  * number is because in practice it can be anything.
46  * Also, that number can be followed by random garbage, so we can not
47  * unfortunately check that we only have a number. */
48  if (ff_subtitles_read_line(&tr, buf, sizeof(buf)) < 0 ||
49  strtol(buf, &pbuf, 10) < 0 || pbuf == buf)
50  return 0;
51 
52  /* Check if the next line matches a SRT timestamp */
53  if (ff_subtitles_read_line(&tr, buf, sizeof(buf)) < 0)
54  return 0;
55  if (buf[0] >= '0' && buf[0] <= '9' && strstr(buf, " --> ")
56  && sscanf(buf, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1)
57  return AVPROBE_SCORE_MAX;
58 
59  return 0;
60 }
61 
62 struct event_info {
64  int duration;
65  int64_t pts;
66  int64_t pos;
67 };
68 
69 static int get_event_info(const char *line, struct event_info *ei)
70 {
71  int hh1, mm1, ss1, ms1;
72  int hh2, mm2, ss2, ms2;
73 
74  ei->x1 = ei->x2 = ei->y1 = ei->y2 = ei->duration = -1;
75  ei->pts = AV_NOPTS_VALUE;
76  ei->pos = -1;
77  if (sscanf(line, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d"
78  "%*[ ]X1:%u X2:%u Y1:%u Y2:%u",
79  &hh1, &mm1, &ss1, &ms1,
80  &hh2, &mm2, &ss2, &ms2,
81  &ei->x1, &ei->x2, &ei->y1, &ei->y2) >= 8) {
82  const int64_t start = (hh1*3600LL + mm1*60LL + ss1) * 1000LL + ms1;
83  const int64_t end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2;
84  ei->duration = end - start;
85  ei->pts = start;
86  return 0;
87  }
88  return -1;
89 }
90 
91 static int add_event(FFDemuxSubtitlesQueue *q, AVBPrint *buf, char *line_cache,
92  const struct event_info *ei, int append_cache)
93 {
94  if (append_cache && line_cache[0])
95  av_bprintf(buf, "%s\n", line_cache);
96  line_cache[0] = 0;
97 
98  while (buf->len > 0 && buf->str[buf->len - 1] == '\n')
99  buf->str[--buf->len] = 0;
100 
101  if (buf->len) {
102  AVPacket *sub = ff_subtitles_queue_insert(q, buf->str, buf->len, 0);
103  if (!sub)
104  return AVERROR(ENOMEM);
105  av_bprint_clear(buf);
106  sub->pos = ei->pos;
107  sub->pts = ei->pts;
108  sub->duration = ei->duration;
109  if (ei->x1 != -1) {
111  if (p) {
112  AV_WL32(p, ei->x1);
113  AV_WL32(p + 4, ei->y1);
114  AV_WL32(p + 8, ei->x2);
115  AV_WL32(p + 12, ei->y2);
116  }
117  }
118  }
119 
120  return 0;
121 }
122 
124 {
125  SRTContext *srt = s->priv_data;
126  AVBPrint buf;
128  int res = 0;
129  char line[4096], line_cache[4096];
130  int has_event_info = 0;
131  struct event_info ei;
132  FFTextReader tr;
133  ff_text_init_avio(s, &tr, s->pb);
134 
135  if (!st)
136  return AVERROR(ENOMEM);
137  avpriv_set_pts_info(st, 64, 1, 1000);
140 
142 
143  line_cache[0] = 0;
144 
145  while (!ff_text_eof(&tr)) {
146  struct event_info tmp_ei;
147  const int64_t pos = ff_text_pos(&tr);
148  ptrdiff_t len = ff_subtitles_read_line(&tr, line, sizeof(line));
149 
150  if (len < 0)
151  break;
152 
153  if (!len || !line[0])
154  continue;
155 
156  if (get_event_info(line, &tmp_ei) < 0) {
157  char *pline;
158 
159  if (!has_event_info)
160  continue;
161 
162  if (line_cache[0]) {
163  /* We got some cache and a new line so we assume the cached
164  * line was actually part of the payload */
165  av_bprintf(&buf, "%s\n", line_cache);
166  line_cache[0] = 0;
167  }
168 
169  /* If the line doesn't start with a number, we assume it's part of
170  * the payload, otherwise is likely an event number preceding the
171  * timing information... but we can't be sure of this yet, so we
172  * cache it */
173  if (strtol(line, &pline, 10) < 0 || line == pline)
174  av_bprintf(&buf, "%s\n", line);
175  else
176  strcpy(line_cache, line);
177  } else {
178  if (has_event_info) {
179  /* We have the information of previous event, append it to the
180  * queue. We insert the cached line if and only if the payload
181  * is empty and the cached line is not a standalone number. */
182  char *pline = NULL;
183  const int standalone_number = strtol(line_cache, &pline, 10) >= 0 && pline && !*pline;
184  res = add_event(&srt->q, &buf, line_cache, &ei, !buf.len && !standalone_number);
185  if (res < 0)
186  goto end;
187  } else {
188  has_event_info = 1;
189  }
190  tmp_ei.pos = pos;
191  ei = tmp_ei;
192  }
193  }
194 
195  /* Append the last event. Here we force the cache to be flushed, because a
196  * trailing number is more likely to be geniune (for example a copyright
197  * date) and not the event index of an inexistant event */
198  if (has_event_info) {
199  res = add_event(&srt->q, &buf, line_cache, &ei, 1);
200  if (res < 0)
201  goto end;
202  }
203 
204  ff_subtitles_queue_finalize(s, &srt->q);
205 
206 end:
207  av_bprint_finalize(&buf, NULL);
208  return res;
209 }
210 
212 {
213  SRTContext *srt = s->priv_data;
214  return ff_subtitles_queue_read_packet(&srt->q, pkt);
215 }
216 
217 static int srt_read_seek(AVFormatContext *s, int stream_index,
218  int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
219 {
220  SRTContext *srt = s->priv_data;
221  return ff_subtitles_queue_seek(&srt->q, s, stream_index,
222  min_ts, ts, max_ts, flags);
223 }
224 
226 {
227  SRTContext *srt = s->priv_data;
229  return 0;
230 }
231 
233  .name = "srt",
234  .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"),
235  .priv_data_size = sizeof(SRTContext),
239  .read_seek2 = srt_read_seek,
241 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
static int get_event_info(const char *line, struct event_info *ei)
Definition: srtdec.c:69
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1487
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4149
Subtitle event position.
Definition: avcodec.h:1379
int32_t y2
Definition: srtdec.c:63
void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q)
Remove and destroy all the subtitles packets.
Definition: subtitles.c:297
FFDemuxSubtitlesQueue q
Definition: srtdec.c:30
int ff_text_peek_r8(FFTextReader *r)
Like ff_text_r8(), but don't remove the byte from the buffer.
Definition: subtitles.c:97
static int srt_read_close(AVFormatContext *s)
Definition: srtdec.c:225
int32_t x1
Definition: srtdec.c:63
static AVPacket pkt
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
int64_t pts
Definition: srtdec.c:65
static int add_event(FFDemuxSubtitlesQueue *q, AVBPrint *buf, char *line_cache, const struct event_info *ei, int append_cache)
Definition: srtdec.c:91
Format I/O context.
Definition: avformat.h:1314
uint8_t
int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt)
Generic read_packet() callback for subtitles demuxers using this queue system.
Definition: subtitles.c:208
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1485
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:3805
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
#define AV_BPRINT_SIZE_UNLIMITED
int ff_text_eof(FFTextReader *r)
Return non-zero if EOF was reached.
Definition: subtitles.c:92
#define AVERROR(e)
Definition: error.h:43
ptrdiff_t ff_subtitles_read_line(FFTextReader *tr, char *buf, size_t size)
Read a line of text.
Definition: subtitles.c:406
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:176
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
Definition: graph2dot.c:48
void ff_text_init_avio(void *s, FFTextReader *r, AVIOContext *pb)
Initialize the FFTextReader from the given AVIOContext.
Definition: subtitles.c:27
static int srt_probe(AVProbeData *p)
Definition: srtdec.c:33
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:896
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:463
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:462
int64_t ff_text_pos(FFTextReader *r)
Return the byte position of the next byte returned by ff_text_r8().
Definition: subtitles.c:60
int duration
Definition: srtdec.c:64
int64_t pos
Definition: srtdec.c:66
static int read_probe(AVProbeData *pd)
Definition: jvdec.c:55
int32_t
int32_t y1
Definition: srtdec.c:63
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:638
int ff_text_r8(FFTextReader *r)
Return the next byte.
Definition: subtitles.c:65
Stream structure.
Definition: avformat.h:877
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Update current_sub_idx to emulate a seek.
Definition: subtitles.c:245
enum AVMediaType codec_type
Definition: avcodec.h:1540
enum AVCodecID codec_id
Definition: avcodec.h:1549
AVIOContext * pb
I/O context.
Definition: avformat.h:1356
int32_t x2
Definition: srtdec.c:63
void * buf
Definition: avisynth_c.h:553
AVInputFormat ff_srt_demuxer
Definition: srtdec.c:232
This structure contains the data a format has to probe a file.
Definition: avformat.h:460
static int flags
Definition: cpu.c:47
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:472
Main libavformat public API header.
static int srt_read_seek(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Definition: srtdec.c:217
void ff_text_init_buf(FFTextReader *r, void *buf, size_t size)
Similar to ff_text_init_avio(), but sets it up to read from a bounded buffer.
Definition: subtitles.c:53
static int srt_read_header(AVFormatContext *s)
Definition: srtdec.c:123
static int srt_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: srtdec.c:211
int len
void * priv_data
Format private data.
Definition: avformat.h:1342
void INT64 start
Definition: avisynth_c.h:553
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:661
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size)
Allocate new information of a packet.
Definition: avpacket.c:299
AVPacket * ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, const uint8_t *event, size_t len, int merge)
Insert a new subtitle event.
Definition: subtitles.c:111
This structure stores compressed data.
Definition: avcodec.h:1444
void ff_subtitles_queue_finalize(void *log_ctx, FFDemuxSubtitlesQueue *q)
Set missing durations, sort subtitles by PTS (and then byte position), and drop duplicated events...
Definition: subtitles.c:193
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1460
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:240
#define AV_WL32(p, v)
Definition: intreadwrite.h:426