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;
77  float stroke_width;
79 
80  int64_t pts;
90  int font_size;
91  int charstyle;
93  int readorder;
94 
95  aribcc_caption_t caption;
96  aribcc_render_result_t render_result;
97  uint32_t *clut;
98  int clut_idx;
102 
103 static void hex_dump_debug(void *ctx, const char *buf, int buf_size)
104 {
105  int i;
106 
107  for (i = 0; i < buf_size; i++) {
108  ff_dlog(ctx, "%02hhx ", buf[i]);
109  if (i % 16 == 15)
110  ff_dlog(ctx, "\n");
111  }
112  if (i % 16)
113  ff_dlog(ctx, "\n");
114 }
115 
116 static void logcat_callback(aribcc_loglevel_t level, const char* message, void* userdata)
117 {
118  ARIBCaptionContext *ctx = userdata;
119  int lvl;
120 
121  if (ctx->decoder != NULL) {
122  switch (level) {
123  case ARIBCC_LOGLEVEL_ERROR:
124  lvl = AV_LOG_ERROR;
125  break;
126  case ARIBCC_LOGLEVEL_WARNING:
127  lvl = AV_LOG_WARNING;
128  break;
129  default:
130  lvl = AV_LOG_INFO;
131  }
132 
133  av_log(ctx, lvl, "%s\n", message);
134  }
135 }
136 
138 {
139  if (ctx->avctx->width > 0 && ctx->avctx->height > 0) {
140  /* input video size specified by -canvas_size option */
141  ctx->bitmap_plane_width = ctx->avctx->width;
142  ctx->bitmap_plane_height = ctx->avctx->height;
143  } else if (ctx->plane_width == 960) {
144  /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] 4.3.1 */
145  /* ARIB TR-B14 Fascicle 2 Volume 3 [Section 2] Appendix-4 */
146  ctx->bitmap_plane_width = 1440;
147  ctx->bitmap_plane_height = 1080;
148  } else {
149  ctx->bitmap_plane_width = ctx->plane_width;
150  ctx->bitmap_plane_height = ctx->plane_height;
151  }
152  /* Expand either width or height */
153  if (ctx->bitmap_plane_height * ctx->plane_width > ctx->bitmap_plane_width * ctx->plane_height) {
154  ctx->frame_height = ctx->bitmap_plane_height;
155  ctx->frame_width = ctx->frame_height * ctx->plane_width / ctx->plane_height;
156  } else {
157  ctx->frame_width = ctx->bitmap_plane_width;
158  ctx->frame_height = ctx->frame_width * ctx->plane_height / ctx->plane_width;
159  }
160 }
161 
162 static void clut_set_alpha(ARIBCaptionContext *ctx, uint8_t a)
163 {
164  int i;
165 
166  for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) {
167  if (ctx->clut_alpha[i] == 0) {
168  ctx->clut_alpha[i] = a;
169  return;
170  }
171  if (ctx->clut_alpha[i] == a)
172  return;
173  }
174  return;
175 }
176 
178 {
179  int i, j, d;
180 
181  if (a == 0)
182  return a;
183  d = 256;
184  j = 0;
185  for (i = 0; i < ARIBC_ALPHA_MAX_NUM; i++) {
186  if (ctx->clut_alpha[i] == a)
187  return a;
188  if (ctx->clut_alpha[i] == 0)
189  break;
190  if (abs((int)a - (int)ctx->clut_alpha[i]) < d) {
191  d = abs((int)a - (int)ctx->clut_alpha[i]);
192  j = i;
193  }
194  }
195  return ctx->clut_alpha[j];
196 }
197 
198 static int clut_find(ARIBCaptionContext *ctx, uint32_t rgba)
199 {
200  int i;
201 
202  for (i = 0; i < ctx->clut_idx; i++) {
203  if (ctx->clut[i] == rgba)
204  return i;
205  }
206  return -1;
207 }
208 
209 static inline int clut_color_distance(uint32_t rgba1, uint32_t rgba2)
210 {
211  return abs((int)CLUT_R(rgba1) - (int)CLUT_R(rgba2)) +
212  abs((int)CLUT_G(rgba1) - (int)CLUT_G(rgba2)) +
213  abs((int)CLUT_B(rgba1) - (int)CLUT_B(rgba2));
214 }
215 
216 static uint8_t clut_pick_or_set(ARIBCaptionContext *ctx, int r, int g, int b, int a)
217 {
218  int c, i, d, d_min;
219  uint32_t rgba;
220 
222  if (a == 0)
223  return 0; /* transparent */
224  rgba = CLUT_RGBA(r,g,b,a);
225 
226  d_min = 256 * 3;
227  c = 0;
228  for (i = 0; i < ctx->clut_idx; i++) {
229  if (ctx->clut[i] == rgba)
230  return i;
231  if (CLUT_A(ctx->clut[i]) != a)
232  continue;
233  d = clut_color_distance(ctx->clut[i], rgba);
234  if (d < d_min) {
235  d_min = d;
236  c = i;
237  }
238  }
239  if (d_min > 3) {
240  if (ctx->clut_idx >= AVPALETTE_COUNT)
241  ctx->clut_overflow++;
242  else {
243  c = ctx->clut_idx;
244  ctx->clut[ctx->clut_idx++] = rgba;
245  }
246  }
247  return c;
248 }
249 
250 /* initialiaze CLUT with each character colors */
251 static void clut_init(ARIBCaptionContext *ctx, aribcc_caption_region_t *region)
252 {
253  aribcc_color_t text_color, back_color, stroke_color;
254  uint32_t rgba;
255 
256  ctx->clut[0] = CLUT_RGBA(0,0,0,0); /* transparent */
257  ctx->clut_alpha[0] = 0xFF;
258  ctx->clut_idx = 1;
259  ctx->clut_overflow = 0;
260  text_color = region->chars[0].text_color;
261  back_color = region->chars[0].back_color;
262  stroke_color = region->chars[0].stroke_color;
264  ctx->clut[ctx->clut_idx++] = rgba;
265  clut_set_alpha(ctx, CLUT_A(rgba));
267  ctx->clut[ctx->clut_idx++] = rgba;
268  clut_set_alpha(ctx, CLUT_A(rgba));
270  if (clut_find(ctx, rgba) < 0) {
271  ctx->clut[ctx->clut_idx++] = rgba;
272  clut_set_alpha(ctx, CLUT_A(rgba));
273  }
274 
275  for (int i = 1; i < region->char_count; i++) {
276  if (region->chars[i].text_color != text_color) {
277  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].text_color,
279  if (clut_find(ctx, rgba) < 0) {
280  ctx->clut[ctx->clut_idx++] = rgba;
281  clut_set_alpha(ctx, CLUT_A(rgba));
282  }
283  }
284  if (region->chars[i].back_color != back_color) {
285  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].back_color,
287  if (clut_find(ctx, rgba) < 0) {
288  ctx->clut[ctx->clut_idx++] = rgba;
289  clut_set_alpha(ctx, CLUT_A(rgba));
290  }
291  }
292  if (region->chars[i].stroke_color != stroke_color) {
293  rgba = ARIBCC_COLOR_TO_CLUT_RGBA(region->chars[i].stroke_color,
295  if (clut_find(ctx, rgba) < 0) {
296  if (ctx->clut_idx < AVPALETTE_COUNT)
297  ctx->clut[ctx->clut_idx++] = rgba;
298  clut_set_alpha(ctx, CLUT_A(rgba));
299  }
300  }
301  }
302 }
303 
304 /**
305  * aribcaption_trans_{bitmap|ass|text}_subtitle()
306  *
307  * Transfer decoded subtitle to AVSubtitle with corresponding subtitle type.
308  *
309  * @param ctx pointer to the ARIBCaptionContext
310  * @return > 0 number of rectangles to be displayed
311  * = 0 no subtitle
312  * < 0 error code
313  */
315 {
316  int ret = 0;
317  AVSubtitle *sub = ctx->sub;
318  int status, rect_idx;
319  int old_width = ctx->frame_width;
320  int old_height = ctx->frame_height;
321 
322  if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0) {
323  ctx->plane_width = ctx->caption.plane_width;
324  ctx->plane_height = ctx->caption.plane_height;
325  }
327  if (ctx->frame_width != old_width || ctx->frame_height != old_height) {
328  ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n",
329  ctx->avctx->width, ctx->avctx->height,
330  ctx->plane_width, ctx->plane_height,
331  ctx->bitmap_plane_width, ctx->bitmap_plane_height,
332  ctx->frame_width, ctx->frame_height);
333  if (!aribcc_renderer_set_frame_size(ctx->renderer,
334  ctx->frame_width, ctx->frame_height)) {
336  "aribcc_renderer_set_frame_size() returned with error.\n");
337  return AVERROR_EXTERNAL;
338  }
339  }
340 
341  status = aribcc_renderer_append_caption(ctx->renderer, &ctx->caption);
342  if (!status) {
344  "aribcc_renderer_append_caption() returned with error.\n");
345  return AVERROR_EXTERNAL;
346  }
347 
348  status = aribcc_renderer_render(ctx->renderer, ctx->pts, &ctx->render_result);
349  switch (status) {
350  case ARIBCC_RENDER_STATUS_GOT_IMAGE:
351  break;
352 
353  case ARIBCC_RENDER_STATUS_GOT_IMAGE_UNCHANGED:
354  aribcc_render_result_cleanup(&ctx->render_result);
355  ff_dlog(ctx, "got image unchanged\n");
356  return 0;
357 
358  case ARIBCC_RENDER_STATUS_NO_IMAGE:
359  ff_dlog(ctx, "no image\n");
360  return 0;
361 
362  case ARIBCC_RENDER_STATUS_ERROR:
364  "aribcc_renderer_render() returned with error.\n");
365  return AVERROR_EXTERNAL;
366 
367  default:
368  aribcc_render_result_cleanup(&ctx->render_result);
370  "aribcc_renderer_render() returned unknown status: %d\n", status);
371  return AVERROR_EXTERNAL;
372  }
373 
374  if (!ctx->render_result.image_count || ctx->render_result.images == NULL) {
375  aribcc_render_result_cleanup(&ctx->render_result);
376  ff_dlog(ctx, "no image (%d)\n", ctx->render_result.image_count);
377  return 0;
378  }
379 
380  sub->format = 0; /* graphic */
381  sub->rects = av_calloc(ctx->render_result.image_count, sizeof(*sub->rects));
382  if (!sub->rects) {
383  ret = AVERROR(ENOMEM);
384  goto fail;
385  }
386  for (int i = 0; i < ctx->render_result.image_count; i++) {
387  sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
388  if (!sub->rects[i]) {
389  ret = AVERROR(ENOMEM);
390  goto fail;
391  }
392  }
393 
394  for (rect_idx = 0; rect_idx < ctx->caption.region_count; rect_idx++) {
395  AVSubtitleRect *rect = sub->rects[rect_idx];
396  aribcc_image_t *image = &ctx->render_result.images[rect_idx];
397  int w, h, shrink_height, dst_idx;
398 
399  clut_init(ctx, &ctx->caption.regions[rect_idx]);
400 
401  rect->w = image->width * ctx->bitmap_plane_width / ctx->frame_width;
402  rect->h = image->height * ctx->bitmap_plane_height / ctx->frame_height;
403  rect->data[0] = av_mallocz(rect->w * rect->h);
404  if (!rect->data[0]) {
405  ret = AVERROR(ENOMEM);
406  goto fail;
407  }
408  if ((image->height != rect->h && image->width != rect->w) ||
409  image->stride < image->width * 4 ||
410  image->stride * image->height > image->bitmap_size) {
411  av_log(ctx, AV_LOG_ERROR, "Bug: unexpected rendered image: %d(%d)x%d -> %dx%d\n",
412  image->width, image->stride / 4, image->height, rect->w, rect->h);
414  goto fail;
415  }
416 
417  shrink_height = image->height != rect->h;
418  dst_idx = 0;
419  for (h = 0; h < rect->h; h++) {
420  for (w = 0; w < rect->w; w++) {
421  /* Bi-linear interpolation */
422  int n, m, idx0, idx1, r, g, b, a;
423  if (shrink_height) {
424  int div_a, y0, y1;
425  div_a = h * ctx->frame_height;
426  n = ctx->bitmap_plane_height;
427  y0 = div_a / n;
428  y1 = FFMIN(y0 + 1, image->height - 1);
429  m = div_a - n * y0;
430  idx0 = image->stride * y0 + w * 4;
431  idx1 = image->stride * y1 + w * 4;
432  } else {
433  int div_a, x0, x1;
434  div_a = w * ctx->frame_width;
435  n = ctx->bitmap_plane_width;
436  x0 = div_a / n;
437  x1 = FFMIN(x0 + 1, image->width - 1);
438  m = div_a - n * x0;
439  idx0 = image->stride * h + x0 * 4;
440  idx1 = image->stride * h + x1 * 4;
441  }
442  r = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
443  g = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
444  b = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
445  a = (image->bitmap[idx0++] * (n - m) + image->bitmap[idx1++] * m) / n;
446  rect->data[0][dst_idx++] = clut_pick_or_set(ctx, r, g, b, a);
447  }
448  }
449  rect->data[1] = av_memdup(ctx->clut, AVPALETTE_SIZE);
450  if (!rect->data[1]) {
451  ret = AVERROR(ENOMEM);
452  goto fail;
453  }
454 
455  if (ctx->avctx->profile == FF_PROFILE_ARIB_PROFILE_C) {
456  /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */
457  /* No position information is provided for profile C */
458  rect->x = (ctx->frame_width - rect->w) / 2;
459  rect->y = ctx->frame_height - rect->h * (ctx->caption.region_count - rect_idx);
460  } else {
461  rect->x = image->dst_x * ctx->bitmap_plane_width / ctx->frame_width;
462  rect->y = image->dst_y * ctx->bitmap_plane_height / ctx->frame_height;
463  }
464  rect->type = SUBTITLE_BITMAP;
465  rect->linesize[0] = rect->w;
466  rect->nb_colors = 256;
467 
468  ff_dlog(ctx, "BITMAP subtitle%s (%d,%d) %dx%d -> (%d,%d) %dx%d [%d]: %d colors\n",
469  (ctx->caption.regions[rect_idx].is_ruby) ? " (ruby)" : "",
470  image->dst_x, image->dst_y, image->width, image->height,
471  rect->x, rect->y, rect->w, rect->h,
472  rect_idx, ctx->clut_idx);
473  if (ctx->clut_overflow)
474  av_log(ctx, AV_LOG_WARNING, "CLUT overflow (%d).\n", ctx->clut_overflow);
475  }
476  sub->num_rects = rect_idx;
477 
478  return rect_idx;
479 
480 fail:
481  if (sub->rects) {
482  for (int i = 0; i < ctx->caption.region_count; i++) {
483  if (sub->rects[i]) {
484  av_freep(&sub->rects[i]->data[0]);
485  av_freep(&sub->rects[i]->data[1]);
486  av_freep(&sub->rects[i]);
487  }
488  }
489  av_freep(&sub->rects);
490  }
491  sub->num_rects = 0;
492 
493  return ret;
494 }
495 
497 {
498  AVCodecContext *avctx = ctx->avctx;
499  int outline, shadow;
500  const char *font_name;
501  const char *fonts = ctx->font;
502 
503  if (ctx->border_style == 4) {
504  outline = 0;
505  shadow = 4;
506  } else {
507  outline = 1;
508  shadow = 0;
509  }
510  if (ctx->force_stroke_text)
511  outline = (int)(ctx->stroke_width * 4.0 / 3.0);
512 
513  if (fonts && *fonts)
514  font_name = av_get_token(&fonts, ",");
515  else
516  font_name = av_strdup(DEFAULT_FONT_ASS);
517  if (!font_name)
518  return AVERROR(ENOMEM);
519 
520  av_freep(&avctx->subtitle_header);
521  avctx->subtitle_header = av_asprintf(
522  "[Script Info]\r\n"
523  "ScriptType: v4.00+\r\n"
524  "PlayResX: %d\r\n"
525  "PlayResY: %d\r\n"
526  "WrapStyle: 2\r\n" /* 2: no word wrapping */
527  "\r\n"
528 
529  "[V4+ Styles]\r\n"
530  "Format: Name, "
531  "Fontname, Fontsize, "
532  "PrimaryColour, SecondaryColour, OutlineColour, BackColour, "
533  "Bold, Italic, Underline, StrikeOut, "
534  "ScaleX, ScaleY, "
535  "Spacing, Angle, "
536  "BorderStyle, Outline, Shadow, "
537  "Alignment, MarginL, MarginR, MarginV, "
538  "Encoding\r\n"
539 
540  "Style: "
541  "Default," /* Name */
542  "%s,%d," /* Font{name,size} */
543  "&H%x,&H%x,&H%x,&H%x," /* {Primary,Secondary,Outline,Back}Colour */
544  "%d,%d,%d,0," /* Bold, Italic, Underline, StrikeOut */
545  "100,100," /* Scale{X,Y} */
546  "0,0," /* Spacing, Angle */
547  "%d,%d,%d," /* BorderStyle, Outline, Shadow */
548  "%d,10,10,10," /* Alignment, Margin[LRV] */
549  "0\r\n" /* Encoding */
550  "\r\n"
551 
552  "[Events]\r\n"
553  "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n",
554  ctx->plane_width, ctx->plane_height,
555  font_name, ctx->font_size,
559  ctx->border_style, outline, shadow, ASS_DEFAULT_ALIGNMENT);
560 
561  av_freep(&font_name);
562  if (!avctx->subtitle_header)
563  return AVERROR(ENOMEM);
564  avctx->subtitle_header_size = strlen(avctx->subtitle_header);
565  return 0;
566 }
567 
568 static void set_ass_color(AVBPrint *buf, int color_num,
569  aribcc_color_t new_color, aribcc_color_t old_color)
570 {
571  if (ARIBCC_COLOR_DIFF_RGB(new_color, old_color))
572  av_bprintf(buf, "{\\%dc&H%06x&}", color_num,
573  ARIBCC_COLOR_RGB(new_color));
574  if (ARIBCC_COLOR_DIFF_A(new_color, old_color))
575  av_bprintf(buf, "{\\%da&H%02x&}", color_num,
576  0xFF - ARIBCC_COLOR_A(new_color));
577 }
578 
580 {
581  AVSubtitle *sub = ctx->sub;
582  AVBPrint buf;
583  bool single_rect = ctx->ass_single_rect;
584  int ret = 0, rect_idx;
585 
586  if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0 &&
587  (ctx->caption.plane_width != ctx->plane_width ||
588  ctx->caption.plane_height != ctx->plane_height)) {
589  ctx->plane_width = ctx->caption.plane_width;
590  ctx->plane_height = ctx->caption.plane_height;
591  if ((ret = set_ass_header(ctx)) < 0)
592  return ret;
593  }
594 
595  /* ARIB TR-B14 version 3.8 Fascicle 1-(2/2) Volume 3 [Section 4] */
596  /* No position information is provided for profile C */
597  if (ctx->avctx->profile == FF_PROFILE_ARIB_PROFILE_C)
598  single_rect = true;
599 
600  sub->format = 1; /* text */
601  if (ctx->caption.region_count == 0) {
602  /* clear previous caption for indefinite duration */
603  ff_ass_add_rect(sub, "", ctx->readorder++, 0, NULL, NULL);
604  return 1;
605  }
606 
608 
609  if (single_rect && ctx->avctx->profile != FF_PROFILE_ARIB_PROFILE_C) {
610  int x, y, rx, ry;
611  x = ctx->plane_width;
612  y = ctx->plane_height;
613  for (int i = 0; i < ctx->caption.region_count; i++) {
614  rx = ctx->caption.regions[i].x;
615  ry = ctx->caption.regions[i].y;
616  if (rx < x)
617  x = rx;
618  if (ry < y)
619  y = ry;
620  }
621  av_bprintf(&buf, "{\\an7}");
622  if (y < 0)
623  y += ctx->plane_height;
624  if (x > 0 || y > 0)
625  av_bprintf(&buf, "{\\pos(%d,%d)}", x, y);
626  }
627 
628  rect_idx = 0;
629  for (int i = 0; i < ctx->caption.region_count; i++) {
630  aribcc_caption_region_t *region = &ctx->caption.regions[i];
631  aribcc_color_t text_color = ARIBCC_MAKE_RGBA(0xFF, 0xFF, 0xFF,
633  aribcc_color_t stroke_color = ARIBCC_MAKE_RGBA(0, 0, 0,
635  aribcc_color_t back_color = ARIBCC_MAKE_RGBA(0, 0, 0,
637  aribcc_charstyle_t charstyle = ctx->charstyle;
638  int char_width = ctx->font_size;
639  int char_height = ctx->font_size;
640  int char_horizontal_spacing = 0;
641 
642  if (region->is_ruby && ctx->ignore_ruby)
643  continue;
644 
645  if (!single_rect) {
646  int x = region->x;
647  int y = region->y;
648  if (x < 0)
649  x += ctx->plane_width;
650  if (y < 0)
651  y += ctx->plane_height;
652  av_bprint_clear(&buf);
653  av_bprintf(&buf, "{\\an7}");
654  if (x > 0 || y > 0)
655  av_bprintf(&buf, "{\\pos(%d,%d)}", x, y);
656  }
657  if (region->is_ruby)
658  av_bprintf(&buf, "{\\fs%d}", char_height / 2);
659 
660  for (int j = 0; j < region->char_count; j++) {
661  aribcc_caption_char_t *ch = &region->chars[j];
662 
663  if (ctx->avctx->profile != FF_PROFILE_ARIB_PROFILE_C) {
664  if (ch->char_horizontal_spacing != char_horizontal_spacing) {
665  av_bprintf(&buf, "{\\fsp%d}", (region->is_ruby) ?
666  ch->char_horizontal_spacing / 2 :
667  ch->char_horizontal_spacing);
668  char_horizontal_spacing = ch->char_horizontal_spacing;
669  }
670  if (ch->char_width != char_width) {
671  av_bprintf(&buf, "{\\fscx%"PRId64"}",
672  av_rescale(ch->char_width, 100, ctx->font_size));
673  char_width = ch->char_width;
674  }
675  if (ch->char_height != char_height) {
676  av_bprintf(&buf, "{\\fscy%"PRId64"}",
677  av_rescale(ch->char_height, 100, ctx->font_size));
678  char_height = ch->char_height;
679  }
680  }
681  if (ch->style != charstyle) {
682  aribcc_charstyle_t diff = ch->style ^ charstyle;
683  if (diff & ARIBCC_CHARSTYLE_STROKE) {
684  if (charstyle & ARIBCC_CHARSTYLE_STROKE) {
685  if (ctx->force_stroke_text)
686  av_bprintf(&buf, "{\\bord%d}",
687  (int)(ctx->stroke_width * 4.0 / 3.0));
688  else
689  av_bprintf(&buf, "{\\bord0}");
690  } else
691  av_bprintf(&buf, "{\\bord3}");
692  }
693  if (diff & ARIBCC_CHARSTYLE_BOLD) {
694  if (charstyle & ARIBCC_CHARSTYLE_BOLD)
695  av_bprintf(&buf, "{\\b0}");
696  else
697  av_bprintf(&buf, "{\\b1}");
698  }
699  if (diff & ARIBCC_CHARSTYLE_ITALIC) {
700  if (charstyle & ARIBCC_CHARSTYLE_ITALIC)
701  av_bprintf(&buf, "{\\i0}");
702  else
703  av_bprintf(&buf, "{\\i1}");
704  }
705  if (diff & ARIBCC_CHARSTYLE_UNDERLINE) {
706  if (charstyle & ARIBCC_CHARSTYLE_UNDERLINE)
707  av_bprintf(&buf, "{\\u0}");
708  else
709  av_bprintf(&buf, "{\\u1}");
710  }
711  charstyle = ch->style;
712  }
713  if (ch->text_color != text_color) {
714  set_ass_color(&buf, 1, ch->text_color, text_color);
715  text_color = ch->text_color;
716  }
717  if (ch->stroke_color != stroke_color) {
718  set_ass_color(&buf, 3, ch->stroke_color, stroke_color);
719  stroke_color = ch->stroke_color;
720  }
721  if (ch->back_color != back_color) {
722  if (ctx->border_style == 4)
723  set_ass_color(&buf, 4, ch->back_color, back_color);
724  else
725  set_ass_color(&buf, 3, ch->back_color, back_color);
726  back_color = ch->back_color;
727  }
728  if (region->chars[j].type == ARIBCC_CHARTYPE_DRCS)
729  av_bprintf(&buf, "\xe3\x80\x93"); /* Geta Mark */
730  else
731  ff_ass_bprint_text_event(&buf, ch->u8str, strlen(ch->u8str), "", 0);
732  }
733 
734  if (single_rect) {
735  if (i + 1 < ctx->caption.region_count)
736  av_bprintf(&buf, "{\\r}\\N");
737  ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]\n",
738  (region->is_ruby) ? " (ruby)" : "",
739  region->x, region->y, region->width, region->height,
740  rect_idx);
741  } else {
742  if (!av_bprint_is_complete(&buf)) {
743  ret = AVERROR(ENOMEM);
744  goto fail;
745  }
746  ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]: %s\n",
747  (region->is_ruby) ? " (ruby)" : "",
748  region->x, region->y, region->width, region->height,
749  rect_idx, buf.str);
750 
751  ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL);
752  if (ret != 0)
753  goto fail;
754  rect_idx++;
755  }
756  }
757  if (single_rect) {
758  if (!av_bprint_is_complete(&buf)) {
759  ret = AVERROR(ENOMEM);
760  goto fail;
761  }
762  ff_dlog(ctx, "ASS subtitle: %s\n", buf.str);
763 
764  ret = ff_ass_add_rect(sub, buf.str, ctx->readorder++, 0 , NULL, NULL);
765  if (ret != 0)
766  goto fail;
767  rect_idx++;
768  }
769 
770  av_bprint_finalize(&buf, NULL);
771  return rect_idx;
772 
773 fail:
774  if (sub->rects) {
775  for (int i = 0; i < ctx->caption.region_count; i++) {
776  if (sub->rects[i]) {
777  av_freep(&sub->rects[i]->ass);
778  av_freep(&sub->rects[i]);
779  }
780  }
781  av_freep(&sub->rects);
782  }
783  sub->num_rects = 0;
784  av_bprint_finalize(&buf, NULL);
785 
786  return ret;
787 }
788 
790 {
791  AVSubtitle *sub = ctx->sub;
793  int ret = 0;
794  const char *text;
795 
796  sub->rects = av_calloc(ctx->caption.region_count, sizeof(*sub->rects));
797  if (!sub->rects) {
798  ret = AVERROR(ENOMEM);
799  goto fail;
800  }
801  sub->num_rects = 1;
802 
803  sub->rects[0] = av_mallocz(sizeof(*sub->rects[0]));
804  if (!sub->rects[0]) {
805  ret = AVERROR(ENOMEM);
806  goto fail;
807  }
808  rect = sub->rects[0];
809 
810  if (ctx->caption.region_count == 0)
811  text = ""; /* clear previous caption */
812  else {
813  text = ctx->caption.text;
814  ff_dlog(ctx, "TEXT subtitle: %s\n", text);
815  }
816  rect->text = av_strdup(text);
817  if (!rect->text) {
818  ret = AVERROR(ENOMEM);
819  goto fail;
820  }
821 
822  sub->format = 1; /* text */
823  rect->type = SUBTITLE_TEXT;
824 
825  return 1;
826 
827 fail:
828  if (sub->rects) {
829  rect = sub->rects[0];
830  if (rect) {
831  av_freep(&rect->text);
832  av_freep(&rect);
833  }
834  av_freep(&sub->rects);
835  }
836  sub->num_rects = 0;
837 
838  return ret;
839 }
840 
842  int *got_sub_ptr, const AVPacket *avpkt)
843 {
844  ARIBCaptionContext *ctx = avctx->priv_data;
845  int status;
846 
847  ff_dlog(ctx, "ARIB caption packet pts=%"PRIx64":\n", avpkt->pts);
848  if (sub->num_rects) {
849  avpriv_request_sample(ctx, "Different Version of Segment asked Twice");
850  return AVERROR_PATCHWELCOME;
851  }
852  hex_dump_debug(ctx, avpkt->data, avpkt->size);
853 
854  ctx->sub = sub;
855  ctx->avpkt = avpkt;
856  ctx->time_base = avctx->pkt_timebase;
857  if (ctx->time_base.num <= 0 || ctx->time_base.den <= 0) {
858  av_log(ctx, AV_LOG_VERBOSE, "No timebase set. assuming 90kHz.\n");
859  ctx->time_base = av_make_q(1, 90000);
860  }
861  if (avpkt->pts == AV_NOPTS_VALUE)
862  ctx->pts = ARIBCC_PTS_NOPTS;
863  else
864  ctx->pts = av_rescale_q(avpkt->pts, ctx->time_base, (AVRational){1, 1000});
865 
866  status = aribcc_decoder_decode(ctx->decoder, avpkt->data, avpkt->size,
867  ctx->pts, &ctx->caption);
868  if (status == ARIBCC_DECODE_STATUS_ERROR) {
870  "aribcc_decoder_decode() returned with error.\n");
871  return AVERROR(EAGAIN);
872  }
873  if (status == ARIBCC_DECODE_STATUS_NO_CAPTION) {
874  ff_dlog(ctx, "No caption.\n");
875  return avpkt->size;
876  } else {
877  ff_dlog(ctx, "type=%02x, flags=%x, lang=%03x\n",
878  ctx->caption.type, ctx->caption.flags, ctx->caption.iso6392_language_code);
879  ff_dlog(ctx, "region count = %d, start=%d.%d, duration=%d.%d\n",
880  ctx->caption.region_count,
881  (int)(ctx->caption.pts / 1000), (int)(ctx->caption.pts % 1000),
882  (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ?
883  -1 : ctx->caption.wait_duration / 1000),
884  (int)((ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE) ?
885  0 : ctx->caption.wait_duration % 1000));
886  }
887 
888  switch ((enum AVSubtitleType) ctx->subtitle_type) {
889  case SUBTITLE_TEXT:
891  break;
892 
893  case SUBTITLE_ASS:
895  break;
896 
897  case SUBTITLE_BITMAP:
899  break;
900 
901  case SUBTITLE_NONE:
902  default:
903  status = 0;
904  }
905 
906  if (status < 0) {
907  av_log(ctx, AV_LOG_ERROR, "Failed to set Subtitle: %s\n",
908  av_err2str(status));
909  aribcc_caption_cleanup(&ctx->caption);
910  return status;
911  }
912  if (status > 0) {
913  *got_sub_ptr = 1;
914  if (ctx->avpkt->pts != AV_NOPTS_VALUE)
915  sub->pts = av_rescale_q(ctx->avpkt->pts,
916  ctx->time_base, AV_TIME_BASE_Q);
917  if (ctx->caption.wait_duration == ARIBCC_DURATION_INDEFINITE)
918  sub->end_display_time = UINT32_MAX;
919  else
920  sub->end_display_time = (uint32_t)ctx->caption.wait_duration;
921  }
922 
923  aribcc_caption_cleanup(&ctx->caption);
924  return avpkt->size;
925 }
926 
928 {
929  ARIBCaptionContext *ctx = avctx->priv_data;
930 
931  if (ctx->decoder)
932  aribcc_decoder_flush(ctx->decoder);
933  if (ctx->renderer)
934  aribcc_renderer_flush(ctx->renderer);
935  if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
936  ctx->readorder = 0;
937 }
938 
940 {
941  ARIBCaptionContext *ctx = avctx->priv_data;
942 
943  av_freep(&ctx->clut);
944  if (ctx->renderer)
945  aribcc_renderer_free(ctx->renderer);
946  if (ctx->decoder)
947  aribcc_decoder_free(ctx->decoder);
948  if (ctx->context)
949  aribcc_context_free(ctx->context);
950 
951  return 0;
952 }
953 
955 {
956  ARIBCaptionContext *ctx = avctx->priv_data;
957  aribcc_profile_t profile;
958  int ret = 0;
959 
960  ctx->avctx = avctx;
961 
962  switch (avctx->profile) {
964  profile = ARIBCC_PROFILE_A;
965  /* assume 960x540 at initial state */
966  ctx->plane_width = 960;
967  ctx->plane_height = 540;
968  ctx->font_size = 36;
969  break;
971  profile = ARIBCC_PROFILE_C;
972  ctx->plane_width = 320;
973  ctx->plane_height = 180;
974  ctx->font_size = 16;
975  break;
976  default:
977  av_log(avctx, AV_LOG_ERROR, "Unknown or unsupported profile set.\n");
978  return AVERROR(EINVAL);
979  }
980  /* determine BorderStyle of ASS header */
981  if (ctx->ignore_background)
982  ctx->border_style = 1;
983  else
984  ctx->border_style = 4;
985  ctx->charstyle = ARIBCC_CHARSTYLE_DEFAULT;
986  if (ctx->force_stroke_text || ctx->ignore_background)
987  ctx->charstyle |= ARIBCC_CHARSTYLE_STROKE;
988 
989  if (!(ctx->context = aribcc_context_alloc())) {
990  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption context.\n");
991  return AVERROR_EXTERNAL;
992  }
993  aribcc_context_set_logcat_callback(ctx->context, logcat_callback, avctx);
994  if (!(ctx->decoder = aribcc_decoder_alloc(ctx->context))) {
995  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption decoder.\n");
996  return AVERROR_EXTERNAL;
997  }
998  if (!aribcc_decoder_initialize(ctx->decoder,
999  (enum aribcc_encoding_scheme_t) ctx->encoding_scheme,
1000  ARIBCC_CAPTIONTYPE_CAPTION,
1001  profile,
1002  ARIBCC_LANGUAGEID_FIRST)) {
1003  av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption decoder.\n");
1004  return AVERROR_EXTERNAL;
1005  }
1006  aribcc_decoder_set_replace_msz_fullwidth_ascii(ctx->decoder,
1007  ctx->replace_fullwidth_ascii);
1008 
1009  /* Similar behavior as ffmpeg tool to set canvas size */
1010  if (ctx->canvas_width > 0 && ctx->canvas_height > 0 &&
1011  (ctx->avctx->width == 0 || ctx->avctx->height == 0)) {
1012  ctx->avctx->width = ctx->canvas_width;
1013  ctx->avctx->height = ctx->canvas_height;
1014  }
1015 
1016  switch ((enum AVSubtitleType) ctx->subtitle_type) {
1017  case SUBTITLE_ASS:
1018  ret = set_ass_header(ctx);
1019  if (ret != 0) {
1020  av_log(avctx, AV_LOG_ERROR, "Failed to set ASS header: %s\n",
1021  av_err2str(ret));
1022  return ret;
1023  }
1024  break;
1025 
1026  case SUBTITLE_BITMAP:
1027  if(!(ctx->renderer = aribcc_renderer_alloc(ctx->context))) {
1028  av_log(avctx, AV_LOG_ERROR, "Failed to alloc libaribcaption renderer.\n");
1029  return AVERROR_EXTERNAL;
1030  }
1031  if(!aribcc_renderer_initialize(ctx->renderer,
1032  ARIBCC_CAPTIONTYPE_CAPTION,
1033  ARIBCC_FONTPROVIDER_TYPE_AUTO,
1034  ARIBCC_TEXTRENDERER_TYPE_AUTO)) {
1035  av_log(avctx, AV_LOG_ERROR, "Failed to initialize libaribcaption renderer.\n");
1036  return AVERROR_EXTERNAL;
1037  }
1039  ff_dlog(ctx, "canvas: %dx%d plane: %dx%d bitmap: %dx%d frame: %dx%d\n",
1040  ctx->avctx->width, ctx->avctx->height,
1041  ctx->plane_width, ctx->plane_height,
1042  ctx->bitmap_plane_width, ctx->bitmap_plane_height,
1043  ctx->frame_width, ctx->frame_height);
1044  if (!aribcc_renderer_set_frame_size(ctx->renderer,
1045  ctx->frame_width, ctx->frame_height)) {
1047  "aribcc_renderer_set_frame_size() returned with error.\n");
1048  return AVERROR_EXTERNAL;
1049  }
1050 
1051  if (!(ctx->clut = av_mallocz(AVPALETTE_SIZE)))
1052  return AVERROR(ENOMEM);
1053 
1054  aribcc_renderer_set_storage_policy(ctx->renderer, ARIBCC_CAPTION_STORAGE_POLICY_MINIMUM, 0);
1055  aribcc_renderer_set_replace_drcs(ctx->renderer, ctx->replace_drcs);
1056  aribcc_renderer_set_force_stroke_text(ctx->renderer, ctx->force_stroke_text);
1057  aribcc_renderer_set_force_no_background(ctx->renderer, ctx->ignore_background);
1058  aribcc_renderer_set_force_no_ruby(ctx->renderer, ctx->ignore_ruby);
1059  aribcc_renderer_set_stroke_width(ctx->renderer, ctx->stroke_width);
1060  if (ctx->font) {
1061  int is_nomem = 0;
1062  size_t count = 0;
1063  const char **font_families = NULL;
1064  const char *fonts = ctx->font;
1065 
1066  while (*fonts) {
1067  const char **ff = av_realloc_array(font_families, count + 1, sizeof(*font_families));
1068  if (!ff) {
1069  is_nomem = 1;
1070  break;
1071  } else {
1072  font_families = ff;
1073  ff[count++] = av_get_token(&fonts, ",");
1074  if (!ff[count - 1]) {
1075  is_nomem = 1;
1076  break;
1077  } else if (*fonts)
1078  fonts++;
1079  }
1080  }
1081  if (!is_nomem && count)
1082  aribcc_renderer_set_default_font_family(ctx->renderer, font_families, count, true);
1083  while (count)
1084  av_freep(&font_families[--count]);
1085  av_freep(&font_families);
1086  if (is_nomem)
1087  return AVERROR(ENOMEM);
1088  }
1089  break;
1090 
1091  case SUBTITLE_TEXT:
1092  case SUBTITLE_NONE:
1093  default:
1094  /* do nothing */ ;
1095  }
1096 
1097  ctx->readorder = 0;
1098 
1099  return 0;
1100 }
1101 
1102 #if !defined(ASS_SINGLE_RECT)
1103 # define ASS_SINGLE_RECT 0
1104 #endif
1105 
1106 #define OFFSET(x) offsetof(ARIBCaptionContext, x)
1107 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
1108 static const AVOption options[] = {
1109  { "sub_type", "subtitle rendering type",
1110  OFFSET(subtitle_type), AV_OPT_TYPE_INT,
1111  { .i64 = SUBTITLE_ASS }, SUBTITLE_NONE, SUBTITLE_ASS, SD, "type" },
1112  { "none", "do nothing", 0, AV_OPT_TYPE_CONST,
1113  { .i64 = SUBTITLE_NONE }, .flags = SD, .unit = "type" },
1114  { "bitmap", "bitmap rendering", 0, AV_OPT_TYPE_CONST,
1115  { .i64 = SUBTITLE_BITMAP }, .flags = SD, .unit = "type" },
1116  { "text", "plain text", 0, AV_OPT_TYPE_CONST,
1117  { .i64 = SUBTITLE_TEXT }, .flags = SD, .unit = "type" },
1118  { "ass", "formatted text", 0, AV_OPT_TYPE_CONST,
1119  { .i64 = SUBTITLE_ASS }, .flags = SD, .unit = "type" },
1120  { "caption_encoding", "encoding scheme of subtitle text",
1121  OFFSET(encoding_scheme), AV_OPT_TYPE_INT, { .i64 = ARIBCC_ENCODING_SCHEME_AUTO },
1122  ARIBCC_ENCODING_SCHEME_AUTO, ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN, SD, "encoding" },
1123  { "auto", "automatically detect encoding scheme", 0, AV_OPT_TYPE_CONST,
1124  { .i64 = ARIBCC_ENCODING_SCHEME_AUTO }, .flags = SD, .unit = "encoding" },
1125  { "jis", "8bit-char JIS encoding (Japanese ISDB captions)", 0, AV_OPT_TYPE_CONST,
1126  { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_JIS }, .flags = SD, .unit = "encoding" },
1127  { "utf8", "UTF-8 encoding (Philippines ISDB-T captions)", 0, AV_OPT_TYPE_CONST,
1128  { .i64 = ARIBCC_ENCODING_SCHEME_ARIB_STD_B24_UTF8 }, .flags = SD, .unit = "encoding" },
1129  { "latin", "latin characters (SBTVD / ISDB-Tb captions used in South America)", 0, AV_OPT_TYPE_CONST,
1130  { .i64 = ARIBCC_ENCODING_SCHEME_ABNT_NBR_15606_1_LATIN }, .flags = SD, .unit = "encoding" },
1131  { "ass_single_rect", "workaround of ASS subtitle for players which can't handle multi-rectangle [ass]",
1132  OFFSET(ass_single_rect), AV_OPT_TYPE_BOOL, { .i64 = ASS_SINGLE_RECT }, 0, 1, SD },
1133  { "font", "comma-separated font family [ass, bitmap]",
1134  OFFSET(font), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
1135  { "replace_fullwidth_ascii", "replace MSZ fullwidth alphanumerics with halfwidth alphanumerics [ass, bitmap]",
1136  OFFSET(replace_fullwidth_ascii), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1137  { "force_outline_text", "always render characters with outline [(ass), bitmap]",
1138  OFFSET(force_stroke_text), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1139  { "ignore_background", "ignore rendering caption background [(ass), bitmap]",
1140  OFFSET(ignore_background), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1141  { "ignore_ruby", "ignore ruby-like characters [ass, bitmap]",
1142  OFFSET(ignore_ruby), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
1143  { "outline_width", "outline width of text [(ass), bitmap]",
1144  OFFSET(stroke_width), AV_OPT_TYPE_FLOAT, { .dbl = 1.5 }, 0.0, 3.0, SD },
1145  { "replace_drcs", "replace known DRCS [bitmap]",
1146  OFFSET(replace_drcs), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, SD },
1147  {"canvas_size", "set input video size (WxH or abbreviation) [bitmap]",
1148  OFFSET(canvas_width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, INT_MAX, SD },
1149  { NULL }
1150 };
1151 
1152 static const AVClass aribcaption_class = {
1153  .class_name = "aribcaption decoder",
1154  .item_name = av_default_item_name,
1155  .option = options,
1156  .version = LIBAVUTIL_VERSION_INT,
1157 };
1158 
1160  .p.name = "libaribcaption",
1161  .p.long_name = NULL_IF_CONFIG_SMALL("ARIB STD-B24 caption decoder"),
1162  .p.type = AVMEDIA_TYPE_SUBTITLE,
1163  .p.id = AV_CODEC_ID_ARIB_CAPTION,
1164  .priv_data_size = sizeof(ARIBCaptionContext),
1166  .close = aribcaption_close,
1168  .flush = aribcaption_flush,
1169  .p.priv_class = &aribcaption_class,
1170  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1171 };
AVSubtitle
Definition: avcodec.h:2384
rect::w
int w
Definition: f_ebur128.c:77
aribcaption_class
static const AVClass aribcaption_class
Definition: libaribcaption.c:1152
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
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
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:215
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:2389
opt.h
ARIBCaptionContext::clut_alpha
uint8_t clut_alpha[ARIBC_ALPHA_MAX_NUM]
Definition: libaribcaption.c:100
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:1103
rect
Definition: f_ebur128.c:77
ARIBCaptionContext::time_base
AVRational time_base
Definition: libaribcaption.c:81
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:260
ARIBCaptionContext::encoding_scheme
int encoding_scheme
Definition: libaribcaption.c:70
AVSubtitleRect
Definition: avcodec.h:2356
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:116
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:2388
rect::y
int y
Definition: f_ebur128.c:77
estimate_video_frame_size
static void estimate_video_frame_size(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:137
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:374
AVOption
AVOption.
Definition: opt.h:251
clut_set_alpha
static void clut_set_alpha(ARIBCaptionContext *ctx, uint8_t a)
Definition: libaribcaption.c:162
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:216
logcat_callback
static void logcat_callback(aribcc_loglevel_t level, const char *message, void *userdata)
Definition: libaribcaption.c:116
FFCodec
Definition: codec_internal.h:127
AVCodecContext::subtitle_header
uint8_t * subtitle_header
Header containing style information for text subtitles.
Definition: avcodec.h:1758
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ARIBCaptionContext::border_style
int border_style
Definition: libaribcaption.c:92
clut_init
static void clut_init(ARIBCaptionContext *ctx, aribcc_caption_region_t *region)
Definition: libaribcaption.c:251
ARIBCaptionContext::clut_idx
int clut_idx
Definition: libaribcaption.c:98
aribcaption_init
static int aribcaption_init(AVCodecContext *avctx)
Definition: libaribcaption.c:954
ARIBCaptionContext::sub
AVSubtitle * sub
Definition: libaribcaption.c:63
ARIBCaptionContext::ignore_ruby
bool ignore_ruby
Definition: libaribcaption.c:76
SUBTITLE_ASS
@ SUBTITLE_ASS
Formatted text, the ass field must be set by the decoder and is authoritative.
Definition: avcodec.h:2351
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:87
ARIBCaptionContext::force_stroke_text
bool force_stroke_text
Definition: libaribcaption.c:74
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:1106
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:198
fail
#define fail()
Definition: checkasm.h:137
aribcaption_trans_text_subtitle
static int aribcaption_trans_text_subtitle(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:789
AVSubtitleRect::ass
char * ass
0 terminated ASS/SSA compatible event line.
Definition: avcodec.h:2379
options
static const AVOption options[]
Definition: libaribcaption.c:1108
ARIBCaptionContext::render_result
aribcc_render_result_t render_result
Definition: libaribcaption.c:96
ass.h
ARIBCaptionContext::replace_drcs
bool replace_drcs
Definition: libaribcaption.c:78
ARIBCaptionContext::canvas_height
int canvas_height
Definition: libaribcaption.c:83
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ARIBCaptionContext::readorder
int readorder
Definition: libaribcaption.c:93
set_ass_header
static int set_ass_header(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:496
ARIBCaptionContext::pts
int64_t pts
Definition: libaribcaption.c:80
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:1222
ARIBCaptionContext::plane_width
int plane_width
Definition: libaribcaption.c:84
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:314
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
FF_PROFILE_ARIB_PROFILE_C
#define FF_PROFILE_ARIB_PROFILE_C
Definition: avcodec.h:1713
ARIBCaptionContext::clut_overflow
int clut_overflow
Definition: libaribcaption.c:99
AVSubtitleType
AVSubtitleType
Definition: avcodec.h:2336
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:2390
AV_CODEC_ID_ARIB_CAPTION
@ AV_CODEC_ID_ARIB_CAPTION
Definition: codec_id.h:571
ASS_DEFAULT_BACK_COLOR
#define ASS_DEFAULT_BACK_COLOR
Definition: ass.h:38
aribcaption_flush
static void aribcaption_flush(AVCodecContext *avctx)
Definition: libaribcaption.c:927
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:85
NULL
#define NULL
Definition: coverity.c:32
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
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:1759
ARIBCaptionContext::caption
aribcc_caption_t caption
Definition: libaribcaption.c:95
AVSubtitleRect::data
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:2367
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:82
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:86
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
AVCodecContext::flags2
int flags2
AV_CODEC_FLAG2_*.
Definition: avcodec.h:522
ASS_DEFAULT_BOLD
#define ASS_DEFAULT_BOLD
Definition: ass.h:39
AVPacket::size
int size
Definition: packet.h:375
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:114
aribcaption_decode
static int aribcaption_decode(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt)
Definition: libaribcaption.c:841
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
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.
Definition: avcodec.h:1799
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:90
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
rect::h
int h
Definition: f_ebur128.c:77
AVSubtitle::end_display_time
uint32_t end_display_time
Definition: avcodec.h:2387
SUBTITLE_TEXT
@ SUBTITLE_TEXT
Plain text, the text field must be set by the decoder and is authoritative.
Definition: avcodec.h:2345
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:162
SUBTITLE_NONE
@ SUBTITLE_NONE
Definition: avcodec.h:2337
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:77
SUBTITLE_BITMAP
@ SUBTITLE_BITMAP
A bitmap, pict will be set.
Definition: avcodec.h:2339
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
FF_PROFILE_ARIB_PROFILE_A
#define FF_PROFILE_ARIB_PROFILE_A
Definition: avcodec.h:1712
ARIBCaptionContext::font
char * font
Definition: libaribcaption.c:72
ARIBCaptionContext::clut
uint32_t * clut
Definition: libaribcaption.c:97
ARIBCaptionContext::bitmap_plane_height
int bitmap_plane_height
Definition: libaribcaption.c:89
AVSubtitle::format
uint16_t format
Definition: avcodec.h:2385
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:367
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:939
ASS_DEFAULT_ITALIC
#define ASS_DEFAULT_ITALIC
Definition: ass.h:40
ASS_DEFAULT_COLOR
#define ASS_DEFAULT_COLOR
Definition: ass.h:37
ARIBCaptionContext::ass_single_rect
bool ass_single_rect
Definition: libaribcaption.c:71
profile
int profile
Definition: mxfenc.c:2111
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:91
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
ARIBCaptionContext::replace_fullwidth_ascii
bool replace_fullwidth_ascii
Definition: libaribcaption.c:73
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
CLUT_G
#define CLUT_G(c)
Definition: libaribcaption.c:51
AVCodecContext
main external API structure.
Definition: avcodec.h:435
ARIBCaptionContext::bitmap_plane_width
int bitmap_plane_width
Definition: libaribcaption.c:88
SD
#define SD
Definition: libaribcaption.c:1107
clut_color_distance
static int clut_color_distance(uint32_t rgba1, uint32_t rgba2)
Definition: libaribcaption.c:209
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:568
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1589
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:144
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
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:462
AVPacket
This structure stores compressed data.
Definition: packet.h:351
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:354
ff_libaribcaption_decoder
const FFCodec ff_libaribcaption_decoder
Definition: libaribcaption.c:1159
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
ARIBCaptionContext::ignore_background
bool ignore_background
Definition: libaribcaption.c:75
h
h
Definition: vp9dsp_template.c:2038
aribcaption_trans_ass_subtitle
static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
Definition: libaribcaption.c:579
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:380
int
int
Definition: ffmpeg_filter.c:354
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:103
ARIBCaptionContext::stroke_width
float stroke_width
Definition: libaribcaption.c:77
clut_find_nearlest_alpha
static uint8_t clut_find_nearlest_alpha(ARIBCaptionContext *ctx, uint8_t a)
Definition: libaribcaption.c:177
ARIBC_ALPHA_DEFAULT_BACK
#define ARIBC_ALPHA_DEFAULT_BACK
Definition: libaribcaption.c:42