FFmpeg
ccaption_dec.c
Go to the documentation of this file.
1 /*
2  * Closed Caption Decoding
3  * Copyright (c) 2015 Anshul Maheshwari
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 <assert.h>
23 #include "avcodec.h"
24 #include "ass.h"
25 #include "codec_internal.h"
26 #include "libavutil/opt.h"
27 
28 #define SCREEN_ROWS 15
29 #define SCREEN_COLUMNS 32
30 
31 #define SET_FLAG(var, val) ( (var) |= ( 1 << (val)) )
32 #define UNSET_FLAG(var, val) ( (var) &= ~( 1 << (val)) )
33 #define CHECK_FLAG(var, val) ( (var) & ( 1 << (val)) )
34 
35 static const AVRational ms_tb = {1, 1000};
36 
37 enum cc_mode {
42 };
43 
55 };
56 
57 enum cc_font {
62 };
63 
64 enum cc_charset {
69 };
70 
71 #define CHARSET_OVERRIDE_LIST(START_SET, ENTRY, END_SET) \
72  START_SET(CCSET_BASIC_AMERICAN) \
73  ENTRY(0x27, "\u2019") \
74  ENTRY(0x2a, "\u00e1") \
75  ENTRY(0x5c, "\u00e9") \
76  ENTRY(0x5e, "\u00ed") \
77  ENTRY(0x5f, "\u00f3") \
78  ENTRY(0x60, "\u00fa") \
79  ENTRY(0x7b, "\u00e7") \
80  ENTRY(0x7c, "\u00f7") \
81  ENTRY(0x7d, "\u00d1") \
82  ENTRY(0x7e, "\u00f1") \
83  ENTRY(0x7f, "\u2588") \
84  END_SET \
85  START_SET(CCSET_SPECIAL_AMERICAN) \
86  ENTRY(0x30, "\u00ae") \
87  ENTRY(0x31, "\u00b0") \
88  ENTRY(0x32, "\u00bd") \
89  ENTRY(0x33, "\u00bf") \
90  ENTRY(0x34, "\u2122") \
91  ENTRY(0x35, "\u00a2") \
92  ENTRY(0x36, "\u00a3") \
93  ENTRY(0x37, "\u266a") \
94  ENTRY(0x38, "\u00e0") \
95  ENTRY(0x39, "\u00A0") \
96  ENTRY(0x3a, "\u00e8") \
97  ENTRY(0x3b, "\u00e2") \
98  ENTRY(0x3c, "\u00ea") \
99  ENTRY(0x3d, "\u00ee") \
100  ENTRY(0x3e, "\u00f4") \
101  ENTRY(0x3f, "\u00fb") \
102  END_SET \
103  START_SET(CCSET_EXTENDED_SPANISH_FRENCH_MISC) \
104  ENTRY(0x20, "\u00c1") \
105  ENTRY(0x21, "\u00c9") \
106  ENTRY(0x22, "\u00d3") \
107  ENTRY(0x23, "\u00da") \
108  ENTRY(0x24, "\u00dc") \
109  ENTRY(0x25, "\u00fc") \
110  ENTRY(0x26, "\u00b4") \
111  ENTRY(0x27, "\u00a1") \
112  ENTRY(0x28, "*") \
113  ENTRY(0x29, "\u2018") \
114  ENTRY(0x2a, "-") \
115  ENTRY(0x2b, "\u00a9") \
116  ENTRY(0x2c, "\u2120") \
117  ENTRY(0x2d, "\u00b7") \
118  ENTRY(0x2e, "\u201c") \
119  ENTRY(0x2f, "\u201d") \
120  ENTRY(0x30, "\u00c0") \
121  ENTRY(0x31, "\u00c2") \
122  ENTRY(0x32, "\u00c7") \
123  ENTRY(0x33, "\u00c8") \
124  ENTRY(0x34, "\u00ca") \
125  ENTRY(0x35, "\u00cb") \
126  ENTRY(0x36, "\u00eb") \
127  ENTRY(0x37, "\u00ce") \
128  ENTRY(0x38, "\u00cf") \
129  ENTRY(0x39, "\u00ef") \
130  ENTRY(0x3a, "\u00d4") \
131  ENTRY(0x3b, "\u00d9") \
132  ENTRY(0x3c, "\u00f9") \
133  ENTRY(0x3d, "\u00db") \
134  ENTRY(0x3e, "\u00ab") \
135  ENTRY(0x3f, "\u00bb") \
136  END_SET \
137  START_SET(CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH) \
138  ENTRY(0x20, "\u00c3") \
139  ENTRY(0x21, "\u00e3") \
140  ENTRY(0x22, "\u00cd") \
141  ENTRY(0x23, "\u00cc") \
142  ENTRY(0x24, "\u00ec") \
143  ENTRY(0x25, "\u00d2") \
144  ENTRY(0x26, "\u00f2") \
145  ENTRY(0x27, "\u00d5") \
146  ENTRY(0x28, "\u00f5") \
147  ENTRY(0x29, "{") \
148  ENTRY(0x2a, "}") \
149  ENTRY(0x2b, "\\") \
150  ENTRY(0x2c, "^") \
151  ENTRY(0x2d, "_") \
152  ENTRY(0x2e, "|") \
153  ENTRY(0x2f, "~") \
154  ENTRY(0x30, "\u00c4") \
155  ENTRY(0x31, "\u00e4") \
156  ENTRY(0x32, "\u00d6") \
157  ENTRY(0x33, "\u00f6") \
158  ENTRY(0x34, "\u00df") \
159  ENTRY(0x35, "\u00a5") \
160  ENTRY(0x36, "\u00a4") \
161  ENTRY(0x37, "\u00a6") \
162  ENTRY(0x38, "\u00c5") \
163  ENTRY(0x39, "\u00e5") \
164  ENTRY(0x3a, "\u00d8") \
165  ENTRY(0x3b, "\u00f8") \
166  ENTRY(0x3c, "\u250c") \
167  ENTRY(0x3d, "\u2510") \
168  ENTRY(0x3e, "\u2514") \
169  ENTRY(0x3f, "\u2518") \
170  END_SET \
171 
172 static const char charset_overrides[4][128][sizeof("\u266a")] =
173 {
174 #define START_SET(IDX) \
175  [IDX] = {
176 #define ENTRY(idx, string) \
177  [idx] = string,
178 #define END_SET \
179  },
181 };
182 #define EMPTY_START(IDX)
183 #define EMPTY_END
184 #define ASSERT_ENTRY(IDX, str) \
185  static_assert(sizeof(str) <= sizeof(charset_overrides[0][0]), \
186  "'" str "' string takes too much space");
188 
189 static const unsigned char bg_attribs[8] = // Color
190 {
191  CCCOL_WHITE,
192  CCCOL_GREEN,
193  CCCOL_BLUE,
194  CCCOL_CYAN,
195  CCCOL_RED,
196  CCCOL_YELLOW,
198  CCCOL_BLACK,
199 };
200 
201 static const unsigned char pac2_attribs[32][3] = // Color, font, ident
202 {
203  { CCCOL_WHITE, CCFONT_REGULAR, 0 }, // 0x40 || 0x60
204  { CCCOL_WHITE, CCFONT_UNDERLINED, 0 }, // 0x41 || 0x61
205  { CCCOL_GREEN, CCFONT_REGULAR, 0 }, // 0x42 || 0x62
206  { CCCOL_GREEN, CCFONT_UNDERLINED, 0 }, // 0x43 || 0x63
207  { CCCOL_BLUE, CCFONT_REGULAR, 0 }, // 0x44 || 0x64
208  { CCCOL_BLUE, CCFONT_UNDERLINED, 0 }, // 0x45 || 0x65
209  { CCCOL_CYAN, CCFONT_REGULAR, 0 }, // 0x46 || 0x66
210  { CCCOL_CYAN, CCFONT_UNDERLINED, 0 }, // 0x47 || 0x67
211  { CCCOL_RED, CCFONT_REGULAR, 0 }, // 0x48 || 0x68
212  { CCCOL_RED, CCFONT_UNDERLINED, 0 }, // 0x49 || 0x69
213  { CCCOL_YELLOW, CCFONT_REGULAR, 0 }, // 0x4a || 0x6a
214  { CCCOL_YELLOW, CCFONT_UNDERLINED, 0 }, // 0x4b || 0x6b
215  { CCCOL_MAGENTA, CCFONT_REGULAR, 0 }, // 0x4c || 0x6c
216  { CCCOL_MAGENTA, CCFONT_UNDERLINED, 0 }, // 0x4d || 0x6d
217  { CCCOL_WHITE, CCFONT_ITALICS, 0 }, // 0x4e || 0x6e
218  { CCCOL_WHITE, CCFONT_UNDERLINED_ITALICS, 0 }, // 0x4f || 0x6f
219  { CCCOL_WHITE, CCFONT_REGULAR, 0 }, // 0x50 || 0x70
220  { CCCOL_WHITE, CCFONT_UNDERLINED, 0 }, // 0x51 || 0x71
221  { CCCOL_WHITE, CCFONT_REGULAR, 4 }, // 0x52 || 0x72
222  { CCCOL_WHITE, CCFONT_UNDERLINED, 4 }, // 0x53 || 0x73
223  { CCCOL_WHITE, CCFONT_REGULAR, 8 }, // 0x54 || 0x74
224  { CCCOL_WHITE, CCFONT_UNDERLINED, 8 }, // 0x55 || 0x75
225  { CCCOL_WHITE, CCFONT_REGULAR, 12 }, // 0x56 || 0x76
226  { CCCOL_WHITE, CCFONT_UNDERLINED, 12 }, // 0x57 || 0x77
227  { CCCOL_WHITE, CCFONT_REGULAR, 16 }, // 0x58 || 0x78
228  { CCCOL_WHITE, CCFONT_UNDERLINED, 16 }, // 0x59 || 0x79
229  { CCCOL_WHITE, CCFONT_REGULAR, 20 }, // 0x5a || 0x7a
230  { CCCOL_WHITE, CCFONT_UNDERLINED, 20 }, // 0x5b || 0x7b
231  { CCCOL_WHITE, CCFONT_REGULAR, 24 }, // 0x5c || 0x7c
232  { CCCOL_WHITE, CCFONT_UNDERLINED, 24 }, // 0x5d || 0x7d
233  { CCCOL_WHITE, CCFONT_REGULAR, 28 }, // 0x5e || 0x7e
234  { CCCOL_WHITE, CCFONT_UNDERLINED, 28 } // 0x5f || 0x7f
235  /* total 32 entries */
236 };
237 
238 struct Screen {
239  /* +1 is used to compensate null character of string */
245  /*
246  * Bitmask of used rows; if a bit is not set, the
247  * corresponding row is not used.
248  * for setting row 1 use row | (1 << 0)
249  * for setting row 15 use row | (1 << 14)
250  */
251  int16_t row_used;
252 };
253 
254 typedef struct CCaptionSubContext {
255  AVClass *class;
256  void *logctx;
260  struct Screen screen[2];
262  uint8_t cursor_row;
263  uint8_t cursor_column;
264  uint8_t cursor_color;
265  uint8_t bg_color;
266  uint8_t cursor_font;
267  uint8_t cursor_charset;
268  AVBPrint buffer[2];
271  int rollup;
272  enum cc_mode mode;
276  uint8_t prev_cmd[2];
279 
281 {
282  CCaptionSubContext *ctx = avctx->priv_data;
283 
284  ctx->logctx = avctx;
285 
288  /* taking by default roll up to 2 */
289  ctx->mode = CCMODE_ROLLUP;
290  ctx->bg_color = CCCOL_BLACK;
291  ctx->rollup = 2;
292  ctx->cursor_row = 10;
293  return ff_ass_subtitle_header(avctx, "Monospace",
300  3,
302 }
303 
305 {
306  CCaptionSubContext *ctx = avctx->priv_data;
307  av_bprint_finalize(&ctx->buffer[0], NULL);
308  av_bprint_finalize(&ctx->buffer[1], NULL);
309  return 0;
310 }
311 
312 static void flush_decoder(AVCodecContext *avctx)
313 {
314  CCaptionSubContext *ctx = avctx->priv_data;
315  ctx->screen[0].row_used = 0;
316  ctx->screen[1].row_used = 0;
317  ctx->prev_cmd[0] = 0;
318  ctx->prev_cmd[1] = 0;
319  ctx->mode = CCMODE_ROLLUP;
320  ctx->rollup = 2;
321  ctx->cursor_row = 10;
322  ctx->cursor_column = 0;
323  ctx->cursor_font = 0;
324  ctx->cursor_color = 0;
325  ctx->bg_color = CCCOL_BLACK;
326  ctx->cursor_charset = 0;
327  ctx->active_screen = 0;
328  ctx->last_real_time = 0;
329  ctx->screen_touched = 0;
330  ctx->buffer_changed = 0;
331  if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
332  ctx->readorder = 0;
333  av_bprint_clear(&ctx->buffer[0]);
334  av_bprint_clear(&ctx->buffer[1]);
335 }
336 
337 /**
338  * @param ctx closed caption context just to print log
339  */
340 static void write_char(CCaptionSubContext *ctx, struct Screen *screen, char ch)
341 {
342  uint8_t col = ctx->cursor_column;
343  char *row = screen->characters[ctx->cursor_row];
344  char *font = screen->fonts[ctx->cursor_row];
345  char *color = screen->colors[ctx->cursor_row];
346  char *bg = screen->bgs[ctx->cursor_row];
347  char *charset = screen->charsets[ctx->cursor_row];
348 
349  if (col < SCREEN_COLUMNS) {
350  row[col] = ch;
351  font[col] = ctx->cursor_font;
352  color[col] = ctx->cursor_color;
353  bg[col] = ctx->bg_color;
354  charset[col] = ctx->cursor_charset;
355  ctx->cursor_charset = CCSET_BASIC_AMERICAN;
356  if (ch) ctx->cursor_column++;
357  return;
358  }
359  /* We have extra space at end only for null character */
360  else if (col == SCREEN_COLUMNS && ch == 0) {
361  row[col] = ch;
362  return;
363  }
364  else {
365  av_log(ctx->logctx, AV_LOG_WARNING, "Data ignored due to columns exceeding screen width\n");
366  return;
367  }
368 }
369 
370 /**
371  * This function after validating parity bit, also remove it from data pair.
372  * The first byte doesn't pass parity, we replace it with a solid blank
373  * and process the pair.
374  * If the second byte doesn't pass parity, it returns INVALIDDATA
375  * user can ignore the whole pair and pass the other pair.
376  */
377 static int validate_cc_data_pair(const uint8_t *cc_data_pair, uint8_t *hi)
378 {
379  uint8_t cc_valid = (*cc_data_pair & 4) >>2;
380  uint8_t cc_type = *cc_data_pair & 3;
381 
382  *hi = cc_data_pair[1];
383 
384  if (!cc_valid)
385  return AVERROR_INVALIDDATA;
386 
387  // if EIA-608 data then verify parity.
388  if (cc_type==0 || cc_type==1) {
389  if (!av_parity(cc_data_pair[2])) {
390  return AVERROR_INVALIDDATA;
391  }
392  if (!av_parity(cc_data_pair[1])) {
393  *hi = 0x7F;
394  }
395  }
396 
397  //Skip non-data
398  if ((cc_data_pair[0] == 0xFA || cc_data_pair[0] == 0xFC || cc_data_pair[0] == 0xFD)
399  && (cc_data_pair[1] & 0x7F) == 0 && (cc_data_pair[2] & 0x7F) == 0)
400  return AVERROR_PATCHWELCOME;
401 
402  //skip 708 data
403  if (cc_type == 3 || cc_type == 2)
404  return AVERROR_PATCHWELCOME;
405 
406  return 0;
407 }
408 
410 {
411  switch (ctx->mode) {
412  case CCMODE_POPON:
413  // use Inactive screen
414  return ctx->screen + !ctx->active_screen;
415  case CCMODE_PAINTON:
416  case CCMODE_ROLLUP:
417  case CCMODE_TEXT:
418  // use active screen
419  return ctx->screen + ctx->active_screen;
420  }
421  /* It was never an option */
422  return NULL;
423 }
424 
426 {
427  struct Screen *screen;
428  int i, keep_lines;
429 
430  if (ctx->mode == CCMODE_TEXT)
431  return;
432 
433  screen = get_writing_screen(ctx);
434 
435  /* +1 signify cursor_row starts from 0
436  * Can't keep lines less then row cursor pos
437  */
438  keep_lines = FFMIN(ctx->cursor_row + 1, ctx->rollup);
439 
440  for (i = 0; i < SCREEN_ROWS; i++) {
441  if (i > ctx->cursor_row - keep_lines && i <= ctx->cursor_row)
442  continue;
443  UNSET_FLAG(screen->row_used, i);
444  }
445 
446  for (i = 0; i < keep_lines && screen->row_used; i++) {
447  const int i_row = ctx->cursor_row - keep_lines + i + 1;
448 
449  memcpy(screen->characters[i_row], screen->characters[i_row+1], SCREEN_COLUMNS);
450  memcpy(screen->colors[i_row], screen->colors[i_row+1], SCREEN_COLUMNS);
451  memcpy(screen->bgs[i_row], screen->bgs[i_row+1], SCREEN_COLUMNS);
452  memcpy(screen->fonts[i_row], screen->fonts[i_row+1], SCREEN_COLUMNS);
453  memcpy(screen->charsets[i_row], screen->charsets[i_row+1], SCREEN_COLUMNS);
454  if (CHECK_FLAG(screen->row_used, i_row + 1))
455  SET_FLAG(screen->row_used, i_row);
456  }
457 
458  UNSET_FLAG(screen->row_used, ctx->cursor_row);
459 }
460 
462 {
463  int i, j, tab = 0;
464  struct Screen *screen = ctx->screen + ctx->active_screen;
465  enum cc_font prev_font = CCFONT_REGULAR;
466  enum cc_color_code prev_color = CCCOL_WHITE;
467  enum cc_color_code prev_bg_color = CCCOL_BLACK;
468  const int bidx = ctx->buffer_index;
469 
470  av_bprint_clear(&ctx->buffer[bidx]);
471 
472  for (i = 0; screen->row_used && i < SCREEN_ROWS; i++)
473  {
474  if (CHECK_FLAG(screen->row_used, i)) {
475  const char *row = screen->characters[i];
476  const char *charset = screen->charsets[i];
477  j = 0;
478  while (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN)
479  j++;
480  if (!tab || j < tab)
481  tab = j;
482  }
483  }
484 
485  for (i = 0; screen->row_used && i < SCREEN_ROWS; i++)
486  {
487  if (CHECK_FLAG(screen->row_used, i)) {
488  const char *row = screen->characters[i];
489  const char *font = screen->fonts[i];
490  const char *bg = screen->bgs[i];
491  const char *color = screen->colors[i];
492  const char *charset = screen->charsets[i];
493  const char *override;
494  int x, y, seen_char = 0;
495  j = 0;
496 
497  /* skip leading space */
498  while (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN && j < tab)
499  j++;
500 
501  x = ASS_DEFAULT_PLAYRESX * (0.1 + 0.0250 * j);
502  y = ASS_DEFAULT_PLAYRESY * (0.1 + 0.0533 * i);
503  av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y);
504 
505  for (; j < SCREEN_COLUMNS; j++) {
506  const char *e_tag = "", *s_tag = "", *c_tag = "", *b_tag = "";
507 
508  if (row[j] == 0)
509  break;
510 
511  if (prev_font != font[j]) {
512  switch (prev_font) {
513  case CCFONT_ITALICS:
514  e_tag = "{\\i0}";
515  break;
516  case CCFONT_UNDERLINED:
517  e_tag = "{\\u0}";
518  break;
520  e_tag = "{\\u0}{\\i0}";
521  break;
522  }
523  switch (font[j]) {
524  case CCFONT_ITALICS:
525  s_tag = "{\\i1}";
526  break;
527  case CCFONT_UNDERLINED:
528  s_tag = "{\\u1}";
529  break;
531  s_tag = "{\\u1}{\\i1}";
532  break;
533  }
534  }
535  if (prev_color != color[j]) {
536  switch (color[j]) {
537  case CCCOL_WHITE:
538  c_tag = "{\\c&HFFFFFF&}";
539  break;
540  case CCCOL_GREEN:
541  c_tag = "{\\c&H00FF00&}";
542  break;
543  case CCCOL_BLUE:
544  c_tag = "{\\c&HFF0000&}";
545  break;
546  case CCCOL_CYAN:
547  c_tag = "{\\c&HFFFF00&}";
548  break;
549  case CCCOL_RED:
550  c_tag = "{\\c&H0000FF&}";
551  break;
552  case CCCOL_YELLOW:
553  c_tag = "{\\c&H00FFFF&}";
554  break;
555  case CCCOL_MAGENTA:
556  c_tag = "{\\c&HFF00FF&}";
557  break;
558  }
559  }
560  if (prev_bg_color != bg[j]) {
561  switch (bg[j]) {
562  case CCCOL_WHITE:
563  b_tag = "{\\3c&HFFFFFF&}";
564  break;
565  case CCCOL_GREEN:
566  b_tag = "{\\3c&H00FF00&}";
567  break;
568  case CCCOL_BLUE:
569  b_tag = "{\\3c&HFF0000&}";
570  break;
571  case CCCOL_CYAN:
572  b_tag = "{\\3c&HFFFF00&}";
573  break;
574  case CCCOL_RED:
575  b_tag = "{\\3c&H0000FF&}";
576  break;
577  case CCCOL_YELLOW:
578  b_tag = "{\\3c&H00FFFF&}";
579  break;
580  case CCCOL_MAGENTA:
581  b_tag = "{\\3c&HFF00FF&}";
582  break;
583  case CCCOL_BLACK:
584  b_tag = "{\\3c&H000000&}";
585  break;
586  }
587  }
588 
589  prev_font = font[j];
590  prev_color = color[j];
591  prev_bg_color = bg[j];
592  override = charset_overrides[(int)charset[j]][(int)row[j]];
593  if (override[0]) {
594  av_bprintf(&ctx->buffer[bidx], "%s%s%s%s%s", e_tag, s_tag, c_tag, b_tag, override);
595  seen_char = 1;
596  } else if (row[j] == ' ' && !seen_char) {
597  av_bprintf(&ctx->buffer[bidx], "%s%s%s%s\\h", e_tag, s_tag, c_tag, b_tag);
598  } else {
599  av_bprintf(&ctx->buffer[bidx], "%s%s%s%s%c", e_tag, s_tag, c_tag, b_tag, row[j]);
600  seen_char = 1;
601  }
602 
603  }
604  av_bprintf(&ctx->buffer[bidx], "\\N");
605  }
606  }
607  if (!av_bprint_is_complete(&ctx->buffer[bidx]))
608  return AVERROR(ENOMEM);
609  if (screen->row_used && ctx->buffer[bidx].len >= 2) {
610  ctx->buffer[bidx].len -= 2;
611  ctx->buffer[bidx].str[ctx->buffer[bidx].len] = 0;
612  }
613  ctx->buffer_changed = 1;
614  return 0;
615 }
616 
618 {
619  ctx->buffer_time[0] = ctx->buffer_time[1];
620  ctx->buffer_time[1] = pts;
621 }
622 
623 static void handle_bgattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
624 {
625  const int i = (lo & 0xf) >> 1;
626 
627  ctx->bg_color = bg_attribs[i];
628 }
629 
630 static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
631 {
632  int i = lo - 0x20;
633  struct Screen *screen = get_writing_screen(ctx);
634 
635  if (i >= 32)
636  return;
637 
638  ctx->cursor_color = pac2_attribs[i][0];
639  ctx->cursor_font = pac2_attribs[i][1];
640 
641  SET_FLAG(screen->row_used, ctx->cursor_row);
642  write_char(ctx, screen, ' ');
643 }
644 
645 static void handle_pac(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
646 {
647  static const int8_t row_map[] = {
648  11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
649  };
650  const int index = ( (hi<<1) & 0x0e) | ( (lo>>5) & 0x01 );
651  struct Screen *screen = get_writing_screen(ctx);
652  int indent, i;
653 
654  if (row_map[index] <= 0) {
655  av_log(ctx->logctx, AV_LOG_DEBUG, "Invalid pac index encountered\n");
656  return;
657  }
658 
659  lo &= 0x1f;
660 
661  ctx->cursor_row = row_map[index] - 1;
662  ctx->cursor_color = pac2_attribs[lo][0];
663  ctx->cursor_font = pac2_attribs[lo][1];
664  ctx->cursor_charset = CCSET_BASIC_AMERICAN;
665  ctx->cursor_column = 0;
666  indent = pac2_attribs[lo][2];
667  for (i = 0; i < indent; i++) {
668  write_char(ctx, screen, ' ');
669  }
670 }
671 
673 {
674  struct Screen *screen = ctx->screen + ctx->active_screen;
675  int ret;
676 
677  // In buffered mode, keep writing to screen until it is wiped.
678  // Before wiping the display, capture contents to emit subtitle.
679  if (!ctx->real_time)
681 
682  screen->row_used = 0;
683  ctx->bg_color = CCCOL_BLACK;
684 
685  // In realtime mode, emit an empty caption so the last one doesn't
686  // stay on the screen.
687  if (ctx->real_time)
689 
690  return ret;
691 }
692 
694 {
695  int ret;
696 
697  ctx->active_screen = !ctx->active_screen;
698 
699  // In buffered mode, we wait til the *next* EOC and
700  // capture what was already on the screen since the last EOC.
701  if (!ctx->real_time)
702  ret = handle_edm(ctx);
703 
704  ctx->cursor_column = 0;
705 
706  // In realtime mode, we display the buffered contents (after
707  // flipping the buffer to active above) as soon as EOC arrives.
708  if (ctx->real_time)
710 
711  return ret;
712 }
713 
715 {
716  struct Screen *screen = get_writing_screen(ctx);
717  write_char(ctx, screen, 0);
718 }
719 
720 static void handle_char(CCaptionSubContext *ctx, char hi, char lo)
721 {
722  struct Screen *screen = get_writing_screen(ctx);
723 
724  SET_FLAG(screen->row_used, ctx->cursor_row);
725 
726  switch (hi) {
727  case 0x11:
728  ctx->cursor_charset = CCSET_SPECIAL_AMERICAN;
729  break;
730  case 0x12:
731  if (ctx->cursor_column > 0)
732  ctx->cursor_column -= 1;
733  ctx->cursor_charset = CCSET_EXTENDED_SPANISH_FRENCH_MISC;
734  break;
735  case 0x13:
736  if (ctx->cursor_column > 0)
737  ctx->cursor_column -= 1;
739  break;
740  default:
741  ctx->cursor_charset = CCSET_BASIC_AMERICAN;
742  write_char(ctx, screen, hi);
743  break;
744  }
745 
746  if (lo) {
747  write_char(ctx, screen, lo);
748  }
749  write_char(ctx, screen, 0);
750 
751  if (ctx->mode != CCMODE_POPON)
752  ctx->screen_touched = 1;
753 
754  if (lo)
755  ff_dlog(ctx->logctx, "(%c,%c)\n", hi, lo);
756  else
757  ff_dlog(ctx->logctx, "(%c)\n", hi);
758 }
759 
760 static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
761 {
762  int ret = 0;
763 
764  if (hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) {
765  return 0;
766  }
767 
768  /* set prev command */
769  ctx->prev_cmd[0] = hi;
770  ctx->prev_cmd[1] = lo;
771 
772  if ( (hi == 0x10 && (lo >= 0x40 && lo <= 0x5f)) ||
773  ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
774  handle_pac(ctx, hi, lo);
775  } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
776  ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
777  handle_textattr(ctx, hi, lo);
778  } else if ((hi == 0x10 && lo >= 0x20 && lo <= 0x2f)) {
779  handle_bgattr(ctx, hi, lo);
780  } else if (hi == 0x14 || hi == 0x15 || hi == 0x1c) {
781  switch (lo) {
782  case 0x20:
783  /* resume caption loading */
784  ctx->mode = CCMODE_POPON;
785  break;
786  case 0x24:
788  break;
789  case 0x25:
790  case 0x26:
791  case 0x27:
792  ctx->rollup = lo - 0x23;
793  ctx->mode = CCMODE_ROLLUP;
794  break;
795  case 0x29:
796  /* resume direct captioning */
797  ctx->mode = CCMODE_PAINTON;
798  break;
799  case 0x2b:
800  /* resume text display */
801  ctx->mode = CCMODE_TEXT;
802  break;
803  case 0x2c:
804  /* erase display memory */
805  handle_edm(ctx);
806  break;
807  case 0x2d:
808  /* carriage return */
809  ff_dlog(ctx->logctx, "carriage return\n");
810  if (!ctx->real_time)
812  roll_up(ctx);
813  ctx->cursor_column = 0;
814  break;
815  case 0x2e:
816  /* erase buffered (non displayed) memory */
817  // Only in realtime mode. In buffered mode, we re-use the inactive screen
818  // for our own buffering.
819  if (ctx->real_time) {
820  struct Screen *screen = ctx->screen + !ctx->active_screen;
821  screen->row_used = 0;
822  }
823  break;
824  case 0x2f:
825  /* end of caption */
826  ff_dlog(ctx->logctx, "handle_eoc\n");
827  ret = handle_eoc(ctx);
828  break;
829  default:
830  ff_dlog(ctx->logctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
831  break;
832  }
833  } else if (hi >= 0x11 && hi <= 0x13) {
834  /* Special characters */
835  handle_char(ctx, hi, lo);
836  } else if (hi >= 0x20) {
837  /* Standard characters (always in pairs) */
838  handle_char(ctx, hi, lo);
839  ctx->prev_cmd[0] = ctx->prev_cmd[1] = 0;
840  } else if (hi == 0x17 && lo >= 0x21 && lo <= 0x23) {
841  int i;
842  /* Tab offsets (spacing) */
843  for (i = 0; i < lo - 0x20; i++) {
844  handle_char(ctx, ' ', 0);
845  }
846  } else {
847  /* Ignoring all other non data code */
848  ff_dlog(ctx->logctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
849  }
850 
851  return ret;
852 }
853 
854 static int decode(AVCodecContext *avctx, AVSubtitle *sub,
855  int *got_sub, const AVPacket *avpkt)
856 {
857  CCaptionSubContext *ctx = avctx->priv_data;
858  int64_t in_time = sub->pts;
860  int64_t end_time;
861  int bidx = ctx->buffer_index;
862  const uint8_t *bptr = avpkt->data;
863  int len = avpkt->size;
864  int ret = 0;
865  int i;
866  unsigned nb_rect_allocated = 0;
867 
868  for (i = 0; i < len; i += 3) {
869  uint8_t hi, cc_type = bptr[i] & 1;
870 
871  if (ctx->data_field < 0)
872  ctx->data_field = cc_type;
873 
874  if (validate_cc_data_pair(bptr + i, &hi))
875  continue;
876 
877  if (cc_type != ctx->data_field)
878  continue;
879 
880  ret = process_cc608(ctx, hi & 0x7f, bptr[i + 2] & 0x7f);
881  if (ret < 0)
882  return ret;
883 
884  if (!ctx->buffer_changed)
885  continue;
886  ctx->buffer_changed = 0;
887 
888  if (!ctx->real_time && ctx->mode == CCMODE_POPON)
889  ctx->buffer_index = bidx = !ctx->buffer_index;
890 
891  update_time(ctx, in_time);
892 
893  if (ctx->buffer[bidx].str[0] || ctx->real_time) {
894  ff_dlog(avctx, "cdp writing data (%s)\n", ctx->buffer[bidx].str);
895  start_time = ctx->buffer_time[0];
896  sub->pts = start_time;
897  end_time = ctx->buffer_time[1];
898  if (!ctx->real_time)
899  sub->end_display_time = av_rescale_q(end_time - start_time,
901  else
902  sub->end_display_time = -1;
903  ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated);
904  if (ret < 0)
905  return ret;
906  ctx->last_real_time = sub->pts;
907  ctx->screen_touched = 0;
908  }
909  }
910 
911  if (!bptr && !ctx->real_time && ctx->buffer[!ctx->buffer_index].str[0]) {
912  bidx = !ctx->buffer_index;
913  ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated);
914  if (ret < 0)
915  return ret;
916  av_bprint_clear(&ctx->buffer[bidx]);
917  sub->pts = ctx->buffer_time[1];
918  sub->end_display_time = av_rescale_q(ctx->buffer_time[1] - ctx->buffer_time[0],
920  if (sub->end_display_time == 0)
921  sub->end_display_time = ctx->buffer[bidx].len * 20;
922  }
923 
924  if (ctx->real_time && ctx->screen_touched &&
925  sub->pts >= ctx->last_real_time + av_rescale_q(ctx->real_time_latency_msec, ms_tb, AV_TIME_BASE_Q)) {
926  ctx->last_real_time = sub->pts;
927  ctx->screen_touched = 0;
928 
930  ctx->buffer_changed = 0;
931 
932  ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated);
933  if (ret < 0)
934  return ret;
935  sub->end_display_time = -1;
936  }
937 
938  *got_sub = sub->num_rects > 0;
939  return avpkt->size;
940 }
941 
942 #define OFFSET(x) offsetof(CCaptionSubContext, x)
943 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
944 static const AVOption options[] = {
945  { "real_time", "emit subtitle events as they are decoded for real-time display", OFFSET(real_time), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD },
946  { "real_time_latency_msec", "minimum elapsed time between emitting real-time subtitle events", OFFSET(real_time_latency_msec), AV_OPT_TYPE_INT, { .i64 = 200 }, 0, 500, SD },
947  { "data_field", "select data field", OFFSET(data_field), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, SD, .unit = "data_field" },
948  { "auto", "pick first one that appears", 0, AV_OPT_TYPE_CONST, { .i64 =-1 }, 0, 0, SD, .unit = "data_field" },
949  { "first", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, SD, .unit = "data_field" },
950  { "second", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, SD, .unit = "data_field" },
951  {NULL}
952 };
953 
954 static const AVClass ccaption_dec_class = {
955  .class_name = "Closed Captions Decoder",
956  .item_name = av_default_item_name,
957  .option = options,
958  .version = LIBAVUTIL_VERSION_INT,
959 };
960 
962  .p.name = "cc_dec",
963  CODEC_LONG_NAME("Closed Captions (EIA-608 / CEA-708)"),
964  .p.type = AVMEDIA_TYPE_SUBTITLE,
965  .p.id = AV_CODEC_ID_EIA_608,
966  .p.priv_class = &ccaption_dec_class,
967  .p.capabilities = AV_CODEC_CAP_DELAY,
968  .priv_data_size = sizeof(CCaptionSubContext),
969  .init = init_decoder,
970  .close = close_decoder,
971  .flush = flush_decoder,
973 };
get_writing_screen
static struct Screen * get_writing_screen(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:409
CCaptionSubContext::last_real_time
int64_t last_real_time
Definition: ccaption_dec.c:275
ff_ass_subtitle_header
int ff_ass_subtitle_header(AVCodecContext *avctx, const char *font, int font_size, int color, int back_color, int bold, int italic, int underline, int border_style, int alignment)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS.
Definition: ass.c:84
AVSubtitle
Definition: avcodec.h:2257
CCCOL_YELLOW
@ CCCOL_YELLOW
Definition: ccaption_dec.c:50
AV_CODEC_ID_EIA_608
@ AV_CODEC_ID_EIA_608
Definition: codec_id.h:568
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:215
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
CCaptionSubContext
Definition: ccaption_dec.c:254
CHECK_FLAG
#define CHECK_FLAG(var, val)
Definition: ccaption_dec.c:33
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
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
opt.h
handle_bgattr
static void handle_bgattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:623
CCaptionSubContext::cursor_font
uint8_t cursor_font
Definition: ccaption_dec.c:266
color
Definition: vf_paletteuse.c:513
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
CCSET_EXTENDED_SPANISH_FRENCH_MISC
@ CCSET_EXTENDED_SPANISH_FRENCH_MISC
Definition: ccaption_dec.c:67
Screen
Definition: ccaption_dec.c:238
CCaptionSubContext::cursor_column
uint8_t cursor_column
Definition: ccaption_dec.c:263
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
int64_t
long long int64_t
Definition: coverity.c:34
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:2261
CCMODE_PAINTON
@ CCMODE_PAINTON
Definition: ccaption_dec.c:39
ASS_DEFAULT_ALIGNMENT
#define ASS_DEFAULT_ALIGNMENT
Definition: ass.h:42
AVPacket::data
uint8_t * data
Definition: packet.h:539
AVOption
AVOption.
Definition: opt.h:429
CHARSET_OVERRIDE_LIST
#define CHARSET_OVERRIDE_LIST(START_SET, ENTRY, END_SET)
Definition: ccaption_dec.c:71
FFCodec
Definition: codec_internal.h:127
CCMODE_POPON
@ CCMODE_POPON
Definition: ccaption_dec.c:38
CCaptionSubContext::cursor_charset
uint8_t cursor_charset
Definition: ccaption_dec.c:267
OFFSET
#define OFFSET(x)
Definition: ccaption_dec.c:942
SCREEN_ROWS
#define SCREEN_ROWS
Definition: ccaption_dec.c:28
START_SET
#define START_SET(IDX)
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
ASSERT_ENTRY
#define ASSERT_ENTRY(IDX, str)
Definition: ccaption_dec.c:184
ff_ass_add_rect2
int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker, unsigned *nb_rect_allocated)
Add an ASS dialog to a subtitle.
Definition: ass.c:119
handle_eoc
static int handle_eoc(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:693
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:10345
CCaptionSubContext::cursor_row
uint8_t cursor_row
Definition: ccaption_dec.c:262
bg_attribs
static const unsigned char bg_attribs[8]
Definition: ccaption_dec.c:189
CCaptionSubContext::screen
struct Screen screen[2]
Definition: ccaption_dec.c:260
CCaptionSubContext::buffer_index
int buffer_index
Definition: ccaption_dec.c:269
pts
static int64_t pts
Definition: transcode_aac.c:644
handle_edm
static int handle_edm(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:672
CCaptionSubContext::real_time_latency_msec
int real_time_latency_msec
Definition: ccaption_dec.c:258
ass.h
CCaptionSubContext::mode
enum cc_mode mode
Definition: ccaption_dec.c:272
cc_mode
cc_mode
Definition: ccaption_dec.c:37
CCFONT_UNDERLINED
@ CCFONT_UNDERLINED
Definition: ccaption_dec.c:60
write_char
static void write_char(CCaptionSubContext *ctx, struct Screen *screen, char ch)
Definition: ccaption_dec.c:340
av_cold
#define av_cold
Definition: attributes.h:90
Screen::characters
uint8_t characters[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:240
av_parity
#define av_parity
Definition: common.h:160
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
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:2263
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:326
ASS_DEFAULT_BACK_COLOR
#define ASS_DEFAULT_BACK_COLOR
Definition: ass.h:38
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
update_time
static void update_time(CCaptionSubContext *ctx, int64_t pts)
Definition: ccaption_dec.c:617
CCCOL_BLUE
@ CCCOL_BLUE
Definition: ccaption_dec.c:47
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:239
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:370
options
Definition: swscale.c:42
ASS_DEFAULT_PLAYRESY
#define ASS_DEFAULT_PLAYRESY
Definition: ass.h:29
CCaptionSubContext::prev_cmd
uint8_t prev_cmd[2]
Definition: ccaption_dec.c:276
index
int index
Definition: gxfenc.c:90
CCaptionSubContext::cursor_color
uint8_t cursor_color
Definition: ccaption_dec.c:264
handle_delete_end_of_row
static void handle_delete_end_of_row(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:714
CCaptionSubContext::rollup
int rollup
Definition: ccaption_dec.c:271
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
CCaptionSubContext::real_time
int real_time
Definition: ccaption_dec.c:257
AVCodecContext::flags2
int flags2
AV_CODEC_FLAG2_*.
Definition: avcodec.h:515
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
ASS_DEFAULT_BOLD
#define ASS_DEFAULT_BOLD
Definition: ass.h:39
AVPacket::size
int size
Definition: packet.h:540
CCCOL_TRANSPARENT
@ CCCOL_TRANSPARENT
Definition: ccaption_dec.c:54
charset_overrides
static const char charset_overrides[4][128][sizeof("\u266a")]
Definition: ccaption_dec.c:172
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
codec_internal.h
cc_charset
cc_charset
Definition: ccaption_dec.c:64
start_time
static int64_t start_time
Definition: ffplay.c:326
Screen::charsets
uint8_t charsets[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:241
ASS_DEFAULT_PLAYRESX
#define ASS_DEFAULT_PLAYRESX
Definition: ass.h:28
pac2_attribs
static const unsigned char pac2_attribs[32][3]
Definition: ccaption_dec.c:201
CCaptionSubContext::buffer
AVBPrint buffer[2]
Definition: ccaption_dec.c:268
CCCOL_BLACK
@ CCCOL_BLACK
Definition: ccaption_dec.c:53
flush_decoder
static void flush_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:312
CCFONT_ITALICS
@ CCFONT_ITALICS
Definition: ccaption_dec.c:59
AVSubtitle::end_display_time
uint32_t end_display_time
Definition: avcodec.h:2260
validate_cc_data_pair
static int validate_cc_data_pair(const uint8_t *cc_data_pair, uint8_t *hi)
This function after validating parity bit, also remove it from data pair.
Definition: ccaption_dec.c:377
SET_FLAG
#define SET_FLAG(var, val)
Definition: ccaption_dec.c:31
ASS_DEFAULT_UNDERLINE
#define ASS_DEFAULT_UNDERLINE
Definition: ass.h:41
init_decoder
static av_cold int init_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:280
SCREEN_COLUMNS
#define SCREEN_COLUMNS
Definition: ccaption_dec.c:29
CCaptionSubContext::data_field
int data_field
Definition: ccaption_dec.c:259
Screen::row_used
int16_t row_used
Definition: ccaption_dec.c:251
CCFONT_UNDERLINED_ITALICS
@ CCFONT_UNDERLINED_ITALICS
Definition: ccaption_dec.c:61
CCaptionSubContext::logctx
void * logctx
Definition: ccaption_dec.c:256
options
static const AVOption options[]
Definition: ccaption_dec.c:944
Screen::bgs
uint8_t bgs[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:243
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
capture_screen
static int capture_screen(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:461
UNSET_FLAG
#define UNSET_FLAG(var, val)
Definition: ccaption_dec.c:32
CCCOL_GREEN
@ CCCOL_GREEN
Definition: ccaption_dec.c:46
cc_color_code
cc_color_code
Definition: ccaption_dec.c:44
ff_ccaption_decoder
const FFCodec ff_ccaption_decoder
Definition: ccaption_dec.c:961
CCaptionSubContext::buffer_changed
int buffer_changed
Definition: ccaption_dec.c:270
EMPTY_END
#define EMPTY_END
Definition: ccaption_dec.c:183
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
cc_font
cc_font
Definition: ccaption_dec.c:57
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
ASS_DEFAULT_ITALIC
#define ASS_DEFAULT_ITALIC
Definition: ass.h:40
len
int len
Definition: vorbis_enc_data.h:426
ASS_DEFAULT_COLOR
#define ASS_DEFAULT_COLOR
Definition: ass.h:37
handle_textattr
static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:630
avcodec.h
ret
ret
Definition: filter_design.txt:187
CCFONT_REGULAR
@ CCFONT_REGULAR
Definition: ccaption_dec.c:58
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:80
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
CCSET_BASIC_AMERICAN
@ CCSET_BASIC_AMERICAN
Definition: ccaption_dec.c:65
Screen::colors
uint8_t colors[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:242
CCaptionSubContext::active_screen
int active_screen
Definition: ccaption_dec.c:261
ASS_DEFAULT_FONT_SIZE
#define ASS_DEFAULT_FONT_SIZE
Definition: ass.h:36
AVCodecContext
main external API structure.
Definition: avcodec.h:451
close_decoder
static av_cold int close_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:304
Screen::fonts
uint8_t fonts[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:244
CCCOL_CYAN
@ CCCOL_CYAN
Definition: ccaption_dec.c:48
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
decode
static int decode(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub, const AVPacket *avpkt)
Definition: ccaption_dec.c:854
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:232
ccaption_dec_class
static const AVClass ccaption_dec_class
Definition: ccaption_dec.c:954
CCSET_SPECIAL_AMERICAN
@ CCSET_SPECIAL_AMERICAN
Definition: ccaption_dec.c:66
AV_CODEC_CAP_DELAY
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: codec.h:76
FF_CODEC_DECODE_SUB_CB
#define FF_CODEC_DECODE_SUB_CB(func)
Definition: codec_internal.h:345
CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH
@ CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH
Definition: ccaption_dec.c:68
CCaptionSubContext::bg_color
uint8_t bg_color
Definition: ccaption_dec.c:265
CCCOL_USERDEFINED
@ CCCOL_USERDEFINED
Definition: ccaption_dec.c:52
EMPTY_START
#define EMPTY_START(IDX)
Definition: ccaption_dec.c:182
END_SET
#define END_SET
process_cc608
static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:760
AVPacket
This structure stores compressed data.
Definition: packet.h:516
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
handle_pac
static void handle_pac(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:645
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
CCaptionSubContext::readorder
int readorder
Definition: ccaption_dec.c:277
handle_char
static void handle_char(CCaptionSubContext *ctx, char hi, char lo)
Definition: ccaption_dec.c:720
ms_tb
static const AVRational ms_tb
Definition: ccaption_dec.c:35
CCCOL_RED
@ CCCOL_RED
Definition: ccaption_dec.c:49
roll_up
static void roll_up(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:425
CCCOL_WHITE
@ CCCOL_WHITE
Definition: ccaption_dec.c:45
CCaptionSubContext::buffer_time
int64_t buffer_time[2]
Definition: ccaption_dec.c:273
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:392
CCCOL_MAGENTA
@ CCCOL_MAGENTA
Definition: ccaption_dec.c:51
CCMODE_TEXT
@ CCMODE_TEXT
Definition: ccaption_dec.c:41
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
SD
#define SD
Definition: ccaption_dec.c:943
ENTRY
#define ENTRY(idx, string)
CCMODE_ROLLUP
@ CCMODE_ROLLUP
Definition: ccaption_dec.c:40
CCaptionSubContext::screen_touched
int screen_touched
Definition: ccaption_dec.c:274