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