2 * SubRip subtitle demuxer
3 * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "subtitles.h"
25 #include "libavutil/bprint.h"
26 #include "libavutil/intreadwrite.h"
29 FFDemuxSubtitlesQueue q
;
32 static int srt_probe(AVProbeData
*p
)
37 ff_text_init_buf(&tr
, p
->buf
, p
->buf_size
);
39 while (ff_text_peek_r8(&tr
) == '\r' || ff_text_peek_r8(&tr
) == '\n')
43 if (ff_subtitles_read_line(&tr
, buf
, sizeof(buf
)) < 0)
45 if ((num
== i
|| num
+ 1 == i
)
46 && buf
[0] >= '0' && buf
[1] <= '9' && strstr(buf
, " --> ")
47 && sscanf(buf
, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v
) == 1)
48 return AVPROBE_SCORE_MAX
;
54 static int64_t get_pts(const char **buf
, int *duration
,
55 int32_t *x1
, int32_t *y1
, int32_t *x2
, int32_t *y2
)
60 int hh1
, mm1
, ss1
, ms1
;
61 int hh2
, mm2
, ss2
, ms2
;
62 if (sscanf(*buf
, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d"
63 "%*[ ]X1:%u X2:%u Y1:%u Y2:%u",
64 &hh1
, &mm1
, &ss1
, &ms1
,
65 &hh2
, &mm2
, &ss2
, &ms2
,
66 x1
, x2
, y1
, y2
) >= 8) {
67 int64_t start
= (hh1
*3600LL + mm1
*60LL + ss1
) * 1000LL + ms1
;
68 int64_t end
= (hh2
*3600LL + mm2
*60LL + ss2
) * 1000LL + ms2
;
69 *duration
= end
- start
;
70 *buf
+= ff_subtitles_next_line(*buf
);
73 *buf
+= ff_subtitles_next_line(*buf
);
75 return AV_NOPTS_VALUE
;
78 static int srt_read_header(AVFormatContext
*s
)
80 SRTContext
*srt
= s
->priv_data
;
82 AVStream
*st
= avformat_new_stream(s
, NULL
);
85 ff_text_init_avio(&tr
, s
->pb
);
88 return AVERROR(ENOMEM
);
89 avpriv_set_pts_info(st
, 64, 1, 1000);
90 st
->codec
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
91 st
->codec
->codec_id
= AV_CODEC_ID_SUBRIP
;
93 av_bprint_init(&buf
, 0, AV_BPRINT_SIZE_UNLIMITED
);
95 while (!ff_text_eof(&tr
)) {
96 ff_subtitles_read_text_chunk(&tr
, &buf
);
99 int64_t pos
= ff_text_pos(&tr
);
102 const char *ptr
= buf
.str
;
103 int32_t x1
= -1, y1
= -1, x2
= -1, y2
= -1;
106 pts
= get_pts(&ptr
, &duration
, &x1
, &y1
, &x2
, &y2
);
107 if (pts
!= AV_NOPTS_VALUE
) {
108 int len
= buf
.len
- (ptr
- buf
.str
);
111 sub
= ff_subtitles_queue_insert(&srt
->q
, ptr
, len
, 0);
113 res
= AVERROR(ENOMEM
);
118 sub
->duration
= duration
;
120 uint8_t *p
= av_packet_new_side_data(sub
, AV_PKT_DATA_SUBTITLE_POSITION
, 16);
132 ff_subtitles_queue_finalize(&srt
->q
);
135 av_bprint_finalize(&buf
, NULL
);
139 static int srt_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
141 SRTContext
*srt
= s
->priv_data
;
142 return ff_subtitles_queue_read_packet(&srt
->q
, pkt
);
145 static int srt_read_seek(AVFormatContext
*s
, int stream_index
,
146 int64_t min_ts
, int64_t ts
, int64_t max_ts
, int flags
)
148 SRTContext
*srt
= s
->priv_data
;
149 return ff_subtitles_queue_seek(&srt
->q
, s
, stream_index
,
150 min_ts
, ts
, max_ts
, flags
);
153 static int srt_read_close(AVFormatContext
*s
)
155 SRTContext
*srt
= s
->priv_data
;
156 ff_subtitles_queue_clean(&srt
->q
);
160 AVInputFormat ff_srt_demuxer
= {
162 .long_name
= NULL_IF_CONFIG_SMALL("SubRip subtitle"),
163 .priv_data_size
= sizeof(SRTContext
),
164 .read_probe
= srt_probe
,
165 .read_header
= srt_read_header
,
166 .read_packet
= srt_read_packet
,
167 .read_seek2
= srt_read_seek
,
168 .read_close
= srt_read_close
,