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