blob: 964da72ad530fff14668bf18bb9ba7571b6b1020
1 | /* |
2 | * Copyright (c) 2012 Clément Bœsch |
3 | * |
4 | * This file is part of FFmpeg. |
5 | * |
6 | * FFmpeg is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2.1 of the License, or (at your option) any later version. |
10 | * |
11 | * FFmpeg is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with FFmpeg; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ |
20 | |
21 | /** |
22 | * @file |
23 | * Raw subtitles decoder |
24 | */ |
25 | |
26 | #include "avcodec.h" |
27 | #include "ass.h" |
28 | #include "libavutil/bprint.h" |
29 | #include "libavutil/opt.h" |
30 | |
31 | typedef struct { |
32 | AVClass *class; |
33 | const char *linebreaks; |
34 | int keep_ass_markup; |
35 | int readorder; |
36 | } TextContext; |
37 | |
38 | #define OFFSET(x) offsetof(TextContext, x) |
39 | #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM |
40 | static const AVOption options[] = { |
41 | { "keep_ass_markup", "Set if ASS tags must be escaped", OFFSET(keep_ass_markup), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags=SD }, |
42 | { NULL } |
43 | }; |
44 | |
45 | static int text_decode_frame(AVCodecContext *avctx, void *data, |
46 | int *got_sub_ptr, AVPacket *avpkt) |
47 | { |
48 | int ret = 0; |
49 | AVBPrint buf; |
50 | AVSubtitle *sub = data; |
51 | const char *ptr = avpkt->data; |
52 | TextContext *text = avctx->priv_data; |
53 | |
54 | av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); |
55 | if (ptr && avpkt->size > 0 && *ptr) { |
56 | ff_ass_bprint_text_event(&buf, ptr, avpkt->size, text->linebreaks, text->keep_ass_markup); |
57 | ret = ff_ass_add_rect(sub, buf.str, text->readorder++, 0, NULL, NULL); |
58 | } |
59 | av_bprint_finalize(&buf, NULL); |
60 | if (ret < 0) |
61 | return ret; |
62 | *got_sub_ptr = sub->num_rects > 0; |
63 | return avpkt->size; |
64 | } |
65 | |
66 | static void text_flush(AVCodecContext *avctx) |
67 | { |
68 | TextContext *text = avctx->priv_data; |
69 | if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) |
70 | text->readorder = 0; |
71 | } |
72 | |
73 | #define DECLARE_CLASS(decname) static const AVClass decname ## _decoder_class = { \ |
74 | .class_name = #decname " decoder", \ |
75 | .item_name = av_default_item_name, \ |
76 | .option = decname ## _options, \ |
77 | .version = LIBAVUTIL_VERSION_INT, \ |
78 | } |
79 | |
80 | #if CONFIG_TEXT_DECODER |
81 | #define text_options options |
82 | DECLARE_CLASS(text); |
83 | |
84 | AVCodec ff_text_decoder = { |
85 | .name = "text", |
86 | .long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), |
87 | .priv_data_size = sizeof(TextContext), |
88 | .type = AVMEDIA_TYPE_SUBTITLE, |
89 | .id = AV_CODEC_ID_TEXT, |
90 | .decode = text_decode_frame, |
91 | .init = ff_ass_subtitle_header_default, |
92 | .priv_class = &text_decoder_class, |
93 | .flush = text_flush, |
94 | }; |
95 | #endif |
96 | |
97 | #if CONFIG_VPLAYER_DECODER || CONFIG_PJS_DECODER || CONFIG_SUBVIEWER1_DECODER || CONFIG_STL_DECODER |
98 | |
99 | static int linebreak_init(AVCodecContext *avctx) |
100 | { |
101 | TextContext *text = avctx->priv_data; |
102 | text->linebreaks = "|"; |
103 | return ff_ass_subtitle_header_default(avctx); |
104 | } |
105 | |
106 | #if CONFIG_VPLAYER_DECODER |
107 | #define vplayer_options options |
108 | DECLARE_CLASS(vplayer); |
109 | |
110 | AVCodec ff_vplayer_decoder = { |
111 | .name = "vplayer", |
112 | .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), |
113 | .priv_data_size = sizeof(TextContext), |
114 | .type = AVMEDIA_TYPE_SUBTITLE, |
115 | .id = AV_CODEC_ID_VPLAYER, |
116 | .decode = text_decode_frame, |
117 | .init = linebreak_init, |
118 | .priv_class = &vplayer_decoder_class, |
119 | .flush = text_flush, |
120 | }; |
121 | #endif |
122 | |
123 | #if CONFIG_STL_DECODER |
124 | #define stl_options options |
125 | DECLARE_CLASS(stl); |
126 | |
127 | AVCodec ff_stl_decoder = { |
128 | .name = "stl", |
129 | .long_name = NULL_IF_CONFIG_SMALL("Spruce subtitle format"), |
130 | .priv_data_size = sizeof(TextContext), |
131 | .type = AVMEDIA_TYPE_SUBTITLE, |
132 | .id = AV_CODEC_ID_STL, |
133 | .decode = text_decode_frame, |
134 | .init = linebreak_init, |
135 | .priv_class = &stl_decoder_class, |
136 | .flush = text_flush, |
137 | }; |
138 | #endif |
139 | |
140 | #if CONFIG_PJS_DECODER |
141 | #define pjs_options options |
142 | DECLARE_CLASS(pjs); |
143 | |
144 | AVCodec ff_pjs_decoder = { |
145 | .name = "pjs", |
146 | .long_name = NULL_IF_CONFIG_SMALL("PJS subtitle"), |
147 | .priv_data_size = sizeof(TextContext), |
148 | .type = AVMEDIA_TYPE_SUBTITLE, |
149 | .id = AV_CODEC_ID_PJS, |
150 | .decode = text_decode_frame, |
151 | .init = linebreak_init, |
152 | .priv_class = &pjs_decoder_class, |
153 | .flush = text_flush, |
154 | }; |
155 | #endif |
156 | |
157 | #if CONFIG_SUBVIEWER1_DECODER |
158 | #define subviewer1_options options |
159 | DECLARE_CLASS(subviewer1); |
160 | |
161 | AVCodec ff_subviewer1_decoder = { |
162 | .name = "subviewer1", |
163 | .long_name = NULL_IF_CONFIG_SMALL("SubViewer1 subtitle"), |
164 | .priv_data_size = sizeof(TextContext), |
165 | .type = AVMEDIA_TYPE_SUBTITLE, |
166 | .id = AV_CODEC_ID_SUBVIEWER1, |
167 | .decode = text_decode_frame, |
168 | .init = linebreak_init, |
169 | .priv_class = &subviewer1_decoder_class, |
170 | .flush = text_flush, |
171 | }; |
172 | #endif |
173 | |
174 | #endif /* text subtitles with '|' line break */ |
175 |