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