FFmpeg
libaribcaption.c
Go to the documentation of this file.
1 /*
2  * ARIB STD-B24 caption decoder using the libaribcaption library
3  * Copyright (c) 2022 TADANO Tokumei
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 
22 #include "avcodec.h"
23 #include "codec_internal.h"
24 #include "internal.h"
25 #include "libavcodec/ass.h"
26 #include "libavutil/avstring.h"
27 #include "libavutil/avutil.h"
28 #include "libavutil/thread.h"
29 #include "libavutil/log.h"
30 #include "libavutil/opt.h"
31 
32 #include <aribcaption/aribcaption.h>
33 
34 #if !defined(DEFAULT_FONT_ASS)
35 # define DEFAULT_FONT_ASS "sans-serif"
36 #endif
37 
38 #define ARIBC_BPRINT_SIZE_INIT 64
39 #define ARIBC_BPRINT_SIZE_MAX (8 * 1024)
40 #define ARIBC_ALPHA_MAX_NUM 4
41 #define ARIBC_ALPHA_DEFAULT_FRONT 0xFF
42 #define ARIBC_ALPHA_DEFAULT_BACK 0x80
43 
44 #define ARIBCC_COLOR_RGB(c) ((c) & 0xFFFFFF)
45 #define ARIBCC_COLOR_DIFF_RGB(c1,c2) (((c1) ^ (c2)) & 0x00FFFFFF)
46 #define ARIBCC_COLOR_DIFF_A(c1,c2) (((c1) ^ (c2)) & 0xFF000000)
47 
48 #define CLUT_RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
49 #define CLUT_A(c) (((c) >> 24) & 0xFF)
50 #define CLUT_R(c) (((c) >> 16) & 0xFF)
51 #define CLUT_G(c) (((c) >> 8) & 0xFF)
52 #define CLUT_B(c) ( (c) & 0xFF)
53 
54 #define ARIBCC_COLOR_TO_CLUT_RGBA(c,a) (((ARIBCC_COLOR_A(c) ? ARIBCC_COLOR_A(c) : (a)) << 24) | \
55  (ARIBCC_COLOR_R(c) << 16) | \
56  (ARIBCC_COLOR_G(c) << 8) | \
57  (ARIBCC_COLOR_B(c)))
58 
59 typedef struct ARIBCaptionContext {
60  AVClass *class;
62  const AVPacket *avpkt;
64 
65  aribcc_context_t *context;
66  aribcc_decoder_t *decoder;
67  aribcc_renderer_t *renderer;
68 
72  char *font;
76  float stroke_width;
81 
82  int64_t pts;
92  int font_size;
93  int charstyle;
95  int readorder;
96 
97  aribcc_caption_t caption;
98  aribcc_render_result_t render_result;
99  uint32_t *clut;
100  int clut_idx;
104 
105 static void hex_dump_debug(void *ctx, const char *buf, int buf_size)
106 {
107  int i;
108 
109  for (i = 0; i < buf_size; i++) {
110  ff_dlog(ctx, "%02hhx ", buf[i]);
111  if (i % 16 == 15)
112  ff_dlog(ctx, "\n");
113  }
114  if (i % 16)
115  ff_dlog(ctx, "\n");
116 }
117 
118 static void logcat_callback(aribcc_loglevel_t level, const char* message, void* userdata)
119 {
120  ARIBCaptionContext *ctx = userdata;
121  int lvl;
122 
123  if (ctx->decoder != NULL) {
124  switch (level) {
125  case ARIBCC_LOGLEVEL_ERROR:
126  lvl = AV_LOG_ERROR;
127  break;
128  case ARIBCC_LOGLEVEL_WARNING:
129  lvl = AV_LOG_WARNING;
130  break;
131  default:
132  lvl = AV_LOG_INFO;
133  }
134 
135  av_log(ctx, lvl, "%s\n", message);
136  }
137 }
138 
140 {
141  if (ctx->avctx->width > 0 && ctx->avctx->height > 0) {
142  /* input video size specified by -canvas_size option */
143  ctx->bitmap_plane_width = ctx->avctx->width;
144  ctx->bitmap_plane_height = ctx->avctx->height;
145  } else if (ctx->plane_width == 960) {
146  /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] 4.3.1 */
147  /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] Appendix-4 */
148  ctx->bitmap_plane_width = 1440;
149  ctx->bitmap_plane_height = 1080;
150  } else {
151  ctx->bitmap_plane_width = ctx->plane_width;
152  ctx->bitmap_plane_height = ctx->plane_height;
153  }
154  /* Expand either width or height */
155  if (ctx->bitmap_plane_height * ctx->plane_width > ctx->bitmap_plane_width * ctx->plane_height) {
156  ctx->frame_height = ctx->bitmap_plane_height;
157  ctx->frame_width = ctx->frame_height * ctx->plane_width / ctx->plane_height;
158  } else {
159  ctx->frame_width = ctx->bitmap_plane_width;
160  ctx->frame_height = ctx->frame_width * ctx->plane_height / ctx->plane_width;
161  }
162 }
163 
164 static void clut_set_alpha(ARIBCaptionContext *ctx, uint8_t a)
165 {
166  int i;
167 
168  for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) {
169  if (ctx->clut_alpha[i] == 0) {
170  ctx->clut_alpha[i] = a;
171  return;
172  }
173  if (ctx->clut_alpha[i] == a)
174  return;
175  }
176  return;
177 }
178 
180 {
181  int i, j, d;
182 
183  if (a == 0)
184  return a;
185  d = 256;
186  j = 0;
187  for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) {
188  if (ctx->clut_alpha[i] == a)
189  return a;
190  if (ctx->clut_alpha[i] == 0)
191  break;
192  if (abs((int)a - (int)ctx->clut_alpha[i]) < d) {
193  d = abs((int)a - (int)ctx->clut_alpha[i]);
194  j = i;
195  }
196  }
197  return ctx->clut_alpha[j];
198 }
199 
200 static int clut_find(ARIBCaptionContext *ctx, uint32_t rgba)
201 {
202  int i;
203 
204  for (i = 0; i < ctx->clut_idx; i++) {
205  if (ctx->clut[i] == rgba)
206  return i;
207  }
208  return -1;
209 }
210 
211 static inline int clut_color_distance(uint32_t rgba1, uint32_t rgba2)
212 {
213  return abs((int)CLUT_R(rgba1) - (int)CLUT_R(rgba2)) +
214  abs((int)CLUT_G(rgba1) - (int)CLUT_G(rgba2)) +
215  abs((int)CLUT_B(rgba1) - (int)CLUT_B(rgba2));
216 }
217 
218 static uint8_t clut_pick_or_set(ARIBCaptionContext *ctx, int r, int g, int b, int a)
219 {
220  int c, i, d, d_min;
221  uint32_t rgba;
222 
224  if (a == 0)
225  return 0; /* transparent */
226  rgba = CLUT_RGBA(r,g,b,a);
227 
228  d_min = 256 * 3;
229  c = 0;
230  for (i = 0; i < ctx->clut_idx; i++) {
231  if (ctx->clut[i] == rgba)
232  return i;
233  if (CLUT_A(ctx->clut[i]) != a)
234  continue;
235  d = clut_color_distance(ctx->clut[i], rgba);
236  if (d < d_min) {
237  d_min = d;
238  c = i;
239  }
240  }
241  if (d_min > 3) {
242  if (ctx->clut_idx >= AVPALETTE_COUNT)
243  ctx->clut_overflow++;
244  else {
245  c = ctx->clut_idx;
246  ctx->clut[ctx->clut_idx++] = rgba;
247  }
248  }
249  return c;
250 }
251 
252 /* initialiaze CLUT with each character colors */
253 static void clut_init(ARIBCaptionContext *ctx, aribcc_caption_region_t *region)
254 {
255  aribcc_color_t text_color, back_color, stroke_color;
256  uint32_t rgba;
257 
258  ctx->clut[0] = CLUT_RGBA(0,0,0,0); /* transparent */
259  ctx->clut_alpha[0] = 0xFF;
260  ctx->clut_idx = 1;
261  ctx->clut_overflow = 0;
262  text_color = region->chars[0].text_color;
263  back_color = region->chars[0].back_color;
264  stroke_color = region->chars[0].stroke_color;
266  ctx->clut[ctx->clut_idx++] = rgba;
267  clut_set_alpha(ctx, CLUT_A(rgba));
269  ctx->clut[ctx->clut_idx++] = rgba;
270  clut_set_alpha(ctx, CLUT_A(rgba));
272  if (clut_find(ctx, rgba) < 0) {
273  ctx->clut[ctx->clut_idx++] = rgba;
274  clut_set_alpha(ctx, CLUT_A(rgba));
275  }
276 
277  for (int i = 1; i < region->char_count; i++) {
278  if (region->chars[i].text_color != text_color) {
279  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].text_color,
281  if (clut_find(ctx, rgba) < 0) {
282  ctx->clut[ctx->clut_idx++] = rgba;
283  clut_set_alpha(ctx, CLUT_A(rgba));
284  }
285  }
286  if (region->chars[i].back_color != back_color) {
287  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].back_color,
289  if (clut_find(ctx, rgba) < 0) {
290  ctx->clut[ctx->clut_idx++] = rgba;
291  clut_set_alpha(ctx, CLUT_A(rgba));
292  }
293  }
294  if (region->chars[i].stroke_color != stroke_color) {
295  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].stroke_color,
297  if (clut_find(ctx, rgba) < 0) {
298  if (ctx->clut_idx < AVPALETTE_COUNT)
299  ctx->clut[ctx->clut_idx++] = rgba;
300  clut_set_alpha(ctx, CLUT_A(rgba));
301  }
302  }
303  }
304 }
305 
306 /**
307  * aribcaption_trans_{bitmap|ass|text}_subtitle()
308  *
309  * Transfer decoded subtitle to AVSubtitle with corresponding subtitle type.
310  *
311  * @param ctx pointer to the ARIBCaptionContext
312  * @return > 0 number of rectangles to be displayed
313  * = 0 no subtitle
314  * < 0 error code
315  */
317 {
318  int ret = 0;
319  AVSubtitle *sub = ctx->sub;
320  int status, rect_idx;
321  int old_width = ctx->frame_width;
322  int old_height = ctx->frame_height;
323 
324  if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0) {
325  ctx->plane_width = ctx->caption.plane_width;
326  ctx->plane_height = ctx->caption.plane_height;
327  }
329  if (ctx->frame_width != old_width || ctx->frame_height != old_height) {
330  ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n",
331  ctx->avctx->width, ctx->avctx->height,
332  ctx->plane_width, ctx->plane_height,
333  ctx->bitmap_plane_width, ctx->bitmap_plane_height,
334  ctx->frame_width, ctx->frame_height);
335  if (!aribcc_renderer_set_frame_size(ctx->renderer,
336  ctx->frame_width, ctx->frame_height)) {
338  "aribcc_renderer_set_frame_size() returned with error.\n");
339  return AVERROR_EXTERNAL;
340  }
341  }
342 
343  status = aribcc_renderer_append_caption(ctx->renderer, &ctx->caption);
344  if (!status) {
346  "aribcc_renderer_append_caption() returned with error.\n");
347  return AVERROR_EXTERNAL;
348  }
349 
350  status = aribcc_renderer_render(ctx->renderer, ctx->pts, &ctx->render_result);
351  switch (status) {
352  case ARIBCC_RENDER_STATUS_GOT_IMAGE:
353  break;
354 
355  case ARIBCC_RENDER_STATUS_GOT_IMAGE_UNCHANGED:
356  aribcc_render_result_cleanup(&ctx->render_result);
357  ff_dlog(ctx, "got image unchanged\n");
358  return 0;
359 
360  case ARIBCC_RENDER_STATUS_NO_IMAGE:
361  ff_dlog(ctx, "no image\n");
362  return 0;
363 
364  case ARIBCC_RENDER_STATUS_ERROR:
366  "aribcc_renderer_render() returned with error.\n");
367  return AVERROR_EXTERNAL;
368 
369  default:
370  aribcc_render_result_cleanup(&ctx->render_result);
372  "aribcc_renderer_render() returned unknown status: %d\n", status);
373  return AVERROR_EXTERNAL;
374  }
375 
376  if (!ctx->render_result.image_count || ctx->render_result.images == NULL) {
377  aribcc_render_result_cleanup(&ctx->render_result);
378  ff_dlog(ctx, "no image (%d)\n", ctx->render_result.image_count);
379  return 0;
380  }
381 
382  sub->format = 0; /* graphic */
383  sub->rects = av_calloc(ctx->render_result.image_count, sizeof(*sub->rects));
384  if (!sub->rects) {
385  ret = AVERROR(ENOMEM);
386  goto fail;
387  }
388  for (int i = 0; i < ctx->render_result.image_count; i++) {
389  sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
390  if (!sub->rects[i]) {
391  ret = AVERROR(ENOMEM);
392  goto fail;
393  }
394  }
395 
396  for (rect_idx = 0; rect_idx < ctx->caption.region_count; rect_idx++) {
397  AVSubtitleRect *rect = sub->rects[rect_idx];
398  aribcc_image_t *image = &ctx->render_result.images[rect_idx];
399  int w, h, shrink_height, dst_idx;
400 
401  clut_init(ctx, &ctx->caption.regions[rect_idx]);
402 
403  rect->w = image->width * ctx->bitmap_plane_width / ctx->frame_width;
404  rect->h = image->height * ctx->bitmap_plane_height / ctx->frame_height;
405  rect->data[0] = av_mallocz(rect->w * rect->h);
406  if (!rect->data[0]) {
407  ret = AVERROR(ENOMEM);
408  goto fail;
409  }
410  if ((image->height != rect->h && image->width != rect->w) ||
411  image->stride < image->width * 4 ||
412  image->stride * image->height > image->bitmap_size) {
413  av_log(ctx, AV_LOG_ERROR, "Bug: unexpected rendered image: %d(%d)x%d -> %dx%d\n",
414  image->width, image->stride / 4, image->height, rect->w, rect->h);
416  goto fail;
417  }
418 
419  shrink_height = image->height != rect->h;
420  dst_idx = 0;
421  for (h = 0; h < rect->h; h++) {
422  for (w = 0; w < rect->w; w++) {
423  /* Bi-linear interpolation */
424  int n, m, idx0, idx1, r, g, b, a;
425  if (shrink_height) {
426  int div_a, y0, y1;
427  div_a = h * ctx->frame_height;
428  n = ctx->bitmap_plane_height;
429  y0 = div_a / n;
430  y1 = FFMIN(y0 + 1, image->height - 1);
431  m = div_a - n * y0;
432  idx0 = image->stride * y0 + w * 4;
433  idx1 = image->stride * y1 + w * 4;
434  } else {
435  int div_a, x0, x1;
436  div_a = w * ctx->frame_width;
437  n = ctx->bitmap_plane_width;
438  x0 = div_a / n;
439  x1 = FFMIN(x0 + 1, image->width - 1);
440  m = div_a - n * x0;
441  idx0 = image->stride * h + x0 * 4;
442  idx1 = image->stride * h + x1 * 4;
443  }
444  r = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
445  g = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
446  b = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
447  a = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
448  rect->data[0][dst_idx++] = clut_pick_or_set(ctx, r, g, b, a);
449  }
450  }
451  rect->data[1] = av_memdup(ctx->clut, AVPALETTE_SIZE);
452  if (!rect->data[1]) {
453  ret = AVERROR(ENOMEM);
454  goto fail;
455  }
456 
457  if (ctx->avctx->profile == AV_PROFILE_ARIB_PROFILE_C) {
458  /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */
459  /* No position information is provided for profile C */
460  rect->x = (ctx->frame_width - rect->w) / 2;
461  rect->y = ctx->frame_height - rect->h * (ctx->caption.region_count - rect_idx);
462  } else {
463  rect->x = image->dst_x * ctx->bitmap_plane_width / ctx->frame_width;
464  rect->y = image->dst_y * ctx->bitmap_plane_height / ctx->frame_height;
465  }
466  rect->type = SUBTITLE_BITMAP;
467  rect->linesize[0] = rect->w;
468  rect->nb_colors = 256;
469 
470  ff_dlog(ctx, "BITMAP subtitle%s (%d,%d) %dx%d -> (%d,%d) %dx%d [%d]: %d colors\n",
471  (ctx->caption.regions[rect_idx].is_ruby) ? " (ruby)" : "",
472  image->dst_x, image->dst_y, image->width, image->height,
473  rect->x, rect->y, rect->w, rect->h,
474  rect_idx, ctx->clut_idx);
475  if (ctx->clut_overflow)
476  av_log(ctx, AV_LOG_WARNING, "CLUT overflow (%d).\n", ctx->clut_overflow);
477  }
478  sub->num_rects = rect_idx;
479 
480  return rect_idx;
481 
482 fail:
483  if (sub->rects) {
484  for (int i = 0; i < ctx->caption.region_count; i++) {
485  if (sub->rects[i]) {
486  av_freep(&sub->rects[i]->data[0]);
487  av_freep(&sub->rects[i]->data[1]);
488  av_freep(&sub->rects[i]);
489  }
490  }
491  av_freep(&sub->rects);
492  }
493  sub->num_rects = 0;
494 
495  return ret;
496 }
497 
499 {
500  AVCodecContext *avctx = ctx->avctx;
501  int outline, shadow;
502  const char *font_name;
503  const char *fonts = ctx->font;
504 
505  if (ctx->border_style == 4) {
506  outline = 0;
507  shadow = 4;
508  } else {
509  outline = 1;
510  shadow = 0;
511  }
512  if (ctx->force_stroke_text)
513  outline = (int)(ctx->stroke_width * 4.0 / 3.0);
514 
515  if (fonts && *fonts)
516  font_name = av_get_token(&fonts, ",");
517  else
518  font_name = av_strdup(DEFAULT_FONT_ASS);
519  if (!font_name)
520  return AVERROR(ENOMEM);
521 
522  av_freep(&avctx->subtitle_header);
523  avctx->subtitle_header = av_asprintf(
524  "[Script Info]\r\n"
525  "ScriptType: v4.00+\r\n"
526  "PlayResX: %d\r\n"
527  "PlayResY: %d\r\n"
528  "WrapStyle: 2\r\n" /* 2: no word wrapping */
529  "\r\n"
530 
531  "[V4+ Styles]\r\n"
532  "Format: Name, "
533  "Fontname, Fontsize, "
534  "PrimaryColour, SecondaryColour, OutlineColour, BackColour, "
535  "Bold, Italic, Underline, StrikeOut, "
536  "ScaleX, ScaleY, "
537  "Spacing, Angle, "
538  "BorderStyle, Outline, Shadow, "
539  "Alignment, MarginL, MarginR, MarginV, "
540  "Encoding\r\n"
541 
542  "Style: "
543  "Default," /* Name */
544  "%s,%d," /* Font{name,size} */
545  "&H%x,&H%x,&H%x,&H%x," /* {Primary,Secondary,Outline,Back}Colour */
546  "%d,%d,%d,0," /* Bold, Italic, Underline, StrikeOut */
547  "100,100," /* Scale{X,Y} */
548  "0,0," /* Spacing, Angle */
549  "%d,%d,%d," /* BorderStyle, Outline, Shadow */
550  "%d,10,10,10," /* Alignment, Margin[LRV] */
551  "0\r\n" /* Encoding */
552  "\r\n"
553 
554  "[Events]\r\n"
555  "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n",
556  ctx->plane_width, ctx->plane_height,
557  font_name, ctx->font_size,
561  ctx->border_style, outline, shadow, ASS_DEFAULT_ALIGNMENT);
562 
563  av_freep(&font_name);
564  if (!avctx->subtitle_header)
565  return AVERROR(ENOMEM);
566  avctx->subtitle_header_size = strlen(avctx->subtitle_header);
567  return 0;
568 }
569 
570 static void set_ass_color(AVBPrint *buf, int color_num,
571  aribcc_color_t new_color, aribcc_color_t old_color)
572 {
573  if (ARIBCC_COLOR_DIFF_RGB(new_color, old_color))
574  av_bprintf(buf, "{\\%dc&H%06x&}", color_num,
575  ARIBCC_COLOR_RGB(new_color));
576  if (ARIBCC_COLOR_DIFF_A(new_color, old_color))
577  av_bprintf(buf, "{\\%da&H%02x&}", color_num,
578  0xFF - ARIBCC_COLOR_A(new_color));
579 }
580 
582 {
583  AVSubtitle *sub = ctx->sub;
584  AVBPrint buf;
585  bool single_rect = ctx->ass_single_rect;
586  int ret = 0, rect_idx;
587 
588  if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0 &&
589  (ctx->caption.plane_width != ctx->plane_width ||
590  ctx->caption.plane_height != ctx->plane_height)) {
591  ctx->plane_width = ctx->caption.plane_width;
592  ctx->plane_height = ctx->caption.plane_height;
593  if ((ret = set_ass_header(ctx)) < 0)
594  return ret;
595  }
596 
597  /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */
598  /* No position information is provided for profile C */
599  if (ctx->avctx->profile == AV_PROFILE_ARIB_PROFILE_C)
600  single_rect = true;
601 
602  sub->format = 1; /* text */
603  if (ctx->caption.region_count == 0) {
604  /* clear previous caption for indefinite duration */
605  ff_ass_add_rect(sub, "", ctx->readorder++, 0, NULL, NULL);
606  return 1;
607  }
608 
610 
611  if (single_rect && ctx->avctx->profile != AV_PROFILE_ARIB_PROFILE_C) {
612  int x, y, rx, ry;
613  x = ctx->plane_width;
614  y = ctx->plane_height;
615  for (int i = 0; i < ctx->caption.region_count; i++) {
616  rx = ctx->caption.regions[i].x;
617  ry = ctx->caption.regions[i].y;
618  if (rx < x)
619  x = rx;
620  if (ry < y)
621  y = ry;
622  }
623  av_bprintf(&buf, "{\\an7}");
624  if (y < 0)
625  y += ctx->plane_height;
626  if (x > 0 || y > 0)
627  av_bprintf(&buf, "{\\pos(%d,%d)}", x, y);
628  }
629 
630  rect_idx = 0;
631  for (int i = 0; i < ctx->caption.region_count; i++) {
632  aribcc_caption_region_t *region = &ctx->caption.regions[i];
633  aribcc_color_t text_color = ARIBCC_MAKE_RGBA(0xFF, 0xFF, 0xFF,
635  aribcc_color_t stroke_color = ARIBCC_MAKE_RGBA(0, 0, 0,
637  aribcc_color_t back_color = ARIBCC_MAKE_RGBA(0, 0, 0,
639  aribcc_charstyle_t charstyle = ctx->charstyle;
640  int char_width = ctx->font_size;
641  int char_height = ctx->font_size;
642  int char_horizontal_spacing = 0;
643 
644  if (region->is_ruby && ctx->ignore_ruby)
645  continue;
646 
647  if (!single_rect) {
648  int x = region->x;
649  int y = region->y;
650  if (x < 0)
651  x += ctx->plane_width;
652  if (y < 0)
653  y += ctx->plane_height;
654  av_bprint_clear(&buf);
655  av_bprintf(&buf, "{\\an7}");
656  if (x > 0 || y > 0)
657  av_bprintf(&buf, "{\\pos(%d,%d)}", x, y);
658  }
659  if (region->is_ruby)
660  av_bprintf(&buf, "{\\fs%d}", char_height / 2);
661 
662  for (int j = 0; j < region->char_count; j++) {
663  aribcc_caption_char_t *ch = &region->chars[j];
664 
665  if (ctx->avctx->profile != AV_PROFILE_ARIB_PROFILE_C) {
666  if (ch->char_horizontal_spacing != char_horizontal_spacing) {
667  av_bprintf(&buf, "{\\fsp%d}", (region->is_ruby) ?
668  ch->char_horizontal_spacing / 2 :
669  ch->char_horizontal_spacing);
670  char_horizontal_spacing = ch->char_horizontal_spacing;
671  }
672  if (ch->char_width != char_width) {
673  av_bprintf(&buf, "{\\fscx%"PRId64"}",
674  av_rescale(ch->char_width, 100, ctx->font_size));
675  char_width = ch->char_width;
676  }
677  if (ch->char_height != char_height) {
678  av_bprintf(&buf, "{\\fscy%"PRId64"}",
679  av_rescale(ch->char_height, 100, ctx->font_size));
680  char_height = ch->char_height;
681  }
682  }
683  if (ch->style != charstyle) {
684  aribcc_charstyle_t diff = ch->style ^ charstyle;
685  if (diff & ARIBCC_CHARSTYLE_STROKE) {
686  if (charstyle & ARIBCC_CHARSTYLE_STROKE) {
687  if (ctx->force_stroke_text)
688  av_bprintf(&buf, "{\\bord%d}",
689  (int)(ctx->stroke_width * 4.0 / 3.0));
690  else
691  av_bprintf(&buf, "{\\bord0}");
692  } else
693  av_bprintf(&buf, "{\\bord3}");
694  }
695  if (diff & ARIBCC_CHARSTYLE_BOLD) {
696  if (charstyle & ARIBCC_CHARSTYLE_BOLD)
697  av_bprintf(&buf, "{\\b0}");
698  else
699  av_bprintf(&buf, "{\\b1}");
700  }
701  if (diff & ARIBCC_CHARSTYLE_ITALIC) {
702  if (charstyle & ARIBCC_CHARSTYLE_ITALIC)
703  av_bprintf(&buf, "{\\i0}");
704  else
705  av_bprintf(&buf, "{\\i1}");
706  }
707  if (diff & ARIBCC_CHARSTYLE_UNDERLINE) {
708  if (charstyle & ARIBCC_CHARSTYLE_UNDERLINE)
709  av_bprintf(&buf, "{\\u0}");
710  else
711  av_bprintf(&buf, "{\\u1}");
712  }
713  charstyle = ch->style;
714  }
715  if (ch->text_color != text_color) {
716  set_ass_color(&buf, 1, ch->text_color, text_color);
717  text_color = ch->text_color;
718  }
719  if (ch->stroke_color != stroke_color) {
720  set_ass_color(&buf, 3, ch->stroke_color, stroke_color);
721  stroke_color = ch->stroke_color;
722  }
723  if (ch->back_color != back_color) {
724  if (ctx->border_style == 4)
725  set_ass_color(&buf, 4, ch->back_color, back_color);
726  else
727  set_ass_color(&buf, 3, ch->back_color, back_color);
728  back_color = ch->back_color;
729  }
730  if (region->chars[j].type == ARIBCC_CHARTYPE_DRCS)
731  av_bprintf(&buf, "\xe3\x80\x93"); /* Geta Mark */
732  else
733  ff_ass_bprint_text_event(&buf, ch->u8str, strlen(ch->u8str), "", 0);
734  }
735 
736  if (single_rect) {
737  if (i + 1 < ctx->caption.region_count)
738  av_bprintf(&buf, "{\\r}\\N");
739  ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]\n",
740  (region->is_ruby) ? " (ruby)" : "",
741  region->x, region->y, region->width, region->height,
742  rect_idx);
743  } else {
744  if (!av_bprint_is_complete(&buf)) {
745  ret = AVERROR(ENOMEM);
746  goto fail;
747  }
748  ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]: %s\n",
749  (region->is_ruby) ? " (ruby)" : "",
750  region->x, region->y, region->width, region->height,
751  rect_idx, buf.str);
752 
753  ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL);
754  if (ret != 0)
755  goto fail;
756  rect_idx++;
757  }
758  }
759  if (single_rect) {
760  if (!av_bprint_is_complete(&buf)) {
761  ret = AVERROR(ENOMEM);
762  goto fail;
763  }
764  ff_dlog(ctx, "ASS subtitle: %s\n", buf.str);
765 
766  ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL);
767  if (ret != 0)
768  goto fail;
769  rect_idx++;
770  }
771 
772  av_bprint_finalize(&buf, NULL);
773  return rect_idx;
774 
775 fail:
776  if (sub->rects) {
777  for (int i = 0; i < ctx->caption.region_count; i++) {
778  if (sub->rects[i]) {
779  av_freep(&sub->rects[i]->ass);
780  av_freep(&sub->rects[i]);
781  }
782  }
783  av_freep(&sub->rects);
784  }
785  sub->num_rects = 0;
786  av_bprint_finalize(&buf, NULL);
787 
788  return ret;
789 }
790 
792 {
793  AVSubtitle *sub = ctx->sub;
795  int ret = 0;
796  const char *text;
797 
798  sub->rects = av_calloc(ctx->caption.region_count, sizeof(*sub->rects));
799  if (!sub->rects) {
800  ret = AVERROR(ENOMEM);
801  goto fail;
802  }
803  sub->num_rects = 1;
804 
805  sub->rects[0] = av_mallocz(sizeof(*sub->rects[0]));
806  if (!sub->rects[0]) {
807  ret = AVERROR(ENOMEM);
808  goto fail;
809  }
810  rect = sub->rects[0];
811 
812  if (ctx->caption.region_count == 0)
813  text = ""; /* clear previous caption */
814  else {
815  text = ctx->caption.text;
816  ff_dlog(ctx, "TEXT subtitle: %s\n", text);
817  }
818  rect->text = av_strdup(text);
819  if (!rect->text) {
820  ret = AVERROR(ENOMEM);
821  goto fail;
822  }
823 
824  sub->format = 1; /* text */
825  rect->type = SUBTITLE_TEXT;
826 
827  return 1;
828 
829 fail:
830  if (sub->rects) {
831  rect = sub->rects[0];
832  if (rect) {
833  av_freep(&rect->text);
834  av_freep(&rect);
835  }
836  av_freep(&sub->rects);
837  }
838  sub->num_rects = 0;
839 
840  return ret;
841 }
842 
844  int *got_sub_ptr, const AVPacket *avpkt)
845 {
846  ARIBCaptionContext *ctx = avctx->priv_data;
847  int status;
848 
849  ff_dlog(ctx, "ARIB caption packet pts=%"PRIx64":\n", avpkt->pts);
850  if (sub->num_rects) {
851  avpriv_request_sample(ctx, "Different Version of Segment asked Twice");
852  return AVERROR_PATCHWELCOME;
853  }
854  hex_dump_debug(ctx, avpkt->data, avpkt->size);
855 
856  ctx->sub = sub;
857  ctx->avpkt = avpkt;
858  ctx->time_base = avctx->pkt_timebase;
859  if (ctx->time_base.num <= 0 || ctx->time_base.den <= 0) {
860  av_log(ctx, AV_LOG_VERBOSE, "No timebase set. assuming 90kHz.\n");
861  ctx->time_base = av_make_q(1, 90000);
862  }
863  if (avpkt->pts == AV_NOPTS_VALUE)
864  ctx->pts = ARIBCC_PTS_NOPTS;
865  else
866  ctx->pts = av_rescale_q(avpkt->pts, ctx->time_base, (AVRational){1, 1000});
867 
868  status = aribcc_decoder_decode(ctx->decoder, avpkt->data, avpkt->size,
869  ctx->pts, &ctx->caption);
870  if (status == ARIBCC_DECODE_STATUS_ERROR) {
872  "aribcc_decoder_decode() returned with error.\n");
873  return AVERROR(EAGAIN);
874  }
875  if (status == ARIBCC_DECODE_STATUS_NO_CAPTION) {
876  ff_dlog(ctx, "No caption.\n");
877  return avpkt->size;
878  } else {
879  ff_dlog(ctx, "type=%02x, flags=%x, lang=%03x\n",
880  ctx->caption.type, ctx->caption.flags, ctx->caption.iso6392_language_code);
881  ff_dlog(ctx, "region count = %d, start=%d.%d, duration=%d.%d\n",
882  ctx->caption.region_count,
883  (int)(ctx->caption.pts / 1000), (int)(ctx->caption.pts % 1000),
884  (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ?
885  -1 : ctx->caption.wait_duration / 1000),
886  (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ?
887  0 : ctx->caption.wait_duration % 1000));
888  }
889 
890  switch ((enum AVSubtitleType) ctx->subtitle_type) {
891  case SUBTITLE_TEXT:
893  break;
894 
895  case SUBTITLE_ASS:
897  break;
898 
899  case SUBTITLE_BITMAP:
901  break;
902 
903  case SUBTITLE_NONE:
904  default:
905  status = 0;
906  }
907 
908  if (status < 0) {
909  av_log(ctx, AV_LOG_ERROR, "Failed to set Subtitle: %s\n",
910  av_err2str(status));
911  aribcc_caption_cleanup(&ctx->caption);
912  return status;
913  }
914  if (status > 0) {
915  *got_sub_ptr = 1;
916  if (ctx->avpkt->pts != AV_NOPTS_VALUE)
917  sub->pts = av_rescale_q(ctx->avpkt->pts,
918  ctx->time_base, AV_TIME_BASE_Q);
919  if (ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE)
920  sub->end_display_time = UINT32_MAX;
921  else
922  sub->end_display_time = (uint32_t)ctx->caption.wait_duration;
923  }
924 
925  aribcc_caption_cleanup(&ctx->caption);
926  return avpkt->size;
927 }
928 
930 {
931  ARIBCaptionContext *ctx = avctx->priv_data;
932 
933  if (ctx->decoder)
934  aribcc_decoder_flush(ctx->decoder);
935  if (ctx->renderer)
936  aribcc_renderer_flush(ctx->renderer);
937  if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
938  ctx->readorder = 0;
939 }
940 
942 {
943  ARIBCaptionContext *ctx = avctx->priv_data;
944 
945  av_freep(&ctx->clut);
946  if (ctx->renderer)
947  aribcc_renderer_free(ctx->renderer);
948  if (ctx->decoder)
949  aribcc_decoder_free(ctx->decoder);
950  if (ctx->context)
951  aribcc_context_free(ctx->context);
952 
953  return 0;
954 }
955 
957 {
958  ARIBCaptionContext *ctx = avctx->priv_data;
959  aribcc_profile_t profile;
960  int ret = 0;
961 
962  ctx->avctx = avctx;
963 
964  switch (avctx->profile) {
966  profile = ARIBCC_PROFILE_A;
967  /* assume 960x540 at initial state */
968  ctx->plane_width = 960;
969  ctx->plane_height = 540;
970  ctx->font_size = 36;
971  break;
973  profile = ARIBCC_PROFILE_C;
974  ctx->plane_width = 320;
975  ctx->plane_height = 180;
976  ctx->font_size = 16;
977  break;
978  default:
979  av_log(avctx, AV_LOG_ERROR, "Unknown or unsupported profile set.\n");
980  return AVERROR(EINVAL);
981  }
982  /* determine BorderStyle of ASS header */
983  if (ctx->ignore_background)
984  ctx->border_style = 1;
985  else
986  ctx->border_style = 4;
987  ctx->charstyle = ARIBCC_CHARSTYLE_DEFAULT;
988  if (ctx->force_stroke_text || ctx->ignore_background)
989  ctx->charstyle |= ARIBCC_CHARSTYLE_STROKE;
990 
991  if (!(ctx->context = aribcc_context_alloc())) {
992  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption context.\n");
993  return AVERROR_EXTERNAL;
994  }
995  aribcc_context_set_logcat_callback(ctx->context, logcat_callback, avctx);
996  if (!(ctx->decoder = aribcc_decoder_alloc(ctx->context))) {
997  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption decoder.\n");
998  return AVERROR_EXTERNAL;
999  }
1000  if (!aribcc_decoder_initialize(ctx->decoder,
1001  (enum aribcc_encoding_scheme_t) ctx->encoding_scheme,
1002  ARIBCC_CAPTIONTYPE_CAPTION,
1003  profile,
1004  ARIBCC_LANGUAGEID_FIRST)) {
1005  av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption decoder.\n");
1006  return AVERROR_EXTERNAL;
1007  }
1008  aribcc_decoder_set_replace_msz_fullwidth_ascii(ctx->decoder,
1009  ctx->replace_msz_ascii);
1010  aribcc_decoder_set_replace_msz_fullwidth_japanese(ctx->decoder,
1011  ctx->replace_msz_japanese);
1012 
1013  /* Similar behavior as ffmpeg tool to set canvas size */
1014  if (ctx->canvas_width > 0 && ctx->canvas_height > 0 &&
1015  (ctx->avctx->width == 0 || ctx->avctx->height == 0)) {
1016  ctx->avctx->width = ctx->canvas_width;
1017  ctx->avctx->height = ctx->canvas_height;
1018  }
1019 
1020  switch ((enum AVSubtitleType) ctx->subtitle_type) {
1021  case SUBTITLE_ASS:
1022  ret = set_ass_header(ctx);
1023  if (ret != 0) {
1024  av_log(avctx, AV_LOG_ERROR, "Failed to set ASS header: %s\n",
1025  av_err2str(ret));
1026  return ret;
1027  }
1028  break;
1029 
1030  case SUBTITLE_BITMAP:
1031  if(!(ctx->renderer = aribcc_renderer_alloc(ctx->context))) {
1032  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption renderer.\n");
1033  return AVERROR_EXTERNAL;
1034  }
1035  if(!aribcc_renderer_initialize(ctx->renderer,
1036  ARIBCC_CAPTIONTYPE_CAPTION,
1037  ARIBCC_FONTPROVIDER_TYPE_AUTO,
1038  ARIBCC_TEXTRENDERER_TYPE_AUTO)) {
1039  av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption renderer.\n");
1040  return AVERROR_EXTERNAL;
1041  }
1043  ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n",
1044  ctx->avctx->width, ctx->avctx->height,
1045  ctx->plane_width, ctx->plane_height,
1046  ctx->bitmap_plane_width, ctx->bitmap_plane_height,
1047  ctx->frame_width, ctx->frame_height);
1048  if (!aribcc_renderer_set_frame_size(ctx->renderer,
1049  ctx->frame_width, ctx->frame_height)) {
1051  "aribcc_renderer_set_frame_size() returned with error.\n");
1052  return AVERROR_EXTERNAL;
1053  }
1054 
1055  if (!(ctx->clut = av_mallocz(AVPALETTE_SIZE)))
1056  return AVERROR(ENOMEM);
1057 
1058  aribcc_renderer_set_storage_policy(ctx->renderer, ARIBCC_CAPTION_STORAGE_POLICY_MINIMUM, 0);
1059  aribcc_renderer_set_replace_drcs(ctx->renderer, ctx->replace_drcs);
1060  aribcc_renderer_set_force_stroke_text(ctx->renderer, ctx->force_stroke_text);
1061  aribcc_renderer_set_force_no_background(ctx->renderer, ctx->ignore_background);
1062  aribcc_renderer_set_force_no_ruby(ctx->renderer, ctx->ignore_ruby);
1063  aribcc_renderer_set_stroke_width(ctx->renderer, ctx->stroke_width);
1064  aribcc_renderer_set_replace_msz_halfwidth_glyph(ctx->renderer,
1065  ctx->replace_msz_glyph);
1066  if (ctx->font) {
1067  int is_nomem = 0;
1068  size_t count = 0;
1069  const char **font_families = NULL;
1070  const char *fonts = ctx->font;
1071 
1072  while (*fonts) {
1073  const char **ff = av_realloc_array(font_families, count + 1, sizeof(*font_families));
1074  if (!ff) {
1075  is_nomem = 1;
1076  break;
1077  } else {
1078  font_families = ff;
1079  ff[count++] = av_get_token(&fonts, ",");
1080  if (!ff[count - 1]) {
1081  is_nomem = 1;
1082  break;
1083  } else if (*fonts)
1084  fonts++;
1085  }
1086  }
1087  if (!is_nomem && count)
1088  aribcc_renderer_set_default_font_family(ctx->renderer, font_families, count, true);
1089  while (count)
1090  av_freep(&font_families[--count]);
1091  av_freep(&font_families);
1092  if (is_nomem)
1093  return AVERROR(ENOMEM);
1094  }
1095  break;
1096 
1097  case SUBTITLE_TEXT:
1098  case SUBTITLE_NONE:
1099  default:
1100  /* do nothing */ ;
1101  }
1102 
1103  ctx->readorder = 0;
1104 
1105  return 0;
1106 }
1107 
1108 #if !defined(ASS_SINGLE_RECT)
1109 # define ASS_SINGLE_RECT 0
1110 #endif
1111 
1112 #define OFFSET(x) offsetof(ARIBCaptionContext, x)
1113 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
1114 static const AVOption options[] = {
1115  { "sub_type", "subtitle rendering type",
1116  OFFSET(subtitle_type), AV_OPT_TYPE_INT,
1117  { .i64 = SUBTITLE_ASS }, SUBTITLE_NONE, SUBTITLE_ASS, SD, "type" },
1118  { "none", "do nothing", 0, AV_OPT_TYPE_CONST,
1119  { .i64 = SUBTITLE_NONE }, .flags = SD, .unit = "type" },
1120  { "bitmap", "bitmap rendering", 0, AV_OPT_TYPE_CONST,
1121  { .i64 = SUBTITLE_BITMAP }, .flags = SD, .unit = "type" },
1122  { "text", "plain text", 0, AV_OPT_TYPE_CONST,
1123  { .i64 = SUBTITLE_TEXT }, .flags = SD, .unit = "type" },
1124  { "ass", "formatted text", 0, AV_OPT_TYPE_CONST,
1125  { .i64 = SUBTITLE_ASS }, .flags = SD, .unit = "type" },
1126  { "caption_encoding", "encoding scheme of subtitle text",
1127  OFFSET(encoding_scheme), AV_OPT_TYPE_INT, { .i64 = ARIBCC_ENCODING_SCHEME_AUTO },
1128  ARIBCC_ENCODING_SCHEME_AUTO, ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN, SD, "encoding" },
1129  { "auto", "automatically detect encoding scheme", 0, AV_OPT_TYPE_CONST,
1130  { .i64 = ARIBCC_ENCODING_SCHEME_AUTO }, .flags = SD, .unit = "encoding" },
1131  { "jis", "8bit-char JIS encoding (Japanese ISDB captions)", 0, AV_OPT_TYPE_CONST,
1132  { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_JIS }, .flags = SD, .unit = "encoding" },
1133  { "utf8", "UTF-8 encoding (Philippines ISDB-T captions)", 0, AV_OPT_TYPE_CONST,
1134  { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_UTF8 }, .flags = SD, .unit = "encoding" },
1135  { "latin", "latin characters (SBTVD / ISDB-Tb captions used in South America)", 0, AV_OPT_TYPE_CONST,
1136  { .i64 = ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN }, .flags = SD, .unit = "encoding" },
1137  { "ass_single_rect", "workaround of ASS subtitle for players which can't handle multi-rectangle [ass]",
1138  OFFSET(ass_single_rect), AV_OPT_TYPE_BOOL, { .i64 = ASS_SINGLE_RECT }, 0, 1, SD },
1139  { "font", "comma-separated font family [ass, bitmap]",
1140  OFFSET(font), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
1141  { "force_outline_text", "always render characters with outline [(ass), bitmap]",
1142  OFFSET(force_stroke_text), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1143  { "ignore_background", "ignore rendering caption background [(ass), bitmap]",
1144  OFFSET(ignore_background), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1145  { "ignore_ruby", "ignore ruby-like characters [ass, bitmap]",
1146  OFFSET(ignore_ruby), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1147  { "outline_width", "outline width of text [(ass), bitmap]",
1148  OFFSET(stroke_width), AV_OPT_TYPE_FLOAT, { .dbl = 1.5 }, 0.0, 3.0, SD },
1149  { "replace_drcs", "replace known DRCS [bitmap]",
1150  OFFSET(replace_drcs), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1151  { "replace_msz_ascii", "replace MSZ fullwidth alphanumerics with halfwidth alphanumerics [ass, bitmap]",
1152  OFFSET(replace_msz_ascii), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1153  { "replace_msz_japanese", "replace MSZ fullwidth Japanese with halfwidth [ass, bitmap]",
1154  OFFSET(replace_msz_japanese), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1155  { "replace_msz_glyph", "replace MSZ characters with halfwidth glyphs [bitmap]",
1156  OFFSET(replace_msz_glyph), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1157  {"canvas_size", "set input video size (WxH or abbreviation) [bitmap]",
1158  OFFSET(canvas_width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, INT_MAX, SD },
1159  { NULL }
1160 };
1161 
1162 static const AVClass aribcaption_class = {
1163  .class_name = "aribcaption decoder",
1164  .item_name = av_default_item_name,
1165  .option = options,
1166  .version = LIBAVUTIL_VERSION_INT,
1167 };
1168 
1170  .p.name = "libaribcaption",
1171  .p.long_name = NULL_IF_CONFIG_SMALL("ARIB STD-B24 caption decoder"),
1172  .p.type = AVMEDIA_TYPE_SUBTITLE,
1173  .p.id = AV_CODEC_ID_ARIB_CAPTION,
1174  .priv_data_size = sizeof(ARIBCaptionContext),
1176  .close = aribcaption_close,
1178  .flush = aribcaption_flush,
1179  .p.priv_class = &aribcaption_class,
1180  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1181 };
AVSubtitle
Definition: avcodec.h:2269
rect::w
int w
Definition: f_ebur128.c:78
aribcaption_class
static const AVClass aribcaption_class
Definition: libaribcaption.c:1162
ARIBCaptionContext::replace_msz_ascii
int replace_msz_ascii
Definition: libaribcaption.c:78
CLUT_RGBA
#define CLUT_RGBA(r, g, b, a)
Definition: libaribcaption.c:48
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
ARIBC_BPRINT_SIZE_INIT
#define ARIBC_BPRINT_SIZE_INIT
Definition: libaribcaption.c:38
level
uint8_t level
Definition: svq3.c:204
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:218
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
AVSubtitle::rects
AVSubtitleRect ** rects
Definition: avcodec.h:2274
opt.h
ARIBCaptionContext::clut_alpha
uint8_t clut_alpha[ARIBC_ALPHA_MAX_NUM]
Definition: libaribcaption.c:102
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
ARIBCC_COLOR_TO_CLUT_RGBA
#define ARIBCC_COLOR_TO_CLUT_RGBA(c, a)
Definition: libaribcaption.c:54
message
Definition: api-threadmessage-test.c:46
thread.h
ASS_SINGLE_RECT
#define ASS_SINGLE_RECT
Definition: libaribcaption.c:1109
ARIBCaptionContext::replace_drcs
int replace_drcs
Definition: libaribcaption.c:77
rect
Definition: f_ebur128.c:78
ARIBCaptionContext::time_base
AVRational time_base
Definition: libaribcaption.c:83
ARIBCC_COLOR_RGB
#define ARIBCC_COLOR_RGB(c)
Definition: libaribcaption.c:44
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
ARIBCaptionContext::encoding_scheme
int encoding_scheme
Definition: libaribcaption.c:70
AVSubtitleRect
Definition: avcodec.h:2241
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:2273
rect::y
int y
Definition: f_ebur128.c:78
estimate_video_frame_size
static void estimate_video_frame_size(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:139
w
uint8_t w
Definition: llviddspenc.c:38
ASS_DEFAULT_ALIGNMENT
#define ASS_DEFAULT_ALIGNMENT
Definition: ass.h:42
ff_ass_add_rect
int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker)
Add an ASS dialog to a subtitle.
Definition: ass.c:159
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:491
AVOption
AVOption.
Definition: opt.h:251
clut_set_alpha
static void clut_set_alpha(ARIBCaptionContext *ctx, uint8_t a)
Definition: libaribcaption.c:164
ARIBC_BPRINT_SIZE_MAX
#define ARIBC_BPRINT_SIZE_MAX
Definition: libaribcaption.c:39
b
#define b
Definition: input.c:41
clut_pick_or_set
static uint8_t clut_pick_or_set(ARIBCaptionContext *ctx, int r, int g, int b, int a)
Definition: libaribcaption.c:218
logcat_callback
static void logcat_callback(aribcc_loglevel_t level, const char *message, void *userdata)
Definition: libaribcaption.c:118
FFCodec
Definition: codec_internal.h:127
AVCodecContext::subtitle_header
uint8_t * subtitle_header
Header containing style information for text subtitles.
Definition: avcodec.h:1776
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ARIBCaptionContext::border_style
int border_style
Definition: libaribcaption.c:94
clut_init
static void clut_init(ARIBCaptionContext *ctx, aribcc_caption_region_t *region)
Definition: libaribcaption.c:253
AV_PROFILE_ARIB_PROFILE_C
#define AV_PROFILE_ARIB_PROFILE_C
Definition: defs.h:187
ARIBCaptionContext::clut_idx
int clut_idx
Definition: libaribcaption.c:100
aribcaption_init
static int aribcaption_init(AVCodecContext *avctx)
Definition: libaribcaption.c:956
ARIBCaptionContext::sub
AVSubtitle * sub
Definition: libaribcaption.c:63
SUBTITLE_ASS
@ SUBTITLE_ASS
Formatted text, the ass field must be set by the decoder and is authoritative.
Definition: avcodec.h:2236
av_memdup
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:302
ARIBCaptionContext::frame_height
int frame_height
Definition: libaribcaption.c:89
AV_PROFILE_ARIB_PROFILE_A
#define AV_PROFILE_ARIB_PROFILE_A
Definition: defs.h:186
ARIBCaptionContext::avctx
AVCodecContext * avctx
Definition: libaribcaption.c:61
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
OFFSET
#define OFFSET(x)
Definition: libaribcaption.c:1112
ARIBC_ALPHA_MAX_NUM
#define ARIBC_ALPHA_MAX_NUM
Definition: libaribcaption.c:40
clut_find
static int clut_find(ARIBCaptionContext *ctx, uint32_t rgba)
Definition: libaribcaption.c:200
fail
#define fail()
Definition: checkasm.h:138
aribcaption_trans_text_subtitle
static int aribcaption_trans_text_subtitle(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:791
AVSubtitleRect::ass
char * ass
0 terminated ASS/SSA compatible event line.
Definition: avcodec.h:2264
options
static const AVOption options[]
Definition: libaribcaption.c:1114
ARIBCaptionContext::render_result
aribcc_render_result_t render_result
Definition: libaribcaption.c:98
ass.h
ARIBCaptionContext::canvas_height
int canvas_height
Definition: libaribcaption.c:85
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ARIBCaptionContext::replace_msz_japanese
int replace_msz_japanese
Definition: libaribcaption.c:79
ARIBCaptionContext::readorder
int readorder
Definition: libaribcaption.c:95
set_ass_header
static int set_ass_header(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:498
ARIBCaptionContext::pts
int64_t pts
Definition: libaribcaption.c:82
ARIBCaptionContext::renderer
aribcc_renderer_t * renderer
Definition: libaribcaption.c:67
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:215
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1233
ARIBCaptionContext::plane_width
int plane_width
Definition: libaribcaption.c:86
g
const char * g
Definition: vf_curves.c:127
aribcaption_trans_bitmap_subtitle
static int aribcaption_trans_bitmap_subtitle(ARIBCaptionContext *ctx)
aribcaption_trans_{bitmap|ass|text}_subtitle()
Definition: libaribcaption.c:316
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
ARIBCaptionContext::clut_overflow
int clut_overflow
Definition: libaribcaption.c:101
AVSubtitleType
AVSubtitleType
Definition: avcodec.h:2221
ff_ass_bprint_text_event
void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, const char *linebreaks, int keep_ass_markup)
Escape a text subtitle using ASS syntax into an AVBPrint buffer.
Definition: ass.c:173
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVSubtitle::pts
int64_t pts
Same as packet pts, in AV_TIME_BASE.
Definition: avcodec.h:2275
AV_CODEC_ID_ARIB_CAPTION
@ AV_CODEC_ID_ARIB_CAPTION
Definition: codec_id.h:575
ASS_DEFAULT_BACK_COLOR
#define ASS_DEFAULT_BACK_COLOR
Definition: ass.h:38
aribcaption_flush
static void aribcaption_flush(AVCodecContext *avctx)
Definition: libaribcaption.c:929
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ARIBCaptionContext::plane_height
int plane_height
Definition: libaribcaption.c:87
NULL
#define NULL
Definition: coverity.c:32
ARIBCaptionContext::ass_single_rect
int ass_single_rect
Definition: libaribcaption.c:71
ARIBCaptionContext::replace_msz_glyph
int replace_msz_glyph
Definition: libaribcaption.c:80
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ARIBCaptionContext::ignore_ruby
int ignore_ruby
Definition: libaribcaption.c:75
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:235
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AVCodecContext::subtitle_header_size
int subtitle_header_size
Definition: avcodec.h:1777
ARIBCaptionContext::caption
aribcc_caption_t caption
Definition: libaribcaption.c:97
AVSubtitleRect::data
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:2252
abs
#define abs(x)
Definition: cuda_runtime.h:35
DEFAULT_FONT_ASS
#define DEFAULT_FONT_ASS
Definition: libaribcaption.c:35
ARIBCaptionContext::canvas_width
int canvas_width
Definition: libaribcaption.c:84
CLUT_A
#define CLUT_A(c)
Definition: libaribcaption.c:49
CLUT_R
#define CLUT_R(c)
Definition: libaribcaption.c:50
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVPALETTE_COUNT
#define AVPALETTE_COUNT
Definition: pixfmt.h:33
ARIBCaptionContext::frame_width
int frame_width
Definition: libaribcaption.c:88
ARIBCaptionContext::force_stroke_text
int force_stroke_text
Definition: libaribcaption.c:73
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
ARIBCaptionContext::ignore_background
int ignore_background
Definition: libaribcaption.c:74
AVCodecContext::flags2
int flags2
AV_CODEC_FLAG2_*.
Definition: avcodec.h:528
ASS_DEFAULT_BOLD
#define ASS_DEFAULT_BOLD
Definition: ass.h:39
AVPacket::size
int size
Definition: packet.h:492
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:106
aribcaption_decode
static int aribcaption_decode(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt)
Definition: libaribcaption.c:843
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
codec_internal.h
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
ARIBCaptionContext::decoder
aribcc_decoder_t * decoder
Definition: libaribcaption.c:66
ARIBCaptionContext::context
aribcc_context_t * context
Definition: libaribcaption.c:65
AVCodecContext::pkt_timebase
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition: avcodec.h:1817
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
ARIBCaptionContext::font_size
int font_size
Definition: libaribcaption.c:92
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
rect::h
int h
Definition: f_ebur128.c:78
AVSubtitle::end_display_time
uint32_t end_display_time
Definition: avcodec.h:2272
SUBTITLE_TEXT
@ SUBTITLE_TEXT
Plain text, the text field must be set by the decoder and is authoritative.
Definition: avcodec.h:2230
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:164
SUBTITLE_NONE
@ SUBTITLE_NONE
Definition: avcodec.h:2222
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
rect::x
int x
Definition: f_ebur128.c:78
SUBTITLE_BITMAP
@ SUBTITLE_BITMAP
A bitmap, pict will be set.
Definition: avcodec.h:2224
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
ASS_DEFAULT_UNDERLINE
#define ASS_DEFAULT_UNDERLINE
Definition: ass.h:41
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
ARIBCaptionContext::font
char * font
Definition: libaribcaption.c:72
ARIBCaptionContext::clut
uint32_t * clut
Definition: libaribcaption.c:99
ARIBCaptionContext::bitmap_plane_height
int bitmap_plane_height
Definition: libaribcaption.c:91
AVSubtitle::format
uint16_t format
Definition: avcodec.h:2270
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:484
CLUT_B
#define CLUT_B(c)
Definition: libaribcaption.c:52
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ARIBCaptionContext::avpkt
const AVPacket * avpkt
Definition: libaribcaption.c:62
ARIBCC_COLOR_DIFF_A
#define ARIBCC_COLOR_DIFF_A(c1, c2)
Definition: libaribcaption.c:46
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
aribcaption_close
static int aribcaption_close(AVCodecContext *avctx)
Definition: libaribcaption.c:941
ASS_DEFAULT_ITALIC
#define ASS_DEFAULT_ITALIC
Definition: ass.h:40
ASS_DEFAULT_COLOR
#define ASS_DEFAULT_COLOR
Definition: ass.h:37
profile
int profile
Definition: mxfenc.c:2115
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
ARIBCaptionContext::charstyle
int charstyle
Definition: libaribcaption.c:93
avcodec.h
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
CLUT_G
#define CLUT_G(c)
Definition: libaribcaption.c:51
AVCodecContext
main external API structure.
Definition: avcodec.h:441
ARIBCaptionContext::bitmap_plane_width
int bitmap_plane_width
Definition: libaribcaption.c:90
status
ov_status_e status
Definition: dnn_backend_openvino.c:119
SD
#define SD
Definition: libaribcaption.c:1113
clut_color_distance
static int clut_color_distance(uint32_t rgba1, uint32_t rgba2)
Definition: libaribcaption.c:211
set_ass_color
static void set_ass_color(AVBPrint *buf, int color_num, aribcc_color_t new_color, aribcc_color_t old_color)
Definition: libaribcaption.c:570
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1596
av_get_token
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:143
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:232
ARIBC_ALPHA_DEFAULT_FRONT
#define ARIBC_ALPHA_DEFAULT_FRONT
Definition: libaribcaption.c:41
FF_CODEC_DECODE_SUB_CB
#define FF_CODEC_DECODE_SUB_CB(func)
Definition: codec_internal.h:309
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
avutil.h
ARIBCaptionContext::subtitle_type
int subtitle_type
Definition: libaribcaption.c:69
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:468
AVPacket
This structure stores compressed data.
Definition: packet.h:468
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
d
d
Definition: ffmpeg_filter.c:368
ff_libaribcaption_decoder
const FFCodec ff_libaribcaption_decoder
Definition: libaribcaption.c:1169
ARIBCC_COLOR_DIFF_RGB
#define ARIBCC_COLOR_DIFF_RGB(c1, c2)
Definition: libaribcaption.c:45
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
aribcaption_trans_ass_subtitle
static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:581
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
ARIBCaptionContext
Definition: libaribcaption.c:59
AV_CODEC_FLAG2_RO_FLUSH_NOOP
#define AV_CODEC_FLAG2_RO_FLUSH_NOOP
Do not reset ASS ReadOrder field on flush (subtitles decoding)
Definition: avcodec.h:388
int
int
Definition: ffmpeg_filter.c:368
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
hex_dump_debug
static void hex_dump_debug(void *ctx, const char *buf, int buf_size)
Definition: libaribcaption.c:105
ARIBCaptionContext::stroke_width
float stroke_width
Definition: libaribcaption.c:76
clut_find_nearlest_alpha
static uint8_t clut_find_nearlest_alpha(ARIBCaptionContext *ctx, uint8_t a)
Definition: libaribcaption.c:179
ARIBC_ALPHA_DEFAULT_BACK
#define ARIBC_ALPHA_DEFAULT_BACK
Definition: libaribcaption.c:42