FFmpeg
dvdsubdec.c
Go to the documentation of this file.
1 /*
2  * DVD subtitle decoding
3  * Copyright (c) 2005 Fabrice Bellard
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 "codec_internal.h"
24 #include "get_bits.h"
25 #include "internal.h"
26 
27 #include "libavutil/attributes.h"
28 #include "libavutil/colorspace.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/imgutils.h"
31 #include "libavutil/bswap.h"
32 
33 typedef struct DVDSubContext
34 {
35  AVClass *class;
36  uint32_t palette[16];
37  char *palette_str;
38  char *ifo_str;
40  uint8_t colormap[4];
41  uint8_t alpha[256];
42  uint8_t buf[0x10000];
43  int buf_size;
45  uint8_t used_color[256];
46 #ifdef DEBUG
47  int sub_id;
48 #endif
50 
51 static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values)
52 {
53  const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
54  uint8_t r, g, b;
55  int i, y, cb, cr;
56  int r_add, g_add, b_add;
57 
58  for (i = num_values; i > 0; i--) {
59  y = *ycbcr++;
60  cr = *ycbcr++;
61  cb = *ycbcr++;
63  YUV_TO_RGB2_CCIR(r, g, b, y);
64  *rgba++ = ((unsigned)*alpha++ << 24) | (r << 16) | (g << 8) | b;
65  }
66 }
67 
68 static int decode_run_2bit(GetBitContext *gb, int *color)
69 {
70  unsigned int v, t;
71 
72  v = 0;
73  for (t = 1; v < t && t <= 0x40; t <<= 2)
74  v = (v << 4) | get_bits(gb, 4);
75  *color = v & 3;
76  if (v < 4) { /* Code for fill rest of line */
77  return INT_MAX;
78  }
79  return v >> 2;
80 }
81 
82 static int decode_run_8bit(GetBitContext *gb, int *color)
83 {
84  int len;
85  int has_run = get_bits1(gb);
86  *color = get_bits(gb, 2 + 6*get_bits1(gb));
87  if (has_run) {
88  if (get_bits1(gb)) {
89  len = get_bits(gb, 7);
90  if (len == 0)
91  len = INT_MAX;
92  else
93  len += 9;
94  } else
95  len = get_bits(gb, 3) + 2;
96  } else
97  len = 1;
98  return len;
99 }
100 
101 static int decode_rle(uint8_t *bitmap, int linesize, int w, int h, uint8_t used_color[256],
102  const uint8_t *buf, int start, int buf_size, int is_8bit)
103 {
104  GetBitContext gb;
105  int bit_len;
106  int x, y, len, color;
107  uint8_t *d;
108 
109  if (start >= buf_size)
110  return -1;
111 
112  if (w <= 0 || h <= 0)
113  return -1;
114 
115  bit_len = (buf_size - start) * 8;
116  init_get_bits(&gb, buf + start, bit_len);
117 
118  x = 0;
119  y = 0;
120  d = bitmap;
121  for(;;) {
122  if (get_bits_count(&gb) > bit_len)
123  return -1;
124  if (is_8bit)
125  len = decode_run_8bit(&gb, &color);
126  else
127  len = decode_run_2bit(&gb, &color);
128  if (len != INT_MAX && len > w - x)
129  return AVERROR_INVALIDDATA;
130  len = FFMIN(len, w - x);
131  memset(d + x, color, len);
132  used_color[color] = 1;
133  x += len;
134  if (x >= w) {
135  y++;
136  if (y >= h)
137  break;
138  d += linesize;
139  x = 0;
140  /* byte align */
141  align_get_bits(&gb);
142  }
143  }
144  return 0;
145 }
146 
148  uint32_t *rgba_palette,
149  uint32_t subtitle_color)
150 {
151  static const uint8_t level_map[4][4] = {
152  // this configuration (full range, lowest to highest) in tests
153  // seemed most common, so assume this
154  {0xff},
155  {0x00, 0xff},
156  {0x00, 0x80, 0xff},
157  {0x00, 0x55, 0xaa, 0xff},
158  };
159  uint8_t color_used[16] = { 0 };
160  int nb_opaque_colors, i, level, j, r, g, b;
161  uint8_t *colormap = ctx->colormap, *alpha = ctx->alpha;
162 
163  if(ctx->has_palette) {
164  for(i = 0; i < 4; i++)
165  rgba_palette[i] = (ctx->palette[colormap[i]] & 0x00ffffff)
166  | ((alpha[i] * 17U) << 24);
167  return;
168  }
169 
170  for(i = 0; i < 4; i++)
171  rgba_palette[i] = 0;
172 
173  nb_opaque_colors = 0;
174  for(i = 0; i < 4; i++) {
175  if (alpha[i] != 0 && !color_used[colormap[i]]) {
176  color_used[colormap[i]] = 1;
177  nb_opaque_colors++;
178  }
179  }
180 
181  if (nb_opaque_colors == 0)
182  return;
183 
184  j = 0;
185  memset(color_used, 0, 16);
186  for(i = 0; i < 4; i++) {
187  if (alpha[i] != 0) {
188  if (!color_used[colormap[i]]) {
189  level = level_map[nb_opaque_colors - 1][j];
190  r = (((subtitle_color >> 16) & 0xff) * level) >> 8;
191  g = (((subtitle_color >> 8) & 0xff) * level) >> 8;
192  b = (((subtitle_color >> 0) & 0xff) * level) >> 8;
193  rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17U) << 24);
194  color_used[colormap[i]] = (i + 1);
195  j++;
196  } else {
197  rgba_palette[i] = (rgba_palette[color_used[colormap[i]] - 1] & 0x00ffffff) |
198  ((alpha[i] * 17U) << 24);
199  }
200  }
201  }
202 }
203 
204 static void reset_rects(AVSubtitle *sub_header)
205 {
206  int i;
207 
208  if (sub_header->rects) {
209  for (i = 0; i < sub_header->num_rects; i++) {
210  av_freep(&sub_header->rects[i]->data[0]);
211  av_freep(&sub_header->rects[i]->data[1]);
212  av_freep(&sub_header->rects[i]);
213  }
214  av_freep(&sub_header->rects);
215  sub_header->num_rects = 0;
216  }
217 }
218 
219 #define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a))
220 
222  const uint8_t *buf, int buf_size)
223 {
224  int cmd_pos, pos, cmd, x1, y1, x2, y2, next_cmd_pos;
225  int big_offsets, offset_size, is_8bit = 0;
226  const uint8_t *yuv_palette = NULL;
227  uint8_t *colormap = ctx->colormap, *alpha = ctx->alpha;
228  int date;
229  int i;
230  int is_menu = 0;
231  uint32_t size;
232  int64_t offset1, offset2;
233 
234  if (buf_size < 10)
235  return -1;
236 
237  if (AV_RB16(buf) == 0) { /* HD subpicture with 4-byte offsets */
238  big_offsets = 1;
239  offset_size = 4;
240  cmd_pos = 6;
241  } else {
242  big_offsets = 0;
243  offset_size = 2;
244  cmd_pos = 2;
245  }
246 
247  size = READ_OFFSET(buf + (big_offsets ? 2 : 0));
248  cmd_pos = READ_OFFSET(buf + cmd_pos);
249 
250  if (cmd_pos < 0 || cmd_pos > buf_size - 2 - offset_size) {
251  if (cmd_pos > size) {
252  av_log(ctx, AV_LOG_ERROR, "Discarding invalid packet\n");
253  return 0;
254  }
255  return AVERROR(EAGAIN);
256  }
257 
258  while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) {
259  date = AV_RB16(buf + cmd_pos);
260  next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2);
261  ff_dlog(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n",
262  cmd_pos, next_cmd_pos, date);
263  pos = cmd_pos + 2 + offset_size;
264  offset1 = -1;
265  offset2 = -1;
266  x1 = y1 = x2 = y2 = 0;
267  while (pos < buf_size) {
268  cmd = buf[pos++];
269  ff_dlog(NULL, "cmd=%02x\n", cmd);
270  switch(cmd) {
271  case 0x00:
272  /* menu subpicture */
273  is_menu = 1;
274  break;
275  case 0x01:
276  /* set start date */
277  sub_header->start_display_time = (date << 10) / 90;
278  break;
279  case 0x02:
280  /* set end date */
281  sub_header->end_display_time = (date << 10) / 90;
282  break;
283  case 0x03:
284  /* set colormap */
285  if ((buf_size - pos) < 2)
286  goto fail;
287  colormap[3] = buf[pos] >> 4;
288  colormap[2] = buf[pos] & 0x0f;
289  colormap[1] = buf[pos + 1] >> 4;
290  colormap[0] = buf[pos + 1] & 0x0f;
291  pos += 2;
292  break;
293  case 0x04:
294  /* set alpha */
295  if ((buf_size - pos) < 2)
296  goto fail;
297  alpha[3] = buf[pos] >> 4;
298  alpha[2] = buf[pos] & 0x0f;
299  alpha[1] = buf[pos + 1] >> 4;
300  alpha[0] = buf[pos + 1] & 0x0f;
301  pos += 2;
302  ff_dlog(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]);
303  break;
304  case 0x05:
305  case 0x85:
306  if ((buf_size - pos) < 6)
307  goto fail;
308  x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4);
309  x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2];
310  y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4);
311  y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5];
312  if (cmd & 0x80)
313  is_8bit = 1;
314  ff_dlog(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2);
315  pos += 6;
316  break;
317  case 0x06:
318  if ((buf_size - pos) < 4)
319  goto fail;
320  offset1 = AV_RB16(buf + pos);
321  offset2 = AV_RB16(buf + pos + 2);
322  ff_dlog(NULL, "offset1=0x%04"PRIx64" offset2=0x%04"PRIx64"\n", offset1, offset2);
323  pos += 4;
324  break;
325  case 0x86:
326  if ((buf_size - pos) < 8)
327  goto fail;
328  offset1 = AV_RB32(buf + pos);
329  offset2 = AV_RB32(buf + pos + 4);
330  ff_dlog(NULL, "offset1=0x%04"PRIx64" offset2=0x%04"PRIx64"\n", offset1, offset2);
331  pos += 8;
332  break;
333 
334  case 0x83:
335  /* HD set palette */
336  if ((buf_size - pos) < 768)
337  goto fail;
338  yuv_palette = buf + pos;
339  pos += 768;
340  break;
341  case 0x84:
342  /* HD set contrast (alpha) */
343  if ((buf_size - pos) < 256)
344  goto fail;
345  for (i = 0; i < 256; i++)
346  alpha[i] = 0xFF - buf[pos+i];
347  pos += 256;
348  break;
349 
350  case 0xff:
351  goto the_end;
352  default:
353  ff_dlog(NULL, "unrecognised subpicture command 0x%x\n", cmd);
354  goto the_end;
355  }
356  }
357  the_end:
358  if (offset1 >= buf_size || offset2 >= buf_size)
359  goto fail;
360 
361  if (offset1 >= 0 && offset2 >= 0) {
362  int w, h;
363  uint8_t *bitmap;
364 
365  /* decode the bitmap */
366  w = x2 - x1 + 1;
367  if (w < 0)
368  w = 0;
369  h = y2 - y1 + 1;
370  if (h < 0)
371  h = 0;
372  if (w > 0 && h > 1) {
373  reset_rects(sub_header);
374  memset(ctx->used_color, 0, sizeof(ctx->used_color));
375  sub_header->rects = av_mallocz(sizeof(*sub_header->rects));
376  if (!sub_header->rects)
377  goto fail;
378  sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect));
379  if (!sub_header->rects[0])
380  goto fail;
381  sub_header->num_rects = 1;
382  bitmap = sub_header->rects[0]->data[0] = av_malloc(w * h);
383  if (!bitmap)
384  goto fail;
385  if (decode_rle(bitmap, w * 2, w, (h + 1) / 2, ctx->used_color,
386  buf, offset1, buf_size, is_8bit) < 0)
387  goto fail;
388  if (decode_rle(bitmap + w, w * 2, w, h / 2, ctx->used_color,
389  buf, offset2, buf_size, is_8bit) < 0)
390  goto fail;
391  sub_header->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE);
392  if (!sub_header->rects[0]->data[1])
393  goto fail;
394  if (is_8bit) {
395  if (!yuv_palette)
396  goto fail;
397  sub_header->rects[0]->nb_colors = 256;
398  yuv_a_to_rgba(yuv_palette, alpha,
399  (uint32_t *)sub_header->rects[0]->data[1],
400  256);
401  } else {
402  sub_header->rects[0]->nb_colors = 4;
403  guess_palette(ctx, (uint32_t*)sub_header->rects[0]->data[1],
404  0xffffff);
405  }
406  sub_header->rects[0]->x = x1;
407  sub_header->rects[0]->y = y1;
408  sub_header->rects[0]->w = w;
409  sub_header->rects[0]->h = h;
410  sub_header->rects[0]->type = SUBTITLE_BITMAP;
411  sub_header->rects[0]->linesize[0] = w;
412  sub_header->rects[0]->flags = is_menu ? AV_SUBTITLE_FLAG_FORCED : 0;
413  }
414  }
415  if (next_cmd_pos < cmd_pos) {
416  av_log(ctx, AV_LOG_ERROR, "Invalid command offset\n");
417  break;
418  }
419  if (next_cmd_pos == cmd_pos)
420  break;
421  cmd_pos = next_cmd_pos;
422  }
423  if (sub_header->num_rects > 0)
424  return is_menu;
425  fail:
426  reset_rects(sub_header);
427  return -1;
428 }
429 
430 static int is_transp(const uint8_t *buf, int pitch, int n,
431  const uint8_t *transp_color)
432 {
433  int i;
434  for(i = 0; i < n; i++) {
435  if (!transp_color[*buf])
436  return 0;
437  buf += pitch;
438  }
439  return 1;
440 }
441 
442 /* return 0 if empty rectangle, 1 if non empty */
444 {
445  uint8_t transp_color[256] = { 0 };
446  int y1, y2, x1, x2, y, w, h, i;
447  uint8_t *bitmap;
448  int transparent = 1;
449 
450  if (s->num_rects == 0 || !s->rects || s->rects[0]->w <= 0 || s->rects[0]->h <= 0)
451  return 0;
452 
453  for(i = 0; i < s->rects[0]->nb_colors; i++) {
454  if ((((uint32_t *)s->rects[0]->data[1])[i] >> 24) == 0) {
455  transp_color[i] = 1;
456  } else if (ctx->used_color[i])
457  transparent = 0;
458  }
459  if (transparent)
460  return 0;
461  y1 = 0;
462  while (y1 < s->rects[0]->h && is_transp(s->rects[0]->data[0] + y1 * s->rects[0]->linesize[0],
463  1, s->rects[0]->w, transp_color))
464  y1++;
465  if (y1 == s->rects[0]->h) {
466  av_freep(&s->rects[0]->data[0]);
467  s->rects[0]->w = s->rects[0]->h = 0;
468  return 0;
469  }
470 
471  y2 = s->rects[0]->h - 1;
472  while (y2 > 0 && is_transp(s->rects[0]->data[0] + y2 * s->rects[0]->linesize[0], 1,
473  s->rects[0]->w, transp_color))
474  y2--;
475  x1 = 0;
476  while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->data[0] + x1, s->rects[0]->linesize[0],
477  s->rects[0]->h, transp_color))
478  x1++;
479  x2 = s->rects[0]->w - 1;
480  while (x2 > 0 && is_transp(s->rects[0]->data[0] + x2, s->rects[0]->linesize[0], s->rects[0]->h,
481  transp_color))
482  x2--;
483  w = x2 - x1 + 1;
484  h = y2 - y1 + 1;
485  bitmap = av_malloc(w * h);
486  if (!bitmap)
487  return 1;
488  for(y = 0; y < h; y++) {
489  memcpy(bitmap + w * y, s->rects[0]->data[0] + x1 + (y1 + y) * s->rects[0]->linesize[0], w);
490  }
491  av_freep(&s->rects[0]->data[0]);
492  s->rects[0]->data[0] = bitmap;
493  s->rects[0]->linesize[0] = w;
494  s->rects[0]->w = w;
495  s->rects[0]->h = h;
496  s->rects[0]->x += x1;
497  s->rects[0]->y += y1;
498 
499  return 1;
500 }
501 
502 #ifdef DEBUG
503 #define ALPHA_MIX(A,BACK,FORE) (((255-(A)) * (BACK) + (A) * (FORE)) / 255)
504 static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
505  uint32_t *rgba_palette)
506 {
507  int x, y, alpha;
508  uint32_t v;
509  int back[3] = {0, 255, 0}; /* green background */
510  FILE *f;
511 
512  f = fopen(filename, "w");
513  if (!f) {
514  perror(filename);
515  return;
516  }
517  fprintf(f, "P6\n"
518  "%d %d\n"
519  "%d\n",
520  w, h, 255);
521  for(y = 0; y < h; y++) {
522  for(x = 0; x < w; x++) {
523  v = rgba_palette[bitmap[y * w + x]];
524  alpha = v >> 24;
525  putc(ALPHA_MIX(alpha, back[0], (v >> 16) & 0xff), f);
526  putc(ALPHA_MIX(alpha, back[1], (v >> 8) & 0xff), f);
527  putc(ALPHA_MIX(alpha, back[2], (v >> 0) & 0xff), f);
528  }
529  }
530  fclose(f);
531 }
532 #endif
533 
535  const uint8_t *buf, int buf_size)
536 {
537  DVDSubContext *ctx = avctx->priv_data;
538 
539  av_assert0(buf_size >= 0 && ctx->buf_size <= sizeof(ctx->buf));
540  if (buf_size >= sizeof(ctx->buf) - ctx->buf_size) {
541  av_log(avctx, AV_LOG_WARNING, "Attempt to reconstruct "
542  "too large SPU packets aborted.\n");
543  ctx->buf_size = 0;
544  return AVERROR_INVALIDDATA;
545  }
546  memcpy(ctx->buf + ctx->buf_size, buf, buf_size);
547  ctx->buf_size += buf_size;
548  return 0;
549 }
550 
552  int *data_size, const AVPacket *avpkt)
553 {
554  DVDSubContext *ctx = avctx->priv_data;
555  const uint8_t *buf = avpkt->data;
556  int buf_size = avpkt->size;
557  int appended = 0;
558  int is_menu;
559 
560  if (ctx->buf_size) {
561  int ret = append_to_cached_buf(avctx, buf, buf_size);
562  if (ret < 0) {
563  *data_size = 0;
564  return ret;
565  }
566  buf = ctx->buf;
567  buf_size = ctx->buf_size;
568  appended = 1;
569  }
570 
571  is_menu = decode_dvd_subtitles(ctx, sub, buf, buf_size);
572  if (is_menu == AVERROR(EAGAIN)) {
573  *data_size = 0;
574  return appended ? 0 : append_to_cached_buf(avctx, buf, buf_size);
575  }
576 
577  if (is_menu < 0) {
578  ctx->buf_size = 0;
579  no_subtitle:
580  reset_rects(sub);
581  *data_size = 0;
582 
583  return buf_size;
584  }
585  if (!is_menu && find_smallest_bounding_rectangle(ctx, sub) == 0)
586  goto no_subtitle;
587 
588  if (ctx->forced_subs_only && !(sub->rects[0]->flags & AV_SUBTITLE_FLAG_FORCED))
589  goto no_subtitle;
590 
591 #if defined(DEBUG)
592  {
593  char ppm_name[32];
594 
595  snprintf(ppm_name, sizeof(ppm_name), "/tmp/%05d.ppm", ctx->sub_id++);
596  ff_dlog(NULL, "start=%d ms end =%d ms\n",
597  sub->start_display_time,
598  sub->end_display_time);
599  ppm_save(ppm_name, sub->rects[0]->data[0],
600  sub->rects[0]->w, sub->rects[0]->h, (uint32_t*) sub->rects[0]->data[1]);
601  }
602 #endif
603 
604  ctx->buf_size = 0;
605  *data_size = 1;
606  return buf_size;
607 }
608 
609 static int parse_ifo_palette(DVDSubContext *ctx, char *p)
610 {
611  FILE *ifo;
612  char ifostr[12];
613  uint32_t sp_pgci, pgci, off_pgc, pgc;
614  uint8_t r, g, b, yuv[65], *buf;
615  int i, y, cb, cr, r_add, g_add, b_add;
616  int ret = 0;
617  const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
618 
619  ctx->has_palette = 0;
620  if ((ifo = fopen(p, "r")) == NULL) {
621  av_log(ctx, AV_LOG_WARNING, "Unable to open IFO file \"%s\": %s\n", p, av_err2str(AVERROR(errno)));
622  return AVERROR_EOF;
623  }
624  if (fread(ifostr, 12, 1, ifo) != 1 || memcmp(ifostr, "DVDVIDEO-VTS", 12)) {
625  av_log(ctx, AV_LOG_WARNING, "\"%s\" is not a proper IFO file\n", p);
627  goto end;
628  }
629  if (fseek(ifo, 0xCC, SEEK_SET) == -1) {
630  ret = AVERROR(errno);
631  goto end;
632  }
633  if (fread(&sp_pgci, 4, 1, ifo) == 1) {
634  pgci = av_be2ne32(sp_pgci) * 2048;
635  if (fseek(ifo, pgci + 0x0C, SEEK_SET) == -1) {
636  ret = AVERROR(errno);
637  goto end;
638  }
639  if (fread(&off_pgc, 4, 1, ifo) == 1) {
640  pgc = pgci + av_be2ne32(off_pgc);
641  if (fseek(ifo, pgc + 0xA4, SEEK_SET) == -1) {
642  ret = AVERROR(errno);
643  goto end;
644  }
645  if (fread(yuv, 64, 1, ifo) == 1) {
646  buf = yuv;
647  for(i=0; i<16; i++) {
648  y = *++buf;
649  cr = *++buf;
650  cb = *++buf;
652  YUV_TO_RGB2_CCIR(r, g, b, y);
653  ctx->palette[i] = (r << 16) + (g << 8) + b;
654  buf++;
655  }
656  ctx->has_palette = 1;
657  }
658  }
659  }
660  if (ctx->has_palette == 0) {
661  av_log(ctx, AV_LOG_WARNING, "Failed to read palette from IFO file \"%s\"\n", p);
663  }
664 end:
665  fclose(ifo);
666  return ret;
667 }
668 
670 {
672  char *dataorig, *data;
673  int ret = 1;
674 
675  if (!avctx->extradata || !avctx->extradata_size)
676  return 1;
677 
678  dataorig = data = av_malloc(avctx->extradata_size+1);
679  if (!data)
680  return AVERROR(ENOMEM);
681  memcpy(data, avctx->extradata, avctx->extradata_size);
682  data[avctx->extradata_size] = '\0';
683 
684  for(;;) {
685  int pos = strcspn(data, "\n\r");
686  if (pos==0 && *data==0)
687  break;
688 
689  if (strncmp("palette:", data, 8) == 0) {
690  ctx->has_palette = 1;
691  ff_dvdsub_parse_palette(ctx->palette, data + 8);
692  } else if (strncmp("size:", data, 5) == 0) {
693  int w, h;
694  if (sscanf(data + 5, "%dx%d", &w, &h) == 2) {
695  ret = ff_set_dimensions(avctx, w, h);
696  if (ret < 0)
697  goto fail;
698  }
699  }
700 
701  data += pos;
702  data += strspn(data, "\n\r");
703  }
704 
705 fail:
706  av_free(dataorig);
707  return ret;
708 }
709 
711 {
712  DVDSubContext *ctx = avctx->priv_data;
713  int ret;
714 
715  if ((ret = dvdsub_parse_extradata(avctx)) < 0)
716  return ret;
717 
718  if (ctx->ifo_str)
719  parse_ifo_palette(ctx, ctx->ifo_str);
720  if (ctx->palette_str) {
721  ctx->has_palette = 1;
722  ff_dvdsub_parse_palette(ctx->palette, ctx->palette_str);
723  }
724  if (ctx->has_palette) {
725  int i;
726  av_log(avctx, AV_LOG_DEBUG, "palette:");
727  for(i=0;i<16;i++)
728  av_log(avctx, AV_LOG_DEBUG, " 0x%06"PRIx32, ctx->palette[i]);
729  av_log(avctx, AV_LOG_DEBUG, "\n");
730  }
731 
732  return 1;
733 }
734 
735 static void dvdsub_flush(AVCodecContext *avctx)
736 {
737  DVDSubContext *ctx = avctx->priv_data;
738  ctx->buf_size = 0;
739 }
740 
741 #define OFFSET(field) offsetof(DVDSubContext, field)
742 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
743 static const AVOption options[] = {
744  { "palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
745  { "ifo_palette", "obtain the global palette from .IFO file", OFFSET(ifo_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
746  { "forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SD},
747  { NULL }
748 };
749 static const AVClass dvdsub_class = {
750  .class_name = "dvdsubdec",
751  .item_name = av_default_item_name,
752  .option = options,
753  .version = LIBAVUTIL_VERSION_INT,
754 };
755 
757  .p.name = "dvdsub",
758  .p.long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
759  .p.type = AVMEDIA_TYPE_SUBTITLE,
760  .p.id = AV_CODEC_ID_DVD_SUBTITLE,
761  .priv_data_size = sizeof(DVDSubContext),
762  .init = dvdsub_init,
764  .flush = dvdsub_flush,
765  .p.priv_class = &dvdsub_class,
766  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
767 };
AVSubtitle
Definition: avcodec.h:2306
options
static const AVOption options[]
Definition: dvdsubdec.c:743
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
level
uint8_t level
Definition: svq3.c:206
r
const char * r
Definition: vf_curves.c:116
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
AVSubtitle::rects
AVSubtitleRect ** rects
Definition: avcodec.h:2311
opt.h
color
Definition: vf_paletteuse.c:600
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:239
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:31
READ_OFFSET
#define READ_OFFSET(a)
Definition: dvdsubdec.c:219
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
dvdsub_init
static av_cold int dvdsub_init(AVCodecContext *avctx)
Definition: dvdsubdec.c:710
reset_rects
static void reset_rects(AVSubtitle *sub_header)
Definition: dvdsubdec.c:204
ff_dvdsub_parse_palette
void ff_dvdsub_parse_palette(uint32_t *palette, const char *p)
Definition: dvdsub.c:26
AVSubtitleRect
Definition: avcodec.h:2278
DVDSubContext::palette_str
char * palette_str
Definition: dvdsubdec.c:37
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:2310
dvdsub_flush
static void dvdsub_flush(AVCodecContext *avctx)
Definition: dvdsubdec.c:735
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:220
w
uint8_t w
Definition: llviddspenc.c:38
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:374
AVOption
AVOption.
Definition: opt.h:251
DVDSubContext::ifo_str
char * ifo_str
Definition: dvdsubdec.c:38
b
#define b
Definition: input.c:34
data
const char data[16]
Definition: mxf.c:143
DVDSubContext::forced_subs_only
int forced_subs_only
Definition: dvdsubdec.c:44
SD
#define SD
Definition: dvdsubdec.c:742
FFCodec
Definition: codec_internal.h:112
DVDSubContext::palette
uint32_t palette[16]
Definition: dvdsubdec.c:36
AVSubtitleRect::linesize
int linesize[4]
Definition: avcodec.h:2290
YUV_TO_RGB1_CCIR
#define YUV_TO_RGB1_CCIR(cb1, cr1)
Definition: colorspace.h:34
init_get_bits
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:660
ff_crop_tab
#define ff_crop_tab
Definition: motionpixels_tablegen.c:26
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
init
static int init
Definition: av_tx.c:47
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:380
dvdsub_parse_extradata
static int dvdsub_parse_extradata(AVCodecContext *avctx)
Definition: dvdsubdec.c:669
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:116
U
#define U(x)
Definition: vp56_arith.h:37
fail
#define fail()
Definition: checkasm.h:130
dvdsub_decode
static int dvdsub_decode(AVCodecContext *avctx, AVSubtitle *sub, int *data_size, const AVPacket *avpkt)
Definition: dvdsubdec.c:551
GetBitContext
Definition: get_bits.h:62
AVSubtitleRect::x
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:2279
find_smallest_bounding_rectangle
static int find_smallest_bounding_rectangle(DVDSubContext *ctx, AVSubtitle *s)
Definition: dvdsubdec.c:443
append_to_cached_buf
static int append_to_cached_buf(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:534
colorspace.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:491
s
#define s(width, name)
Definition: cbs_vp9.c:256
g
const char * g
Definition: vf_curves.c:117
AVSubtitleRect::y
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:2280
DVDSubContext::buf
uint8_t buf[0x10000]
Definition: dvdsubdec.c:42
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
get_bits.h
if
if(ret)
Definition: filter_design.txt:179
av_be2ne32
#define av_be2ne32(x)
Definition: bswap.h:93
AVSubtitleRect::w
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:2281
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
DVDSubContext
Definition: dvdsubdec.c:33
NULL
#define NULL
Definition: coverity.c:32
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
AV_CODEC_ID_DVD_SUBTITLE
@ AV_CODEC_ID_DVD_SUBTITLE
Definition: codec_id.h:525
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:499
AVSubtitleRect::data
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:2289
YUV_TO_RGB2_CCIR
#define YUV_TO_RGB2_CCIR(r, g, b, y1)
Definition: colorspace.h:55
decode_run_2bit
static int decode_run_2bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:68
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
f
f
Definition: af_crystalizer.c:122
DVDSubContext::used_color
uint8_t used_color[256]
Definition: dvdsubdec.c:45
AVPacket::size
int size
Definition: packet.h:375
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:116
codec_internal.h
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
AVSubtitle::end_display_time
uint32_t end_display_time
Definition: avcodec.h:2309
AVSubtitleRect::type
enum AVSubtitleType type
Definition: avcodec.h:2292
dvdsub_class
static const AVClass dvdsub_class
Definition: dvdsubdec.c:749
decode_rle
static int decode_rle(uint8_t *bitmap, int linesize, int w, int h, uint8_t used_color[256], const uint8_t *buf, int start, int buf_size, int is_8bit)
Definition: dvdsubdec.c:101
attributes.h
AV_SUBTITLE_FLAG_FORCED
#define AV_SUBTITLE_FLAG_FORCED
Definition: avcodec.h:2276
SUBTITLE_BITMAP
@ SUBTITLE_BITMAP
A bitmap, pict will be set.
Definition: avcodec.h:2261
decode_dvd_subtitles
static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:221
AVSubtitleRect::flags
int flags
Definition: avcodec.h:2303
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:490
AVSubtitleRect::nb_colors
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:2283
parse_ifo_palette
static int parse_ifo_palette(DVDSubContext *ctx, char *p)
Definition: dvdsubdec.c:609
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: codec_internal.h:31
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:203
ff_dvdsub_decoder
const FFCodec ff_dvdsub_decoder
Definition: dvdsubdec.c:756
len
int len
Definition: vorbis_enc_data.h:426
avcodec.h
ret
ret
Definition: filter_design.txt:187
bswap.h
AVSubtitleRect::h
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:2282
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:71
is_transp
static int is_transp(const uint8_t *buf, int pitch, int n, const uint8_t *transp_color)
Definition: dvdsubdec.c:430
align_get_bits
static const uint8_t * align_get_bits(GetBitContext *s)
Definition: get_bits.h:694
pos
unsigned int pos
Definition: spdifenc.c:412
AVCodecContext
main external API structure.
Definition: avcodec.h:389
DVDSubContext::has_palette
int has_palette
Definition: dvdsubdec.c:39
cm
#define cm
Definition: dvbsubdec.c:39
FF_CODEC_DECODE_SUB_CB
#define FF_CODEC_DECODE_SUB_CB(func)
Definition: codec_internal.h:257
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:90
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
DVDSubContext::colormap
uint8_t colormap[4]
Definition: dvdsubdec.c:40
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
OFFSET
#define OFFSET(field)
Definition: dvdsubdec.c:741
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:416
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
cr
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:240
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
d
d
Definition: ffmpeg_filter.c:153
imgutils.h
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
h
h
Definition: vp9dsp_template.c:2038
DVDSubContext::buf_size
int buf_size
Definition: dvdsubdec.c:43
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
MAX_NEG_CROP
#define MAX_NEG_CROP
Definition: mathops.h:30
yuv_a_to_rgba
static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values)
Definition: dvdsubdec.c:51
snprintf
#define snprintf
Definition: snprintf.h:34
DVDSubContext::alpha
uint8_t alpha[256]
Definition: dvdsubdec.c:41
AVSubtitle::start_display_time
uint32_t start_display_time
Definition: avcodec.h:2308
AV_RB16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:98
guess_palette
static void guess_palette(DVDSubContext *ctx, uint32_t *rgba_palette, uint32_t subtitle_color)
Definition: dvdsubdec.c:147
decode_run_8bit
static int decode_run_8bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:82