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