2 * SubRip subtitle muxer
3 * Copyright (c) 2012 Nicolas George <nicolas.george@normalesup.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 "libavutil/log.h"
25 #include "libavutil/intreadwrite.h"
27 /* TODO: add options for:
33 typedef struct SRTContext
{
37 static int srt_write_header(AVFormatContext
*avf
)
39 SRTContext
*srt
= avf
->priv_data
;
41 if (avf
->nb_streams
!= 1 ||
42 avf
->streams
[0]->codec
->codec_type
!= AVMEDIA_TYPE_SUBTITLE
) {
43 av_log(avf
, AV_LOG_ERROR
,
44 "SRT supports only a single subtitles stream.\n");
45 return AVERROR(EINVAL
);
47 if (avf
->streams
[0]->codec
->codec_id
!= AV_CODEC_ID_TEXT
&&
48 avf
->streams
[0]->codec
->codec_id
!= AV_CODEC_ID_SUBRIP
) {
49 av_log(avf
, AV_LOG_ERROR
,
50 "Unsupported subtitles codec: %s\n",
51 avcodec_get_name(avf
->streams
[0]->codec
->codec_id
));
52 return AVERROR(EINVAL
);
54 avpriv_set_pts_info(avf
->streams
[0], 64, 1, 1000);
59 static int srt_write_packet(AVFormatContext
*avf
, AVPacket
*pkt
)
61 SRTContext
*srt
= avf
->priv_data
;
64 int64_t s
= pkt
->pts
, e
, d
= pkt
->duration
;
65 int size
, x1
= -1, y1
= -1, x2
= -1, y2
= -1;
68 p
= av_packet_get_side_data(pkt
, AV_PKT_DATA_SUBTITLE_POSITION
, &size
);
69 if (p
&& size
== 16) {
77 /* For backward compatibility, fallback to convergence_duration. */
78 d
= pkt
->convergence_duration
;
79 if (s
== AV_NOPTS_VALUE
|| d
< 0) {
80 av_log(avf
, AV_LOG_WARNING
,
81 "Insufficient timestamps in event number %d.\n", srt
->index
);
85 avio_printf(avf
->pb
, "%d\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d",
87 (int)(s
/ 3600000), (int)(s
/ 60000) % 60,
88 (int)(s
/ 1000) % 60, (int)(s
% 1000),
89 (int)(e
/ 3600000), (int)(e
/ 60000) % 60,
90 (int)(e
/ 1000) % 60, (int)(e
% 1000));
92 avio_printf(avf
->pb
, " X1:%03d X2:%03d Y1:%03d Y2:%03d",
94 avio_printf(avf
->pb
, "\n");
96 avio_write(avf
->pb
, pkt
->data
, pkt
->size
);
97 avio_write(avf
->pb
, "\n\n", 2);
102 AVOutputFormat ff_srt_muxer
= {
104 .long_name
= NULL_IF_CONFIG_SMALL("SubRip subtitle"),
105 .mime_type
= "application/x-subrip",
107 .priv_data_size
= sizeof(SRTContext
),
108 .write_header
= srt_write_header
,
109 .write_packet
= srt_write_packet
,
110 .flags
= AVFMT_VARIABLE_FPS
| AVFMT_TS_NONSTRICT
,
111 .subtitle_codec
= AV_CODEC_ID_SUBRIP
,