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