Line | Count | Source |
1 | | /* |
2 | | * This file is part of mpv. |
3 | | * |
4 | | * mpv is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * mpv is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | * GNU Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with mpv. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | #include <stdlib.h> |
19 | | #include <assert.h> |
20 | | |
21 | | #include <libavcodec/avcodec.h> |
22 | | #include <libavutil/intreadwrite.h> |
23 | | #include <libavutil/common.h> |
24 | | #include <libavutil/opt.h> |
25 | | |
26 | | #include "mpv_talloc.h" |
27 | | #include "common/msg.h" |
28 | | #include "common/av_common.h" |
29 | | #include "demux/stheader.h" |
30 | | #include "misc/bstr.h" |
31 | | #include "sd.h" |
32 | | |
33 | | struct lavc_conv { |
34 | | struct mp_log *log; |
35 | | struct mp_subtitle_opts *opts; |
36 | | bool styled; |
37 | | AVCodecContext *avctx; |
38 | | AVPacket *avpkt; |
39 | | AVPacket *avpkt_vtt; |
40 | | const char *codec; |
41 | | char *extradata; |
42 | | AVSubtitle cur; |
43 | | char **cur_list; |
44 | | }; |
45 | | |
46 | | static const char *get_lavc_format(const char *format) |
47 | 1.10k | { |
48 | | // For the hack involving parse_webvtt(). |
49 | 1.10k | if (format && strcmp(format, "webvtt-webm") == 0) |
50 | 0 | format = "webvtt"; |
51 | | // Most text subtitles are srt/html style anyway. |
52 | 1.10k | if (format && strcmp(format, "text") == 0) |
53 | 0 | format = "subrip"; |
54 | 1.10k | return format; |
55 | 1.10k | } |
56 | | |
57 | | struct lavc_conv *lavc_conv_create(struct sd *sd) |
58 | 1.10k | { |
59 | 1.10k | struct lavc_conv *priv = talloc_zero(NULL, struct lavc_conv); |
60 | 1.10k | priv->log = sd->log; |
61 | 1.10k | priv->opts = sd->opts; |
62 | 1.10k | priv->cur_list = talloc_array(priv, char*, 0); |
63 | 1.10k | priv->codec = sd->codec->codec; |
64 | 1.10k | AVCodecContext *avctx = NULL; |
65 | 1.10k | AVDictionary *opts = NULL; |
66 | 1.10k | const char *fmt = get_lavc_format(priv->codec); |
67 | 1.10k | const AVCodec *codec = avcodec_find_decoder(mp_codec_to_av_codec_id(fmt)); |
68 | 1.10k | if (!codec) |
69 | 71 | goto error; |
70 | 1.03k | avctx = avcodec_alloc_context3(codec); |
71 | 1.03k | if (!avctx) |
72 | 0 | goto error; |
73 | 1.03k | if (mp_set_avctx_codec_headers(avctx, sd->codec) < 0) |
74 | 0 | goto error; |
75 | | |
76 | 1.03k | MP_VERBOSE(sd, "Using subtitle decoder %s\n", codec->name); |
77 | | |
78 | 1.03k | priv->avpkt = av_packet_alloc(); |
79 | 1.03k | priv->avpkt_vtt = av_packet_alloc(); |
80 | 1.03k | if (!priv->avpkt || !priv->avpkt_vtt) |
81 | 0 | goto error; |
82 | | |
83 | 1.03k | switch (codec->id) { |
84 | 0 | case AV_CODEC_ID_DVB_TELETEXT: |
85 | 0 | av_dict_set_int(&opts, "txt_format", 2, 0); |
86 | 0 | break; |
87 | 0 | case AV_CODEC_ID_ARIB_CAPTION: |
88 | 0 | av_dict_set_int(&opts, "sub_type", SUBTITLE_ASS, 0); |
89 | 0 | break; |
90 | 1.03k | } |
91 | | |
92 | 1.03k | av_dict_set(&opts, "sub_text_format", "ass", 0); |
93 | 1.03k | av_dict_set(&opts, "flags2", "+ass_ro_flush_noop", 0); |
94 | 1.03k | if (strcmp(priv->codec, "eia_608") == 0) |
95 | 36 | av_dict_set(&opts, "real_time", "1", 0); |
96 | 1.03k | if (avcodec_open2(avctx, codec, &opts) < 0) |
97 | 5 | goto error; |
98 | 1.02k | av_dict_free(&opts); |
99 | | // Documented as "set by libavcodec", but there is no other way |
100 | 1.02k | avctx->time_base = (AVRational) {1, 1000}; |
101 | 1.02k | avctx->pkt_timebase = avctx->time_base; |
102 | 1.02k | avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_IGNORE; |
103 | 1.02k | priv->avctx = avctx; |
104 | 1.02k | priv->extradata = talloc_strndup(priv, avctx->subtitle_header, |
105 | 1.02k | avctx->subtitle_header_size); |
106 | 1.02k | mp_codec_info_from_av(avctx, sd->codec); |
107 | | // Keep original codec name, which get_lavc_format() may have transformed |
108 | 1.02k | sd->codec->codec = priv->codec; |
109 | 1.02k | return priv; |
110 | | |
111 | 76 | error: |
112 | 76 | MP_FATAL(priv, "Could not open libavcodec subtitle converter\n"); |
113 | 76 | av_dict_free(&opts); |
114 | 76 | avcodec_free_context(&avctx); |
115 | 76 | mp_free_av_packet(&priv->avpkt); |
116 | 76 | mp_free_av_packet(&priv->avpkt_vtt); |
117 | 76 | talloc_free(priv); |
118 | 76 | return NULL; |
119 | 1.03k | } |
120 | | |
121 | | char *lavc_conv_get_extradata(struct lavc_conv *priv) |
122 | 1.02k | { |
123 | 1.02k | return priv->extradata; |
124 | 1.02k | } |
125 | | |
126 | | // FFmpeg WebVTT packets are pre-parsed in some way. The FFmpeg Matroska |
127 | | // demuxer does this on its own. In order to free our demuxer_mkv.c from |
128 | | // codec-specific crud, we do this here. |
129 | | // Copied from libavformat/matroskadec.c (FFmpeg 818ebe9 / 2013-08-19) |
130 | | // License: LGPL v2.1 or later |
131 | | // Author header: The FFmpeg Project |
132 | | // Modified in some ways. |
133 | | static int parse_webvtt(AVPacket *in, AVPacket *pkt) |
134 | 0 | { |
135 | 0 | uint8_t *id, *settings, *text, *buf; |
136 | 0 | int id_len, settings_len, text_len; |
137 | 0 | uint8_t *p, *q; |
138 | 0 | int err; |
139 | |
|
140 | 0 | uint8_t *data = in->data; |
141 | 0 | int data_len = in->size; |
142 | |
|
143 | 0 | if (data_len <= 0) |
144 | 0 | return AVERROR_INVALIDDATA; |
145 | | |
146 | 0 | p = data; |
147 | 0 | q = data + data_len; |
148 | |
|
149 | 0 | id = p; |
150 | 0 | id_len = -1; |
151 | 0 | while (p < q) { |
152 | 0 | if (*p == '\r' || *p == '\n') { |
153 | 0 | id_len = p - id; |
154 | 0 | if (*p == '\r') |
155 | 0 | p++; |
156 | 0 | break; |
157 | 0 | } |
158 | 0 | p++; |
159 | 0 | } |
160 | |
|
161 | 0 | if (p >= q || *p != '\n') |
162 | 0 | return AVERROR_INVALIDDATA; |
163 | 0 | p++; |
164 | |
|
165 | 0 | settings = p; |
166 | 0 | settings_len = -1; |
167 | 0 | while (p < q) { |
168 | 0 | if (*p == '\r' || *p == '\n') { |
169 | 0 | settings_len = p - settings; |
170 | 0 | if (*p == '\r') |
171 | 0 | p++; |
172 | 0 | break; |
173 | 0 | } |
174 | 0 | p++; |
175 | 0 | } |
176 | |
|
177 | 0 | if (p >= q || *p != '\n') |
178 | 0 | return AVERROR_INVALIDDATA; |
179 | 0 | p++; |
180 | |
|
181 | 0 | text = p; |
182 | 0 | text_len = q - p; |
183 | 0 | while (text_len > 0) { |
184 | 0 | const int len = text_len - 1; |
185 | 0 | const uint8_t c = p[len]; |
186 | 0 | if (c != '\r' && c != '\n') |
187 | 0 | break; |
188 | 0 | text_len = len; |
189 | 0 | } |
190 | |
|
191 | 0 | if (text_len <= 0) |
192 | 0 | return AVERROR_INVALIDDATA; |
193 | | |
194 | 0 | err = av_new_packet(pkt, text_len); |
195 | 0 | if (err < 0) |
196 | 0 | return AVERROR(err); |
197 | | |
198 | 0 | memcpy(pkt->data, text, text_len); |
199 | |
|
200 | 0 | if (id_len > 0) { |
201 | 0 | buf = av_packet_new_side_data(pkt, |
202 | 0 | AV_PKT_DATA_WEBVTT_IDENTIFIER, |
203 | 0 | id_len); |
204 | 0 | if (buf == NULL) { |
205 | 0 | av_packet_unref(pkt); |
206 | 0 | return AVERROR(ENOMEM); |
207 | 0 | } |
208 | 0 | memcpy(buf, id, id_len); |
209 | 0 | } |
210 | | |
211 | 0 | if (settings_len > 0) { |
212 | 0 | buf = av_packet_new_side_data(pkt, |
213 | 0 | AV_PKT_DATA_WEBVTT_SETTINGS, |
214 | 0 | settings_len); |
215 | 0 | if (buf == NULL) { |
216 | 0 | av_packet_unref(pkt); |
217 | 0 | return AVERROR(ENOMEM); |
218 | 0 | } |
219 | 0 | memcpy(buf, settings, settings_len); |
220 | 0 | } |
221 | | |
222 | 0 | pkt->pts = in->pts; |
223 | 0 | pkt->duration = in->duration; |
224 | 0 | return 0; |
225 | 0 | } |
226 | | |
227 | | // Return a NULL-terminated list of ASS event lines and have |
228 | | // the AVSubtitle display PTS and duration set to input |
229 | | // double variables. |
230 | | char **lavc_conv_decode(struct lavc_conv *priv, struct demux_packet *packet, |
231 | | double *sub_pts, double *sub_duration) |
232 | 1.41k | { |
233 | 1.41k | AVCodecContext *avctx = priv->avctx; |
234 | 1.41k | AVPacket *curr_pkt = priv->avpkt; |
235 | 1.41k | int ret, got_sub; |
236 | 1.41k | int num_cur = 0; |
237 | | |
238 | 1.41k | avsubtitle_free(&priv->cur); |
239 | | |
240 | 1.41k | mp_set_av_packet(priv->avpkt, packet, &avctx->time_base); |
241 | 1.41k | if (priv->avpkt->pts < 0) |
242 | 15 | priv->avpkt->pts = 0; |
243 | | |
244 | 1.41k | if (strcmp(priv->codec, "webvtt-webm") == 0) { |
245 | 0 | if (parse_webvtt(priv->avpkt, priv->avpkt_vtt) < 0) { |
246 | 0 | MP_ERR(priv, "Error parsing subtitle\n"); |
247 | 0 | goto done; |
248 | 0 | } |
249 | 0 | curr_pkt = priv->avpkt_vtt; |
250 | 0 | } |
251 | | |
252 | 1.41k | priv->styled = avctx->codec_id == AV_CODEC_ID_DVB_TELETEXT; |
253 | | |
254 | 1.41k | if (avctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) { |
255 | 0 | if (!priv->opts->teletext_page) { |
256 | 0 | av_opt_set(avctx, "txt_page", "subtitle", AV_OPT_SEARCH_CHILDREN); |
257 | 0 | priv->styled = false; |
258 | 0 | } else if (priv->opts->teletext_page == -1) { |
259 | 0 | av_opt_set(avctx, "txt_page", "*", AV_OPT_SEARCH_CHILDREN); |
260 | 0 | } else { |
261 | 0 | char page[4]; |
262 | 0 | snprintf(page, sizeof(page), "%d", priv->opts->teletext_page); |
263 | 0 | av_opt_set(avctx, "txt_page", page, AV_OPT_SEARCH_CHILDREN); |
264 | 0 | } |
265 | 0 | } |
266 | | |
267 | 1.41k | ret = avcodec_decode_subtitle2(avctx, &priv->cur, &got_sub, curr_pkt); |
268 | 1.41k | if (ret < 0) { |
269 | 0 | MP_ERR(priv, "Error decoding subtitle\n"); |
270 | 1.41k | } else if (got_sub) { |
271 | 1.41k | *sub_pts = packet->pts + mp_pts_from_av(priv->cur.start_display_time, |
272 | 1.41k | &avctx->time_base); |
273 | 1.41k | *sub_duration = priv->cur.end_display_time == UINT32_MAX ? |
274 | 1.41k | UINT32_MAX : |
275 | 1.41k | mp_pts_from_av(priv->cur.end_display_time - |
276 | 1.41k | priv->cur.start_display_time, |
277 | 1.41k | &avctx->time_base); |
278 | | |
279 | 2.83k | for (int i = 0; i < priv->cur.num_rects; i++) { |
280 | 1.41k | if (priv->cur.rects[i]->w > 0 && priv->cur.rects[i]->h > 0) |
281 | 1.41k | MP_WARN(priv, "Ignoring bitmap subtitle.\n"); |
282 | 1.41k | char *ass_line = priv->cur.rects[i]->ass; |
283 | 1.41k | if (!ass_line) |
284 | 0 | continue; |
285 | 1.41k | MP_TARRAY_APPEND(priv, priv->cur_list, num_cur, ass_line); |
286 | 1.41k | } |
287 | 1.41k | } |
288 | | |
289 | 1.41k | done: |
290 | 1.41k | av_packet_unref(priv->avpkt_vtt); |
291 | 1.41k | MP_TARRAY_APPEND(priv, priv->cur_list, num_cur, NULL); |
292 | 1.41k | return priv->cur_list; |
293 | 1.41k | } |
294 | | |
295 | | bool lavc_conv_is_styled(struct lavc_conv *priv) |
296 | 0 | { |
297 | 0 | return priv->styled; |
298 | 0 | } |
299 | | |
300 | | void lavc_conv_reset(struct lavc_conv *priv) |
301 | 2.05k | { |
302 | 2.05k | avcodec_flush_buffers(priv->avctx); |
303 | 2.05k | } |
304 | | |
305 | | void lavc_conv_uninit(struct lavc_conv *priv) |
306 | 1.02k | { |
307 | 1.02k | avsubtitle_free(&priv->cur); |
308 | 1.02k | avcodec_free_context(&priv->avctx); |
309 | 1.02k | mp_free_av_packet(&priv->avpkt); |
310 | 1.02k | mp_free_av_packet(&priv->avpkt_vtt); |
311 | 1.02k | talloc_free(priv); |
312 | 1.02k | } |