/src/ffmpeg/libavcodec/textdec.c
Line | Count | Source |
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 "config_components.h" |
27 | | |
28 | | #include "avcodec.h" |
29 | | #include "ass.h" |
30 | | #include "codec_internal.h" |
31 | | #include "libavutil/attributes.h" |
32 | | #include "libavutil/bprint.h" |
33 | | #include "libavutil/opt.h" |
34 | | |
35 | | typedef struct { |
36 | | AVClass *class; |
37 | | const char *linebreaks; |
38 | | int keep_ass_markup; |
39 | | int readorder; |
40 | | } TextContext; |
41 | | |
42 | | #define OFFSET(x) offsetof(TextContext, x) |
43 | | #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM |
44 | | static const AVOption options[] = { |
45 | | { "keep_ass_markup", "Set if ASS tags must be escaped", OFFSET(keep_ass_markup), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags=SD }, |
46 | | { NULL } |
47 | | }; |
48 | | |
49 | | static int text_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, |
50 | | int *got_sub_ptr, const AVPacket *avpkt) |
51 | 876k | { |
52 | 876k | int ret = 0; |
53 | 876k | AVBPrint buf; |
54 | 876k | const char *ptr = avpkt->data; |
55 | 876k | TextContext *text = avctx->priv_data; |
56 | | |
57 | 876k | av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); |
58 | 876k | if (ptr && avpkt->size > 0 && *ptr) { |
59 | 812k | ff_ass_bprint_text_event(&buf, ptr, avpkt->size, text->linebreaks, text->keep_ass_markup); |
60 | 812k | ret = ff_ass_add_rect(sub, buf.str, text->readorder++, 0, NULL, NULL); |
61 | 812k | } |
62 | 876k | av_bprint_finalize(&buf, NULL); |
63 | 876k | if (ret < 0) |
64 | 0 | return ret; |
65 | 876k | *got_sub_ptr = sub->num_rects > 0; |
66 | 876k | return avpkt->size; |
67 | 876k | } |
68 | | |
69 | | static av_cold void text_flush(AVCodecContext *avctx) |
70 | 178k | { |
71 | 178k | TextContext *text = avctx->priv_data; |
72 | 178k | if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) |
73 | 178k | text->readorder = 0; |
74 | 178k | } |
75 | | |
76 | | static const AVClass textsub_decoder_class = { |
77 | | .class_name = "text/vplayer/stl/pjs/subviewer1 decoder", |
78 | | .item_name = av_default_item_name, |
79 | | .option = options, |
80 | | .version = LIBAVUTIL_VERSION_INT, |
81 | | }; |
82 | | |
83 | | #if CONFIG_TEXT_DECODER |
84 | | const FFCodec ff_text_decoder = { |
85 | | .p.name = "text", |
86 | | CODEC_LONG_NAME("Raw text subtitle"), |
87 | | .priv_data_size = sizeof(TextContext), |
88 | | .p.type = AVMEDIA_TYPE_SUBTITLE, |
89 | | .p.id = AV_CODEC_ID_TEXT, |
90 | | FF_CODEC_DECODE_SUB_CB(text_decode_frame), |
91 | | .init = ff_ass_subtitle_header_default, |
92 | | .p.priv_class = &textsub_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 av_cold int linebreak_init(AVCodecContext *avctx) |
100 | 4.17k | { |
101 | 4.17k | TextContext *text = avctx->priv_data; |
102 | 4.17k | text->linebreaks = "|"; |
103 | 4.17k | return ff_ass_subtitle_header_default(avctx); |
104 | 4.17k | } |
105 | | |
106 | | #if CONFIG_VPLAYER_DECODER |
107 | | const FFCodec ff_vplayer_decoder = { |
108 | | .p.name = "vplayer", |
109 | | CODEC_LONG_NAME("VPlayer subtitle"), |
110 | | .priv_data_size = sizeof(TextContext), |
111 | | .p.type = AVMEDIA_TYPE_SUBTITLE, |
112 | | .p.id = AV_CODEC_ID_VPLAYER, |
113 | | FF_CODEC_DECODE_SUB_CB(text_decode_frame), |
114 | | .init = linebreak_init, |
115 | | .p.priv_class = &textsub_decoder_class, |
116 | | .flush = text_flush, |
117 | | }; |
118 | | #endif |
119 | | |
120 | | #if CONFIG_STL_DECODER |
121 | | const FFCodec ff_stl_decoder = { |
122 | | .p.name = "stl", |
123 | | CODEC_LONG_NAME("Spruce subtitle format"), |
124 | | .priv_data_size = sizeof(TextContext), |
125 | | .p.type = AVMEDIA_TYPE_SUBTITLE, |
126 | | .p.id = AV_CODEC_ID_STL, |
127 | | FF_CODEC_DECODE_SUB_CB(text_decode_frame), |
128 | | .init = linebreak_init, |
129 | | .p.priv_class = &textsub_decoder_class, |
130 | | .flush = text_flush, |
131 | | }; |
132 | | #endif |
133 | | |
134 | | #if CONFIG_PJS_DECODER |
135 | | const FFCodec ff_pjs_decoder = { |
136 | | .p.name = "pjs", |
137 | | CODEC_LONG_NAME("PJS subtitle"), |
138 | | .priv_data_size = sizeof(TextContext), |
139 | | .p.type = AVMEDIA_TYPE_SUBTITLE, |
140 | | .p.id = AV_CODEC_ID_PJS, |
141 | | FF_CODEC_DECODE_SUB_CB(text_decode_frame), |
142 | | .init = linebreak_init, |
143 | | .p.priv_class = &textsub_decoder_class, |
144 | | .flush = text_flush, |
145 | | }; |
146 | | #endif |
147 | | |
148 | | #if CONFIG_SUBVIEWER1_DECODER |
149 | | const FFCodec ff_subviewer1_decoder = { |
150 | | .p.name = "subviewer1", |
151 | | CODEC_LONG_NAME("SubViewer1 subtitle"), |
152 | | .priv_data_size = sizeof(TextContext), |
153 | | .p.type = AVMEDIA_TYPE_SUBTITLE, |
154 | | .p.id = AV_CODEC_ID_SUBVIEWER1, |
155 | | FF_CODEC_DECODE_SUB_CB(text_decode_frame), |
156 | | .init = linebreak_init, |
157 | | .p.priv_class = &textsub_decoder_class, |
158 | | .flush = text_flush, |
159 | | }; |
160 | | #endif |
161 | | |
162 | | #endif /* text subtitles with '|' line break */ |