1 /*
2 * ARIB STD-B24 caption decoder using the libaribb24 library
3 * Copyright (c) 2019 Jan Ekström
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 */
21
27
28 #include <aribb24/aribb24.h>
29 #include <aribb24/parser.h>
30 #include <aribb24/decoder.h>
31
34
38
40
43
46
48 {
51
54
57 return 36;
59 return 18;
60 default:
61 return 0;
62 }
63 }
64
66 {
68 }
69
71 {
73 unsigned int plane_width = 0;
74 unsigned int plane_height = 0;
75 unsigned int font_size = 0;
77
80
83 plane_width = 960;
84 plane_height = 540;
85 break;
87 plane_width = 320;
88 plane_height = 180;
89 break;
90 default:
93 }
94
96
98 "[Script Info]\r\n"
99 "; Script generated by FFmpeg/Lavc%s\r\n"
100 "ScriptType: v4.00+\r\n"
101 "PlayResX: %d\r\n"
102 "PlayResY: %d\r\n"
103 "\r\n"
104 "[V4+ Styles]\r\n"
105
106 /* ASSv4 header */
107 "Format: Name, "
108 "Fontname, Fontsize, "
109 "PrimaryColour, SecondaryColour, OutlineColour, BackColour, "
110 "Bold, Italic, Underline, StrikeOut, "
111 "ScaleX, ScaleY, "
112 "Spacing, Angle, "
113 "BorderStyle, Outline, Shadow, "
114 "Alignment, MarginL, MarginR, MarginV, "
115 "Encoding\r\n"
116
117 "Style: "
118 "Default," /* Name */
119 "%s,%d," /* Font{name,size} */
120 "&H%x,&H%x,&H%x,&H%x," /* {Primary,Secondary,Outline,Back}Colour */
121 "%d,%d,%d,0," /* Bold, Italic, Underline, StrikeOut */
122 "100,100," /* Scale{X,Y} */
123 "0,0," /* Spacing, Angle */
124 "%d,1,0," /* BorderStyle, Outline, Shadow */
125 "%d,10,10,10," /* Alignment, Margin[LRV] */
126 "0\r\n" /* Encoding */
127
128 "\r\n"
129 "[Events]\r\n"
130 "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n",
132 plane_width, plane_height,
137
140
142
143 return 0;
144 }
145
147 {
149 void(* arib_dec_init)(arib_decoder_t*
decoder) =
NULL;
152
155 goto init_fail;
156 }
157
162 }
163
165
168 goto init_fail;
169 }
172 goto init_fail;
173 }
174
177
180 arib_dec_init = arib_initialize_decoder_a_profile;
181 break;
183 arib_dec_init = arib_initialize_decoder_c_profile;
184 break;
185 default:
188 goto init_fail;
189 }
190
192
195 goto init_fail;
196 }
197
198 return 0;
199
200 init_fail:
202 arib_finalize_decoder(b24->
decoder);
203
206
207 return ret_code;
208 }
209
211 {
213
215 arib_finalize_decoder(b24->
decoder);
216
219
220 return 0;
221 }
222
223 #define RGB_TO_BGR(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff))
224
226 {
228 const arib_buf_region_t *region = arib_decoder_get_regions(b24->
decoder);
230 AVBPrint buf = { 0 };
232
234
235 while (region) {
236 ptrdiff_t region_length = region->p_end - region->p_start;
237 unsigned int ruby_region =
238 region->i_fontheight == (profile_font_size / 2);
239
240 // ASS requires us to make the colors BGR, so we convert here
241 int foreground_bgr_color =
RGB_TO_BGR(region->i_foreground_color);
242 int background_bgr_color =
RGB_TO_BGR(region->i_background_color);
243
244 if (region_length < 0) {
247 break;
248 }
249
251 goto next_region;
252 }
253
254 // color and alpha
256 av_bprintf(&buf,
"{\1円c&H%06x&}", foreground_bgr_color);
257
258 if (region->i_foreground_alpha != 0)
259 av_bprintf(&buf,
"{\1円a&H%02x&}", region->i_foreground_alpha);
260
262 av_bprintf(&buf,
"{\3円c&H%06x&}", background_bgr_color);
263
264 if (region->i_background_alpha != 0)
265 av_bprintf(&buf,
"{\3円a&H%02x&}", region->i_background_alpha);
266
267 // font size
268 if (region->i_fontwidth != profile_font_size ||
269 region->i_fontheight != profile_font_size) {
270 av_bprintf(&buf,
"{\\fscx%"PRId64
"\\fscy%"PRId64
"}",
272 profile_font_size),
274 profile_font_size));
275 }
276
277 // TODO: positioning
278
280
282
283 next_region:
284 region = region->p_next;
285 }
286
289
292 buf.str);
293
296 }
297
299
301 }
302
305 {
307 size_t parsed_data_size = 0;
308 size_t decoded_subtitle_size = 0;
309 const unsigned char *parsed_data =
NULL;
310 char *decoded_subtitle =
NULL;
311 time_t subtitle_duration = 0;
313
316
318
319 parsed_data = arib_parser_get_data(b24->
parser,
320 &parsed_data_size);
321 if (!parsed_data || !parsed_data_size) {
323 "packet (dts: %"PRId64", pts: %"PRId64").\n",
326 }
327
328 decoded_subtitle_size = parsed_data_size * 4;
329 if (!(decoded_subtitle =
av_mallocz(decoded_subtitle_size + 1))) {
331 "Failed to allocate buffer for decoded subtitle!\n");
333 }
334
335 decoded_subtitle_size = arib_decode_buffer(b24->
decoder,
336 parsed_data,
337 parsed_data_size,
338 decoded_subtitle,
339 decoded_subtitle_size);
340
341 subtitle_duration = arib_decoder_get_time(b24->
decoder);
342
346
347 sub->end_display_time = subtitle_duration ?
351 UINT32_MAX;
352
354 "Result: '%s' (size: %zu, pkt_pts: %"PRId64", sub_pts: %"PRId64" "
355 "duration: %"PRIu32", pkt_timebase: %d/%d, time_base: %d/%d')\n",
356 decoded_subtitle ? decoded_subtitle : "<no subtitle>",
357 decoded_subtitle_size,
359 sub->end_display_time,
362
363 if (decoded_subtitle)
365
366 *got_sub_ptr =
sub->num_rects > 0;
367
369
370 // flush the region buffers, otherwise the linked list keeps getting
371 // longer and longer...
372 arib_finalize_decoder(b24->
decoder);
373
375 }
376
378 {
382 }
383
384 #define OFFSET(x) offsetof(Libaribb24Context, x)
385 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
387 { "aribb24-base-path", "set the base path for the libaribb24 library",
389 { "aribb24-skip-ruby-text", "skip ruby text blocks during decoding",
391 { "default_profile", "default profile to use if not specified in the stream parameters",
396 };
397
403 };
404
406 .
p.
name =
"libaribb24",
411 .p.wrapper_name = "libaribb24",
418 };