3 * Copyright (c) 2008 Michael Niedermayer
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
26 #include "subtitles.h"
27 #include "libavcodec/internal.h"
28 #include "libavutil/bprint.h"
30 typedef struct ASSContext
{
31 FFDemuxSubtitlesQueue q
;
34 static int ass_probe(AVProbeData
*p
)
38 ff_text_init_buf(&tr
, p
->buf
, p
->buf_size
);
40 ff_text_read(&tr
, buf
, sizeof(buf
));
42 if (!memcmp(buf
, "[Script Info]", 13))
43 return AVPROBE_SCORE_MAX
;
48 static int ass_read_close(AVFormatContext
*s
)
50 ASSContext
*ass
= s
->priv_data
;
51 ff_subtitles_queue_clean(&ass
->q
);
55 static int read_ts(const uint8_t *p
, int64_t *start
, int *duration
)
58 int hh1
, mm1
, ss1
, ms1
;
59 int hh2
, mm2
, ss2
, ms2
;
61 if (sscanf(p
, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d",
62 &hh1
, &mm1
, &ss1
, &ms1
,
63 &hh2
, &mm2
, &ss2
, &ms2
) == 8) {
64 end
= (hh2
*3600LL + mm2
*60LL + ss2
) * 100LL + ms2
;
65 *start
= (hh1
*3600LL + mm1
*60LL + ss1
) * 100LL + ms1
;
66 *duration
= end
- *start
;
72 static int64_t get_line(AVBPrint
*buf
, FFTextReader
*tr
)
74 int64_t pos
= ff_text_pos(tr
);
78 char c
= ff_text_r8(tr
);
81 av_bprint_chars(buf
, c
, 1);
88 static int ass_read_header(AVFormatContext
*s
)
90 ASSContext
*ass
= s
->priv_data
;
91 AVBPrint header
, line
;
92 int header_remaining
, res
= 0;
95 ff_text_init_avio(&tr
, s
->pb
);
97 st
= avformat_new_stream(s
, NULL
);
99 return AVERROR(ENOMEM
);
100 avpriv_set_pts_info(st
, 64, 1, 100);
101 st
->codec
->codec_type
= AVMEDIA_TYPE_SUBTITLE
;
102 st
->codec
->codec_id
= AV_CODEC_ID_SSA
;
104 header_remaining
= INT_MAX
;
106 av_bprint_init(&header
, 0, AV_BPRINT_SIZE_UNLIMITED
);
107 av_bprint_init(&line
, 0, AV_BPRINT_SIZE_UNLIMITED
);
110 int64_t pos
= get_line(&line
, &tr
);
112 if (!line
.str
[0]) // EOF
115 if (!memcmp(line
.str
, "[Events]", 8))
116 header_remaining
= 2;
117 else if (line
.str
[0] == '[')
118 header_remaining
= INT_MAX
;
120 if (header_remaining
) {
121 av_bprintf(&header
, "%s", line
.str
);
124 int64_t ts_start
= AV_NOPTS_VALUE
;
128 if (read_ts(line
.str
, &ts_start
, &duration
) < 0)
130 sub
= ff_subtitles_queue_insert(&ass
->q
, line
.str
, line
.len
, 0);
132 res
= AVERROR(ENOMEM
);
137 sub
->duration
= duration
;
141 av_bprint_finalize(&line
, NULL
);
143 res
= avpriv_bprint_to_extradata(st
->codec
, &header
);
147 ff_subtitles_queue_finalize(&ass
->q
);
153 static int ass_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
155 ASSContext
*ass
= s
->priv_data
;
156 return ff_subtitles_queue_read_packet(&ass
->q
, pkt
);
159 static int ass_read_seek(AVFormatContext
*s
, int stream_index
,
160 int64_t min_ts
, int64_t ts
, int64_t max_ts
, int flags
)
162 ASSContext
*ass
= s
->priv_data
;
163 return ff_subtitles_queue_seek(&ass
->q
, s
, stream_index
,
164 min_ts
, ts
, max_ts
, flags
);
167 AVInputFormat ff_ass_demuxer
= {
169 .long_name
= NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
170 .priv_data_size
= sizeof(ASSContext
),
171 .read_probe
= ass_probe
,
172 .read_header
= ass_read_header
,
173 .read_packet
= ass_read_packet
,
174 .read_close
= ass_read_close
,
175 .read_seek2
= ass_read_seek
,