FFmpeg  2.8.17
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules 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 */
174 
175 
177 {
178  int ret;
179  CCaptionSubContext *ctx = avctx->priv_data;
180 
182  /* taking by default roll up to 2 */
183  ctx->mode = CCMODE_ROLLUP_2;
184  ctx->rollup = 2;
185  ret = ff_ass_subtitle_header_default(avctx);
186  if(ret < 0) {
187  return ret;
188  }
189 
190  return ret;
191 }
192 
194 {
195  CCaptionSubContext *ctx = avctx->priv_data;
196  av_bprint_finalize( &ctx->buffer, NULL);
197  av_freep(&ctx->pktbuf);
198  ctx->pktbuf_size = 0;
199  return 0;
200 }
201 
202 /**
203  * @param ctx closed caption context just to print log
204  */
205 static int write_char (CCaptionSubContext *ctx, char *row,uint8_t col, char ch)
206 {
207  if(col < SCREEN_COLUMNS) {
208  row[col] = ch;
209  return 0;
210  }
211  /* We have extra space at end only for null character */
212  else if ( col == SCREEN_COLUMNS && ch == 0) {
213  row[col] = ch;
214  return 0;
215  }
216  else {
217  av_log(ctx, AV_LOG_WARNING,"Data Ignored since exceeding screen width\n");
218  return AVERROR_INVALIDDATA;
219  }
220 }
221 
222 /**
223  * This function after validating parity bit, also remove it from data pair.
224  * The first byte doesn't pass parity, we replace it with a solid blank
225  * and process the pair.
226  * If the second byte doesn't pass parity, it returns INVALIDDATA
227  * user can ignore the whole pair and pass the other pair.
228  */
229 static int validate_cc_data_pair (uint8_t *cc_data_pair)
230 {
231  uint8_t cc_valid = (*cc_data_pair & 4) >>2;
232  uint8_t cc_type = *cc_data_pair & 3;
233 
234  if (!cc_valid)
235  return AVERROR_INVALIDDATA;
236 
237  // if EIA-608 data then verify parity.
238  if (cc_type==0 || cc_type==1) {
239  if (!parity_table[cc_data_pair[2]]) {
240  return AVERROR_INVALIDDATA;
241  }
242  if (!parity_table[cc_data_pair[1]]) {
243  cc_data_pair[1]=0x7F;
244  }
245  }
246 
247  //Skip non-data
248  if( (cc_data_pair[0] == 0xFA || cc_data_pair[0] == 0xFC || cc_data_pair[0] == 0xFD )
249  && (cc_data_pair[1] & 0x7F) == 0 && (cc_data_pair[2] & 0x7F) == 0)
250  return AVERROR_PATCHWELCOME;
251 
252  //skip 708 data
253  if(cc_type == 3 || cc_type == 2 )
254  return AVERROR_PATCHWELCOME;
255 
256  /* remove parity bit */
257  cc_data_pair[1] &= 0x7F;
258  cc_data_pair[2] &= 0x7F;
259 
260 
261  return 0;
262 
263 }
264 
266 {
267  switch (ctx->mode) {
268  case CCMODE_POPON:
269  // use Inactive screen
270  return ctx->screen + !ctx->active_screen;
271  case CCMODE_PAINTON:
272  case CCMODE_ROLLUP_2:
273  case CCMODE_ROLLUP_3:
274  case CCMODE_ROLLUP_4:
275  case CCMODE_TEXT:
276  // use active screen
277  return ctx->screen + ctx->active_screen;
278  }
279  /* It was never an option */
280  return NULL;
281 }
282 
283 static void roll_up(CCaptionSubContext *ctx)
284 {
285  struct Screen *screen;
286  int i, keep_lines;
287 
288  if(ctx->mode == CCMODE_TEXT)
289  return;
290 
291  screen = get_writing_screen(ctx);
292 
293  /* +1 signify cursor_row starts from 0
294  * Can't keep lines less then row cursor pos
295  */
296  keep_lines = FFMIN(ctx->cursor_row + 1, ctx->rollup);
297 
298  for( i = 0; i < ctx->cursor_row - keep_lines; i++ )
299  UNSET_FLAG(screen->row_used, i);
300 
301 
302  for( i = 0; i < keep_lines && screen->row_used; i++ ) {
303  const int i_row = ctx->cursor_row - keep_lines + i + 1;
304 
305  memcpy( screen->characters[i_row], screen->characters[i_row+1], SCREEN_COLUMNS );
306  memcpy( screen->colors[i_row], screen->colors[i_row+1], SCREEN_COLUMNS);
307  memcpy( screen->fonts[i_row], screen->fonts[i_row+1], SCREEN_COLUMNS);
308  if(CHECK_FLAG(screen->row_used, i_row + 1))
309  SET_FLAG(screen->row_used, i_row);
310 
311  }
312  UNSET_FLAG(screen->row_used, ctx->cursor_row);
313 
314 }
315 
316 static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
317 {
318  int i;
319  int ret = 0;
320  struct Screen *screen = ctx->screen + ctx->active_screen;
321  ctx->start_time = ctx->startv_time;
322 
323  for( i = 0; screen->row_used && i < SCREEN_ROWS; i++)
324  {
325  if(CHECK_FLAG(screen->row_used,i)) {
326  char *str = screen->characters[i];
327  /* skip space */
328  while (*str == ' ')
329  str++;
330 
331  av_bprintf(&ctx->buffer, "%s\\N", str);
332  ret = av_bprint_is_complete(&ctx->buffer);
333  if( ret == 0) {
334  ret = AVERROR(ENOMEM);
335  break;
336  }
337  }
338 
339  }
340  if(screen->row_used && ctx->buffer.len >= 2 ) {
341  ctx->buffer.len -= 2;
342  ctx->buffer.str[ctx->buffer.len] = 0;
343  }
344  ctx->startv_time = pts;
345  ctx->end_time = pts;
346  return ret;
347 }
348 
350 {
351  int i = lo - 0x20;
352  int ret;
353  struct Screen *screen = get_writing_screen(ctx);
354  char *row = screen->characters[ctx->cursor_row];
355 
356  if( i >= 32)
357  return;
358 
359  ctx->cursor_color = pac2_attribs[i][0];
360  ctx->cursor_font = pac2_attribs[i][1];
361 
362  SET_FLAG(screen->row_used,ctx->cursor_row);
363  ret = write_char(ctx, row, ctx->cursor_column, ' ');
364  if(ret == 0)
365  ctx->cursor_column++;
366 }
367 
368 static void handle_pac( CCaptionSubContext *ctx, uint8_t hi, uint8_t lo )
369 {
370  static const int8_t row_map[] = {
371  11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
372  };
373  const int index = ( (hi<<1) & 0x0e) | ( (lo>>5) & 0x01 );
374  struct Screen *screen = get_writing_screen(ctx);
375  char *row;
376  int indent,i,ret;
377 
378  if( row_map[index] <= 0 ) {
379  av_log(ctx, AV_LOG_DEBUG,"Invalid pac index encountered\n");
380  return;
381  }
382 
383  lo &= 0x1f;
384 
385  ctx->cursor_row = row_map[index] - 1;
386  ctx->cursor_color = pac2_attribs[lo][0];
387  ctx->cursor_font = pac2_attribs[lo][1];
388  ctx->cursor_column = 0;
389  indent = pac2_attribs[lo][2];
390  row = screen->characters[ctx->cursor_row];
391  for(i = 0;i < indent; i++) {
392  ret = write_char(ctx, row, ctx->cursor_column, ' ');
393  if( ret == 0 )
394  ctx->cursor_column++;
395  }
396 
397 }
398 
399 /**
400  * @param pts it is required to set end time
401  */
402 static int handle_edm(CCaptionSubContext *ctx,int64_t pts)
403 {
404  int ret = 0;
405  struct Screen *screen = ctx->screen + ctx->active_screen;
406 
407  reap_screen(ctx, pts);
408  screen->row_used = 0;
409  ctx->screen_changed = 1;
410  return ret;
411 }
412 
413 static int handle_eoc(CCaptionSubContext *ctx, int64_t pts)
414 {
415  int ret;
416  ret = handle_edm(ctx,pts);
417  ctx->active_screen = !ctx->active_screen;
418  ctx->cursor_column = 0;
419  return ret;
420 }
421 
422 static void handle_delete_end_of_row( CCaptionSubContext *ctx, char hi, char lo)
423 {
424  struct Screen *screen = get_writing_screen(ctx);
425  char *row = screen->characters[ctx->cursor_row];
426  write_char(ctx, row, ctx->cursor_column, 0);
427 
428 }
429 
430 static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
431 {
432  struct Screen *screen = get_writing_screen(ctx);
433  char *row = screen->characters[ctx->cursor_row];
434  int ret;
435 
436  SET_FLAG(screen->row_used,ctx->cursor_row);
437 
438  ret = write_char(ctx, row, ctx->cursor_column, hi);
439  if( ret == 0 )
440  ctx->cursor_column++;
441 
442  if(lo) {
443  ret = write_char(ctx, row, ctx->cursor_column, lo);
444  if ( ret == 0 )
445  ctx->cursor_column++;
446  }
447  write_char(ctx, row, ctx->cursor_column, 0);
448 
449  /* reset prev command since character can repeat */
450  ctx->prev_cmd[0] = 0;
451  ctx->prev_cmd[1] = 0;
452  if (lo)
453  ff_dlog(ctx, "(%c,%c)\n",hi,lo);
454  else
455  ff_dlog(ctx, "(%c)\n",hi);
456 }
457 
458 static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
459 {
460  int ret = 0;
461 #define COR3(var, with1, with2, with3) ( (var) == (with1) || (var) == (with2) || (var) == (with3) )
462  if ( hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) {
463  /* ignore redundant command */
464  } else if ( (hi == 0x10 && (lo >= 0x40 || lo <= 0x5f)) ||
465  ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
466  handle_pac(ctx, hi, lo);
467  } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
468  ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
469  handle_textattr(ctx, hi, lo);
470  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x20 ) {
471  /* resume caption loading */
472  ctx->mode = CCMODE_POPON;
473  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x24 ) {
474  handle_delete_end_of_row(ctx, hi, lo);
475  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x25 ) {
476  ctx->rollup = 2;
477  ctx->mode = CCMODE_ROLLUP_2;
478  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x26 ) {
479  ctx->rollup = 3;
480  ctx->mode = CCMODE_ROLLUP_3;
481  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x27 ) {
482  ctx->rollup = 4;
483  ctx->mode = CCMODE_ROLLUP_4;
484  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x29 ) {
485  /* resume direct captioning */
486  ctx->mode = CCMODE_PAINTON;
487  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2B ) {
488  /* resume text display */
489  ctx->mode = CCMODE_TEXT;
490  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2C ) {
491  /* erase display memory */
492  ret = handle_edm(ctx, pts);
493  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2D ) {
494  /* carriage return */
495  ff_dlog(ctx, "carriage return\n");
496  reap_screen(ctx, pts);
497  roll_up(ctx);
498  ctx->screen_changed = 1;
499  ctx->cursor_column = 0;
500  } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2F ) {
501  /* end of caption */
502  ff_dlog(ctx, "handle_eoc\n");
503  ret = handle_eoc(ctx, pts);
504  } else if (hi>=0x20) {
505  /* Standard characters (always in pairs) */
506  handle_char(ctx, hi, lo, pts);
507  } else {
508  /* Ignoring all other non data code */
509  ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
510  }
511 
512  /* set prev command */
513  ctx->prev_cmd[0] = hi;
514  ctx->prev_cmd[1] = lo;
515 
516 #undef COR3
517  return ret;
518 
519 }
520 
521 static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
522 {
523  CCaptionSubContext *ctx = avctx->priv_data;
524  AVSubtitle *sub = data;
525  uint8_t *bptr = NULL;
526  int len = avpkt->size;
527  int ret = 0;
528  int i;
529 
530  av_fast_padded_malloc(&ctx->pktbuf, &ctx->pktbuf_size, len);
531  if (!ctx->pktbuf) {
532  av_log(ctx, AV_LOG_WARNING, "Insufficient Memory of %d truncated to %d\n", len, ctx->pktbuf_size);
533  return AVERROR(ENOMEM);
534  }
535  memcpy(ctx->pktbuf, avpkt->data, len);
536  bptr = ctx->pktbuf;
537 
538 
539  for (i = 0; i < len; i += 3) {
540  uint8_t cc_type = *(bptr + i) & 3;
541  if (validate_cc_data_pair( bptr + i) )
542  continue;
543  /* ignoring data field 1 */
544  if(cc_type == 1)
545  continue;
546  else
547  process_cc608(ctx, avpkt->pts, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
548  if(ctx->screen_changed && *ctx->buffer.str)
549  {
550  int start_time = av_rescale_q(ctx->start_time, avctx->time_base, (AVRational){ 1, 100 });
551  int end_time = av_rescale_q(ctx->end_time, avctx->time_base, (AVRational){ 1, 100 });
552  ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str);
553  ret = ff_ass_add_rect_bprint(sub, &ctx->buffer, start_time, end_time - start_time);
554  if (ret < 0)
555  return ret;
556  sub->pts = av_rescale_q(ctx->start_time, avctx->time_base, AV_TIME_BASE_Q);
557  ctx->screen_changed = 0;
558  av_bprint_clear(&ctx->buffer);
559  }
560  }
561 
562  *got_sub = sub->num_rects > 0;
563  return ret;
564 }
565 
566 static const AVOption options[] = {
567  {NULL}
568 };
569 
570 static const AVClass ccaption_dec_class = {
571  .class_name = "Closed caption Decoder",
572  .item_name = av_default_item_name,
573  .option = options,
574  .version = LIBAVUTIL_VERSION_INT,
575 };
576 
578  .name = "cc_dec",
579  .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 / CEA-708) Decoder"),
580  .type = AVMEDIA_TYPE_SUBTITLE,
581  .id = AV_CODEC_ID_EIA_608,
582  .priv_data_size = sizeof(CCaptionSubContext),
583  .init = init_decoder,
584  .close = close_decoder,
585  .decode = decode,
586  .priv_class = &ccaption_dec_class,
587 };
#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
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:368
#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:1434
unsigned num_rects
Definition: avcodec.h:3813
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition: utils.c:126
static struct Screen * get_writing_screen(CCaptionSubContext *ctx)
Definition: ccaption_dec.c:265
static void handle_delete_end_of_row(CCaptionSubContext *ctx, char hi, char lo)
Definition: ccaption_dec.c:422
AVCodec.
Definition: avcodec.h:3482
static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
Definition: ccaption_dec.c:430
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:1641
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:205
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:402
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:1433
#define ff_dlog(a,...)
static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
Definition: ccaption_dec.c:316
#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:147
#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:178
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:3489
AVCodec ff_ccaption_decoder
Definition: ccaption_dec.c:577
Libavcodec external API header.
int16_t row_used
Definition: ccaption_dec.c:149
int64_t pts
Same as packet pts, in AV_TIME_BASE.
Definition: avcodec.h:3815
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:176
#define SCREEN_COLUMNS
Definition: ccaption_dec.c:28
#define FFMIN(a, b)
Definition: common.h:92
static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:458
uint8_t characters[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:140
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:413
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
uint8_t fonts[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:142
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:252
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:1512
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
static int64_t pts
Global timestamp for the audio frames.
static const AVClass ccaption_dec_class
Definition: ccaption_dec.c:570
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:283
static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
Definition: ccaption_dec.c:521
static const AVOption options[]
Definition: ccaption_dec.c:566
#define UNSET_FLAG(var, val)
Definition: ccaption_dec.c:31
cc_color_code
Definition: ccaption_dec.c:47
void * priv_data
Definition: avcodec.h:1554
int len
static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
Definition: ccaption_dec.c:349
#define av_freep(p)
static av_cold int close_decoder(AVCodecContext *avctx)
Definition: ccaption_dec.c:193
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:229
This structure stores compressed data.
Definition: avcodec.h:1410
uint8_t colors[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
Definition: ccaption_dec.c:141
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1426
struct Screen screen[2]
Definition: ccaption_dec.c:155