FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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/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 /*
35  * TODO list
36  * 1) handle font and color completely
37  */
38 enum cc_mode {
45 };
46 
58 };
59 
60 enum cc_font {
65 };
66 
67 static const unsigned char pac2_attribs[32][3] = // Color, font, ident
68 {
69  { CCCOL_WHITE, CCFONT_REGULAR, 0 }, // 0x40 || 0x60
70  { CCCOL_WHITE, CCFONT_UNDERLINED, 0 }, // 0x41 || 0x61
71  { CCCOL_GREEN, CCFONT_REGULAR, 0 }, // 0x42 || 0x62
72  { CCCOL_GREEN, CCFONT_UNDERLINED, 0 }, // 0x43 || 0x63
73  { CCCOL_BLUE, CCFONT_REGULAR, 0 }, // 0x44 || 0x64
74  { CCCOL_BLUE, CCFONT_UNDERLINED, 0 }, // 0x45 || 0x65
75  { CCCOL_CYAN, CCFONT_REGULAR, 0 }, // 0x46 || 0x66
76  { CCCOL_CYAN, CCFONT_UNDERLINED, 0 }, // 0x47 || 0x67
77  { CCCOL_RED, CCFONT_REGULAR, 0 }, // 0x48 || 0x68
78  { CCCOL_RED, CCFONT_UNDERLINED, 0 }, // 0x49 || 0x69
79  { CCCOL_YELLOW, CCFONT_REGULAR, 0 }, // 0x4a || 0x6a
80  { CCCOL_YELLOW, CCFONT_UNDERLINED, 0 }, // 0x4b || 0x6b
81  { CCCOL_MAGENTA, CCFONT_REGULAR, 0 }, // 0x4c || 0x6c
82  { CCCOL_MAGENTA, CCFONT_UNDERLINED, 0 }, // 0x4d || 0x6d
83  { CCCOL_WHITE, CCFONT_ITALICS, 0 }, // 0x4e || 0x6e
84  { CCCOL_WHITE, CCFONT_UNDERLINED_ITALICS, 0 }, // 0x4f || 0x6f
85  { CCCOL_WHITE, CCFONT_REGULAR, 0 }, // 0x50 || 0x70
86  { CCCOL_WHITE, CCFONT_UNDERLINED, 0 }, // 0x51 || 0x71
87  { CCCOL_WHITE, CCFONT_REGULAR, 4 }, // 0x52 || 0x72
88  { CCCOL_WHITE, CCFONT_UNDERLINED, 4 }, // 0x53 || 0x73
89  { CCCOL_WHITE, CCFONT_REGULAR, 8 }, // 0x54 || 0x74
90  { CCCOL_WHITE, CCFONT_UNDERLINED, 8 }, // 0x55 || 0x75
91  { CCCOL_WHITE, CCFONT_REGULAR, 12 }, // 0x56 || 0x76
92  { CCCOL_WHITE, CCFONT_UNDERLINED, 12 }, // 0x57 || 0x77
93  { CCCOL_WHITE, CCFONT_REGULAR, 16 }, // 0x58 || 0x78
94  { CCCOL_WHITE, CCFONT_UNDERLINED, 16 }, // 0x59 || 0x79
95  { CCCOL_WHITE, CCFONT_REGULAR, 20 }, // 0x5a || 0x7a
96  { CCCOL_WHITE, CCFONT_UNDERLINED, 20 }, // 0x5b || 0x7b
97  { CCCOL_WHITE, CCFONT_REGULAR, 24 }, // 0x5c || 0x7c
98  { CCCOL_WHITE, CCFONT_UNDERLINED, 24 }, // 0x5d || 0x7d
99  { CCCOL_WHITE, CCFONT_REGULAR, 28 }, // 0x5e || 0x7e
100  { CCCOL_WHITE, CCFONT_UNDERLINED, 28 } // 0x5f || 0x7f
101  /* total 32 entries */
102 };
103 
104 /* 0-255 needs 256 spaces */
105 static const uint8_t parity_table[256] = { 0, 1, 1, 0, 1, 0, 0, 1,
106  1, 0, 0, 1, 0, 1, 1, 0,
107  1, 0, 0, 1, 0, 1, 1, 0,
108  0, 1, 1, 0, 1, 0, 0, 1,
109  1, 0, 0, 1, 0, 1, 1, 0,
110  0, 1, 1, 0, 1, 0, 0, 1,
111  0, 1, 1, 0, 1, 0, 0, 1,
112  1, 0, 0, 1, 0, 1, 1, 0,
113  1, 0, 0, 1, 0, 1, 1, 0,
114  0, 1, 1, 0, 1, 0, 0, 1,
115  0, 1, 1, 0, 1, 0, 0, 1,
116  1, 0, 0, 1, 0, 1, 1, 0,
117  0, 1, 1, 0, 1, 0, 0, 1,
118  1, 0, 0, 1, 0, 1, 1, 0,
119  1, 0, 0, 1, 0, 1, 1, 0,
120  0, 1, 1, 0, 1, 0, 0, 1,
121  1, 0, 0, 1, 0, 1, 1, 0,
122  0, 1, 1, 0, 1, 0, 0, 1,
123  0, 1, 1, 0, 1, 0, 0, 1,
124  1, 0, 0, 1, 0, 1, 1, 0,
125  0, 1, 1, 0, 1, 0, 0, 1,
126  1, 0, 0, 1, 0, 1, 1, 0,
127  1, 0, 0, 1, 0, 1, 1, 0,
128  0, 1, 1, 0, 1, 0, 0, 1,
129  0, 1, 1, 0, 1, 0, 0, 1,
130  1, 0, 0, 1, 0, 1, 1, 0,
131  1, 0, 0, 1, 0, 1, 1, 0,
132  0, 1, 1, 0, 1, 0, 0, 1,
133  1, 0, 0, 1, 0, 1, 1, 0,
134  0, 1, 1, 0, 1, 0, 0, 1,
135  0, 1, 1, 0, 1, 0, 0, 1,
136  1, 0, 0, 1, 0, 1, 1, 0 };
137 
138 struct Screen {
139  /* +1 is used to compensate null character of string */
143  /*
144  * Bitmask of used rows; if a bit is not set, the
145  * corresponding row is not used.
146  * for setting row 1 use row | (1 << 0)
147  * for setting row 15 use row | (1 << 14)
148  */
149  int16_t row_used;
150 };
151 
152 
153 typedef struct CCaptionSubContext {
154  AVClass *class;
155  struct Screen screen[2];
161  AVBPrint buffer;
163  int rollup;
164  enum cc_mode mode;
165  int64_t start_time;
166  /* visible screen time */
167  int64_t startv_time;
168  int64_t end_time;
169  char prev_cmd[2];
170  /* buffer to store pkt data */
173 
174 
176 {
177  int ret;
178  CCaptionSubContext *ctx = avctx->priv_data;
179 
181  /* taking by default roll up to 2 */
182  ctx->mode = CCMODE_ROLLUP_2;
183  ctx->rollup = 2;
184  ret = ff_ass_subtitle_header_default(avctx);
185  if(ret < 0) {
186  return ret;
187  }
188  /* allocate pkt buffer */
189  ctx->pktbuf = av_buffer_alloc(128);
190  if( !ctx->pktbuf) {
191  ret = AVERROR(ENOMEM);
192  }
193  return ret;
194 }
195 
197 {
198  CCaptionSubContext *ctx = avctx->priv_data;
199  av_bprint_finalize( &ctx->buffer, NULL);
200  av_buffer_unref(&ctx->pktbuf);
201  return 0;
202 }
203 
204 /**
205  * @param ctx closed caption context just to print log
206  */
207 static int write_char (CCaptionSubContext *ctx, char *row,uint8_t col, char ch)
208 {
209  if(col < SCREEN_COLUMNS) {
210  row[col] = ch;
211  return 0;
212  }
213  /* We have extra space at end only for null character */
214  else if ( col == SCREEN_COLUMNS && ch == 0) {
215  row[col] = ch;
216  return 0;
217  }
218  else {
219  av_log(ctx, AV_LOG_WARNING,"Data Ignored since exceeding screen width\n");
220  return AVERROR_INVALIDDATA;
221  }
222 }
223 
224 /**
225  * This function after validating parity bit, also remove it from data pair.
226  * The first byte doesn't pass parity, we replace it with a solid blank
227  * and process the pair.
228  * If the second byte doesn't pass parity, it returns INVALIDDATA
229  * user can ignore the whole pair and pass the other pair.
230  */
231 static int validate_cc_data_pair (uint8_t *cc_data_pair)
232 {
233  uint8_t cc_valid = (*cc_data_pair & 4) >>2;
234  uint8_t cc_type = *cc_data_pair & 3;
235 
236  if (!cc_valid)
237  return AVERROR_INVALIDDATA;
238 
239  // if EIA-608 data then verify parity.
240  if (cc_type==0 || cc_type==1) {
241  if (!parity_table[cc_data_pair[2]]) {
242  return AVERROR_INVALIDDATA;
243  }
244  if (!parity_table[cc_data_pair[1]]) {
245  cc_data_pair[1]=0x7F;
246  }
247  }
248 
249  //Skip non-data
250  if( (cc_data_pair[0] == 0xFA || cc_data_pair[0] == 0xFC || cc_data_pair[0] == 0xFD )
251  && (cc_data_pair[1] & 0x7F) == 0 && (cc_data_pair[2] & 0x7F) == 0)
252  return AVERROR_PATCHWELCOME;
253 
254  //skip 708 data
255  if(cc_type == 3 || cc_type == 2 )
256  return AVERROR_PATCHWELCOME;
257 
258  /* remove parity bit */
259  cc_data_pair[1] &= 0x7F;
260  cc_data_pair[2] &= 0x7F;
261 
262 
263  return 0;
264 
265 }
266 
268 {
269  switch (ctx->mode) {
270  case CCMODE_POPON:
271  // use Inactive screen
272  return ctx->screen + !ctx->active_screen;
273  case CCMODE_PAINTON:
274  case CCMODE_ROLLUP_2:
275  case CCMODE_ROLLUP_3:
276  case CCMODE_ROLLUP_4:
277  case CCMODE_TEXT:
278  // use active screen
279  return ctx->screen + ctx->active_screen;
280  }
281  /* It was never an option */
282  return NULL;
283 }
284 
285 static void roll_up(CCaptionSubContext *ctx)
286 {
287  struct Screen *screen;
288  int i, keep_lines;
289 
290  if(ctx->mode == CCMODE_TEXT)
291  return;
292 
293  screen = get_writing_screen(ctx);
294 
295  /* +1 signify cursor_row starts from 0
296  * Can't keep lines less then row cursor pos
297  */
298  keep_lines = FFMIN(ctx->cursor_row + 1, ctx->rollup);
299 
300  for( i = 0; i < ctx->cursor_row - keep_lines; i++ )
301  UNSET_FLAG(screen->row_used, i);
302 
303 
304  for( i = 0; i < keep_lines && screen->row_used; i++ ) {
305  const int i_row = ctx->cursor_row - keep_lines + i + 1;
306 
307  memcpy( screen->characters[i_row], screen->characters[i_row+1], SCREEN_COLUMNS );
308  memcpy( screen->colors[i_row], screen->colors[i_row+1], SCREEN_COLUMNS);
309  memcpy( screen->fonts[i_row], screen->fonts[i_row+1], SCREEN_COLUMNS);
310  if(CHECK_FLAG(screen->row_used, i_row + 1))
311  SET_FLAG(screen->row_used, i_row);
312 
313  }
314  UNSET_FLAG(screen->row_used, ctx->cursor_row);
315 
316 }
317 
318 static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
319 {
320  int i;
321  int ret = 0;
322  struct Screen *screen = ctx->screen + ctx->active_screen;
323  ctx->start_time = ctx->startv_time;
324 
325  for( i = 0; screen->row_used && i < SCREEN_ROWS; i++)
326  {
327  if(CHECK_FLAG(screen->row_used,i)) {
328  char *str = screen->characters[i];
329  /* skip space */
330  while (*str == ' ')
331  str++;
332 
333  av_bprintf(&ctx->buffer, "%s\\N", str);
334  ret = av_bprint_is_complete(&ctx->buffer);
335  if( ret == 0) {
336  ret = AVERROR(ENOMEM);
337  break;
338  }
339  }
340 
341  }
342  if(screen->row_used && ctx->buffer.len >= 2 ) {
343  ctx->buffer.len -= 2;
344  ctx->buffer.str[ctx->buffer.len] = 0;
345  }
346  ctx->startv_time = pts;
347  ctx->end_time = pts;
348  return ret;
349 }
350 
352 {
353  int i = lo - 0x20;
354  int ret;
355  struct Screen *screen = get_writing_screen(ctx);
356  char *row = screen->characters[ctx->cursor_row];
357 
358  if( i >= 32)
359  return;
360 
361  ctx->cursor_color = pac2_attribs[i][0];
362  ctx->cursor_font = pac2_attribs[i][1];
363 
364  SET_FLAG(screen->row_used,ctx->cursor_row);
365  ret = write_char(ctx, row, ctx->cursor_column, ' ');
366  if(ret == 0)
367  ctx->cursor_column++;
368 }
369 
370 static void handle_pac( CCaptionSubContext *ctx, uint8_t hi, uint8_t lo )
371 {
372  static const int8_t row_map[] = {
373  11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
374  };
375  const int index = ( (hi<<1) & 0x0e) | ( (lo>>5) & 0x01 );
376  struct Screen *screen = get_writing_screen(ctx);
377  char *row;
378  int indent,i,ret;
379 
380  if( row_map[index] <= 0 ) {
381  av_log(ctx, AV_LOG_DEBUG,"Invalid pac index encountered\n");
382  return;
383  }
384 
385  lo &= 0x1f;
386 
387  ctx->cursor_row = row_map[index] - 1;
388  ctx->cursor_color = pac2_attribs[lo][0];
389  ctx->cursor_font = pac2_attribs[lo][1];
390  ctx->cursor_column = 0;
391  indent = pac2_attribs[lo][2];
392  row = screen->characters[ctx->cursor_row];
393  for(i = 0;i < indent; i++) {
394  ret = write_char(ctx, row, ctx->cursor_column, ' ');
395  if( ret == 0 )
396  ctx->cursor_column++;
397  }
398 
399 }
400 
401 /**
402  * @param pts it is required to set end time
403  */
404 static int handle_edm(CCaptionSubContext *ctx,int64_t pts)
405 {
406  int ret = 0;
407  struct Screen *screen = ctx->screen + ctx->active_screen;
408 
409  reap_screen(ctx, pts);
410  screen->row_used = 0;
411  ctx->screen_changed = 1;
412  return ret;
413 }
414 
415 static int handle_eoc(CCaptionSubContext *ctx, int64_t pts)
416 {
417  int ret;
418  ret = handle_edm(ctx,pts);
419  ctx->active_screen = !ctx->active_screen;
420  ctx->cursor_column = 0;
421  return ret;
422 }
423 
424 static void handle_delete_end_of_row( CCaptionSubContext *ctx, char hi, char lo)
425 {
426  struct Screen *screen = get_writing_screen(ctx);
427  char *row = screen->characters[ctx->cursor_row];
428  write_char(ctx, row, ctx->cursor_column, 0);
429 
430 }
431 
432 static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
433 {
434  struct Screen *screen = get_writing_screen(ctx);
435  char *row = screen->characters[ctx->cursor_row];
436  int ret;
437 
438  SET_FLAG(screen->row_used,ctx->cursor_row);
439 
440  ret = write_char(ctx, row, ctx->cursor_column, hi);
441  if( ret == 0 )
442  ctx->cursor_column++;
443 
444  if(lo) {
445  ret = write_char(ctx, row, ctx->cursor_column, lo);
446  if ( ret == 0 )
447  ctx->cursor_column++;
448  }
449  write_char(ctx, row, ctx->cursor_column, 0);
450 
451  /* reset prev command since character can repeat */
452  ctx->prev_cmd[0] = 0;
453  ctx->prev_cmd[1] = 0;
454  if (lo)
455  ff_dlog(ctx, "(%c,%c)\n",hi,lo);
456  else
457  ff_dlog(ctx, "(%c)\n",hi);
458 }
459 
460 static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
461 {
462  int ret = 0;
463 #define COR3(var, with1, with2, with3) ( (var) == (with1) || (var) == (with2) || (var) == (with3) )
464  if ( hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) {
465  /* ignore redundant command */
466  } else if ( (hi == 0x10 && (lo >= 0x40 || lo <= 0x5f)) ||
467  ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
468  handle_pac(ctx, hi, lo);
469  } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
470  ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
471  handle_textattr(ctx, hi, lo);
472  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x20 ) {
473  /* resume caption loading */
474  ctx->mode = CCMODE_POPON;
475  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x24 ) {
476  handle_delete_end_of_row(ctx, hi, lo);
477  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x25 ) {
478  ctx->rollup = 2;
479  ctx->mode = CCMODE_ROLLUP_2;
480  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x26 ) {
481  ctx->rollup = 3;
482  ctx->mode = CCMODE_ROLLUP_3;
483  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x27 ) {
484  ctx->rollup = 4;
485  ctx->mode = CCMODE_ROLLUP_4;
486  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x29 ) {
487  /* resume direct captioning */
488  ctx->mode = CCMODE_PAINTON;
489  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2B ) {
490  /* resume text display */
491  ctx->mode = CCMODE_TEXT;
492  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2C ) {
493  /* erase display memory */
494  ret = handle_edm(ctx, pts);
495  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2D ) {
496  /* carriage return */
497  ff_dlog(ctx, "carriage return\n");
498  reap_screen(ctx, pts);
499  roll_up(ctx);
500  ctx->screen_changed = 1;
501  ctx->cursor_column = 0;
502  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2F ) {
503  /* end of caption */
504  ff_dlog(ctx, "handle_eoc\n");
505  ret = handle_eoc(ctx, pts);
506  } else if (hi>=0x20) {
507  /* Standard characters (always in pairs) */
508  handle_char(ctx, hi, lo, pts);
509  } else {
510  /* Ignoring all other non data code */
511  ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
512  }
513 
514  /* set prev command */
515  ctx->prev_cmd[0] = hi;
516  ctx->prev_cmd[1] = lo;
517 
518 #undef COR3
519  return ret;
520 
521 }
522 
523 static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
524 {
525  CCaptionSubContext *ctx = avctx->priv_data;
526  AVSubtitle *sub = data;
527  uint8_t *bptr = NULL;
528  int len = avpkt->size;
529  int ret = 0;
530  int i;
531 
532  if ( ctx->pktbuf->size < len) {
533  ret = av_buffer_realloc(&ctx->pktbuf, len);
534  if(ret < 0) {
535  av_log(ctx, AV_LOG_WARNING, "Insufficient Memory of %d truncated to %d\n",len, ctx->pktbuf->size);
536  len = ctx->pktbuf->size;
537  ret = 0;
538  }
539  }
540  memcpy(ctx->pktbuf->data, avpkt->data, len);
541  bptr = ctx->pktbuf->data;
542 
543 
544  for (i = 0; i < len; i += 3) {
545  uint8_t cc_type = *(bptr + i) & 3;
546  if (validate_cc_data_pair( bptr + i) )
547  continue;
548  /* ignoring data field 1 */
549  if(cc_type == 1)
550  continue;
551  else
552  process_cc608(ctx, avpkt->pts, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
553  if(ctx->screen_changed && *ctx->buffer.str)
554  {
555  int start_time = av_rescale_q(ctx->start_time, avctx->time_base, (AVRational){ 1, 100 });
556  int end_time = av_rescale_q(ctx->end_time, avctx->time_base, (AVRational){ 1, 100 });
557  ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str);
558  ret = ff_ass_add_rect_bprint(sub, &ctx->buffer, start_time, end_time - start_time);
559  if (ret < 0)
560  return ret;
561  sub->pts = av_rescale_q(ctx->start_time, avctx->time_base, AV_TIME_BASE_Q);
562  ctx->screen_changed = 0;
563  av_bprint_clear(&ctx->buffer);
564  }
565  }
566 
567  *got_sub = sub->num_rects > 0;
568  return ret;
569 }
570 
571 static const AVOption options[] = {
572  {NULL}
573 };
574 
575 static const AVClass ccaption_dec_class = {
576  .class_name = "Closed caption Decoder",
577  .item_name = av_default_item_name,
578  .option = options,
579  .version = LIBAVUTIL_VERSION_INT,
580 };
581 
583  .name = "cc_dec",
584  .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 / CEA-708) Decoder"),
585  .type = AVMEDIA_TYPE_SUBTITLE,
586  .id = AV_CODEC_ID_EIA_608,
587  .priv_data_size = sizeof(CCaptionSubContext),
588  .init = init_decoder,
589  .close = close_decoder,
590  .decode = decode,
591  .priv_class = &ccaption_dec_class,
592 };
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:124
AVOption.
Definition: opt.h:255
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
enum cc_mode mode
Definition: ccaption_dec.c:164
static void handle_pac(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:370
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:62
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1424
static struct Screen * get_writing_screen(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:267
uint8_t colors[SCREEN_ROWS][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:141
static void handle_delete_end_of_row(CCaptionSubContext *ctx, char hi, char lo)
Definition: ccaption_dec.c:424
AVCodec.
Definition: avcodec.h:3472
static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
Definition: ccaption_dec.c:432
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
#define CHECK_FLAG(var, val)
Definition: ccaption_dec.c:32
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1631
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
static int write_char(CCaptionSubContext *ctx, char *row, uint8_t col, char ch)
Definition: ccaption_dec.c:207
static int64_t start_time
Definition: ffplay.c:325
uint8_t
#define av_cold
Definition: attributes.h:74
static int handle_edm(CCaptionSubContext *ctx, int64_t pts)
Definition: ccaption_dec.c:404
AVOptions.
cc_mode
Definition: ccaption_dec.c:38
int ff_ass_subtitle_header_default(AVCodecContext *avctx)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS with default style.
Definition: ass.c:80
uint8_t * data
Definition: avcodec.h:1423
#define ff_dlog(a,...)
static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
Definition: ccaption_dec.c:318
#define av_log(a,...)
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:140
#define SCREEN_ROWS
Definition: ccaption_dec.c:27
#define AV_BPRINT_SIZE_UNLIMITED
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define COR3(var, with1, with2, with3)
const char * name
Name of the codec implementation.
Definition: avcodec.h:3479
AVCodec ff_ccaption_decoder
Definition: ccaption_dec.c:582
int av_buffer_realloc(AVBufferRef **pbuf, int size)
Reallocate a given buffer.
Definition: buffer.c:168
Libavcodec external API header.
uint8_t fonts[SCREEN_ROWS][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:142
int16_t row_used
Definition: ccaption_dec.c:149
int64_t pts
Same as packet pts, in AV_TIME_BASE.
Definition: avcodec.h:3805
common internal API header
static SDL_Surface * screen
Definition: ffplay.c:360
#define SET_FLAG(var, val)
Definition: ccaption_dec.c:30
static av_cold int init_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:175
#define SCREEN_COLUMNS
Definition: ccaption_dec.c:28
#define FFMIN(a, b)
Definition: common.h:81
static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:460
AVBufferRef * pktbuf
Definition: ccaption_dec.c:171
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
static int handle_eoc(CCaptionSubContext *ctx, int64_t pts)
Definition: ccaption_dec.c:415
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:252
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:66
static const unsigned char pac2_attribs[32][3]
Definition: ccaption_dec.c:67
int ff_ass_add_rect_bprint(AVSubtitle *sub, AVBPrint *buf, int ts_start, int duration)
Same as ff_ass_add_rect_bprint, but taking an AVBPrint buffer instead of a string, and assuming raw=0.
Definition: ass.c:178
main external API structure.
Definition: avcodec.h:1502
uint8_t * data
The data buffer.
Definition: buffer.h:89
uint8_t characters[SCREEN_ROWS][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:140
Describe the class of an AVClass context structure.
Definition: log.h:67
int index
Definition: gxfenc.c:89
rational number numerator/denominator
Definition: rational.h:43
int size
Size of data in bytes.
Definition: buffer.h:93
static int64_t pts
Global timestamp for the audio frames.
static const AVClass ccaption_dec_class
Definition: ccaption_dec.c:575
cc_font
Definition: ccaption_dec.c:60
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
static void roll_up(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:285
static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
Definition: ccaption_dec.c:523
A reference to a data buffer.
Definition: buffer.h:81
static const AVOption options[]
Definition: ccaption_dec.c:571
#define UNSET_FLAG(var, val)
Definition: ccaption_dec.c:31
cc_color_code
Definition: ccaption_dec.c:47
void * priv_data
Definition: avcodec.h:1544
int len
static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:351
static av_cold int close_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:196
static const uint8_t parity_table[256]
Definition: ccaption_dec.c:105
static int validate_cc_data_pair(uint8_t *cc_data_pair)
This function after validating parity bit, also remove it from data pair.
Definition: ccaption_dec.c:231
This structure stores compressed data.
Definition: avcodec.h:1400
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1416
struct Screen screen[2]
Definition: ccaption_dec.c:155