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/avstring.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;
41  uint8_t alpha[256];
42  uint8_t buf[0x10000];
43  int buf_size;
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 {
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  0xffff00);
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 #if FF_API_AVPICTURE
416  for (i = 0; i < 4; i++) {
417  sub_header->rects[0]->pict.data[i] = sub_header->rects[0]->data[i];
418  sub_header->rects[0]->pict.linesize[i] = sub_header->rects[0]->linesize[i];
419  }
421 #endif
422  }
423  }
424  if (next_cmd_pos < cmd_pos) {
425  av_log(ctx, AV_LOG_ERROR, "Invalid command offset\n");
426  break;
427  }
428  if (next_cmd_pos == cmd_pos)
429  break;
430  cmd_pos = next_cmd_pos;
431  }
432  if (sub_header->num_rects > 0)
433  return is_menu;
434  fail:
435  reset_rects(sub_header);
436  return -1;
437 }
438 
439 static int is_transp(const uint8_t *buf, int pitch, int n,
440  const uint8_t *transp_color)
441 {
442  int i;
443  for(i = 0; i < n; i++) {
444  if (!transp_color[*buf])
445  return 0;
446  buf += pitch;
447  }
448  return 1;
449 }
450 
451 /* return 0 if empty rectangle, 1 if non empty */
453 {
454  uint8_t transp_color[256] = { 0 };
455  int y1, y2, x1, x2, y, w, h, i;
456  uint8_t *bitmap;
457  int transparent = 1;
458 
459  if (s->num_rects == 0 || !s->rects || s->rects[0]->w <= 0 || s->rects[0]->h <= 0)
460  return 0;
461 
462  for(i = 0; i < s->rects[0]->nb_colors; i++) {
463  if ((((uint32_t *)s->rects[0]->data[1])[i] >> 24) == 0) {
464  transp_color[i] = 1;
465  } else if (ctx->used_color[i])
466  transparent = 0;
467  }
468  if (transparent)
469  return 0;
470  y1 = 0;
471  while (y1 < s->rects[0]->h && is_transp(s->rects[0]->data[0] + y1 * s->rects[0]->linesize[0],
472  1, s->rects[0]->w, transp_color))
473  y1++;
474  if (y1 == s->rects[0]->h) {
475  av_freep(&s->rects[0]->data[0]);
476  s->rects[0]->w = s->rects[0]->h = 0;
477  return 0;
478  }
479 
480  y2 = s->rects[0]->h - 1;
481  while (y2 > 0 && is_transp(s->rects[0]->data[0] + y2 * s->rects[0]->linesize[0], 1,
482  s->rects[0]->w, transp_color))
483  y2--;
484  x1 = 0;
485  while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->data[0] + x1, s->rects[0]->linesize[0],
486  s->rects[0]->h, transp_color))
487  x1++;
488  x2 = s->rects[0]->w - 1;
489  while (x2 > 0 && is_transp(s->rects[0]->data[0] + x2, s->rects[0]->linesize[0], s->rects[0]->h,
490  transp_color))
491  x2--;
492  w = x2 - x1 + 1;
493  h = y2 - y1 + 1;
494  bitmap = av_malloc(w * h);
495  if (!bitmap)
496  return 1;
497  for(y = 0; y < h; y++) {
498  memcpy(bitmap + w * y, s->rects[0]->data[0] + x1 + (y1 + y) * s->rects[0]->linesize[0], w);
499  }
500  av_freep(&s->rects[0]->data[0]);
501  s->rects[0]->data[0] = bitmap;
502  s->rects[0]->linesize[0] = w;
503  s->rects[0]->w = w;
504  s->rects[0]->h = h;
505  s->rects[0]->x += x1;
506  s->rects[0]->y += y1;
507 
508 #if FF_API_AVPICTURE
510  for (i = 0; i < 4; i++) {
511  s->rects[0]->pict.data[i] = s->rects[0]->data[i];
512  s->rects[0]->pict.linesize[i] = s->rects[0]->linesize[i];
513  }
515 #endif
516 
517  return 1;
518 }
519 
520 #ifdef DEBUG
521 #define ALPHA_MIX(A,BACK,FORE) (((255-(A)) * (BACK) + (A) * (FORE)) / 255)
522 static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
523  uint32_t *rgba_palette)
524 {
525  int x, y, alpha;
526  uint32_t v;
527  int back[3] = {0, 255, 0}; /* green background */
528  FILE *f;
529 
530  f = fopen(filename, "w");
531  if (!f) {
532  perror(filename);
533  return;
534  }
535  fprintf(f, "P6\n"
536  "%d %d\n"
537  "%d\n",
538  w, h, 255);
539  for(y = 0; y < h; y++) {
540  for(x = 0; x < w; x++) {
541  v = rgba_palette[bitmap[y * w + x]];
542  alpha = v >> 24;
543  putc(ALPHA_MIX(alpha, back[0], (v >> 16) & 0xff), f);
544  putc(ALPHA_MIX(alpha, back[1], (v >> 8) & 0xff), f);
545  putc(ALPHA_MIX(alpha, back[2], (v >> 0) & 0xff), f);
546  }
547  }
548  fclose(f);
549 }
550 #endif
551 
553  const uint8_t *buf, int buf_size)
554 {
555  DVDSubContext *ctx = avctx->priv_data;
556 
557  av_assert0(buf_size >= 0 && ctx->buf_size <= sizeof(ctx->buf));
558  if (buf_size >= sizeof(ctx->buf) - ctx->buf_size) {
559  av_log(avctx, AV_LOG_WARNING, "Attempt to reconstruct "
560  "too large SPU packets aborted.\n");
561  ctx->buf_size = 0;
562  return AVERROR_INVALIDDATA;
563  }
564  memcpy(ctx->buf + ctx->buf_size, buf, buf_size);
565  ctx->buf_size += buf_size;
566  return 0;
567 }
568 
569 static int dvdsub_decode(AVCodecContext *avctx,
570  void *data, int *data_size,
571  AVPacket *avpkt)
572 {
573  DVDSubContext *ctx = avctx->priv_data;
574  const uint8_t *buf = avpkt->data;
575  int buf_size = avpkt->size;
576  AVSubtitle *sub = data;
577  int appended = 0;
578  int is_menu;
579 
580  if (ctx->buf_size) {
581  int ret = append_to_cached_buf(avctx, buf, buf_size);
582  if (ret < 0) {
583  *data_size = 0;
584  return ret;
585  }
586  buf = ctx->buf;
587  buf_size = ctx->buf_size;
588  appended = 1;
589  }
590 
591  is_menu = decode_dvd_subtitles(ctx, sub, buf, buf_size);
592  if (is_menu == AVERROR(EAGAIN)) {
593  *data_size = 0;
594  return appended ? 0 : append_to_cached_buf(avctx, buf, buf_size);
595  }
596 
597  if (is_menu < 0) {
598  ctx->buf_size = 0;
599  no_subtitle:
600  reset_rects(sub);
601  *data_size = 0;
602 
603  return buf_size;
604  }
605  if (!is_menu && find_smallest_bounding_rectangle(ctx, sub) == 0)
606  goto no_subtitle;
607 
608  if (ctx->forced_subs_only && !(sub->rects[0]->flags & AV_SUBTITLE_FLAG_FORCED))
609  goto no_subtitle;
610 
611 #if defined(DEBUG)
612  {
613  char ppm_name[32];
614 
615  snprintf(ppm_name, sizeof(ppm_name), "/tmp/%05d.ppm", ctx->sub_id++);
616  ff_dlog(NULL, "start=%d ms end =%d ms\n",
617  sub->start_display_time,
618  sub->end_display_time);
619  ppm_save(ppm_name, sub->rects[0]->data[0],
620  sub->rects[0]->w, sub->rects[0]->h, (uint32_t*) sub->rects[0]->data[1]);
621  }
622 #endif
623 
624  ctx->buf_size = 0;
625  *data_size = 1;
626  return buf_size;
627 }
628 
629 static void parse_palette(DVDSubContext *ctx, char *p)
630 {
631  int i;
632 
633  ctx->has_palette = 1;
634  for(i=0;i<16;i++) {
635  ctx->palette[i] = strtoul(p, &p, 16);
636  while(*p == ',' || av_isspace(*p))
637  p++;
638  }
639 }
640 
641 static int parse_ifo_palette(DVDSubContext *ctx, char *p)
642 {
643  FILE *ifo;
644  char ifostr[12];
645  uint32_t sp_pgci, pgci, off_pgc, pgc;
646  uint8_t r, g, b, yuv[65], *buf;
647  int i, y, cb, cr, r_add, g_add, b_add;
648  int ret = 0;
649  const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
650 
651  ctx->has_palette = 0;
652  if ((ifo = fopen(p, "r")) == NULL) {
653  av_log(ctx, AV_LOG_WARNING, "Unable to open IFO file \"%s\": %s\n", p, av_err2str(AVERROR(errno)));
654  return AVERROR_EOF;
655  }
656  if (fread(ifostr, 12, 1, ifo) != 1 || memcmp(ifostr, "DVDVIDEO-VTS", 12)) {
657  av_log(ctx, AV_LOG_WARNING, "\"%s\" is not a proper IFO file\n", p);
659  goto end;
660  }
661  if (fseek(ifo, 0xCC, SEEK_SET) == -1) {
662  ret = AVERROR(errno);
663  goto end;
664  }
665  if (fread(&sp_pgci, 4, 1, ifo) == 1) {
666  pgci = av_be2ne32(sp_pgci) * 2048;
667  if (fseek(ifo, pgci + 0x0C, SEEK_SET) == -1) {
668  ret = AVERROR(errno);
669  goto end;
670  }
671  if (fread(&off_pgc, 4, 1, ifo) == 1) {
672  pgc = pgci + av_be2ne32(off_pgc);
673  if (fseek(ifo, pgc + 0xA4, SEEK_SET) == -1) {
674  ret = AVERROR(errno);
675  goto end;
676  }
677  if (fread(yuv, 64, 1, ifo) == 1) {
678  buf = yuv;
679  for(i=0; i<16; i++) {
680  y = *++buf;
681  cr = *++buf;
682  cb = *++buf;
684  YUV_TO_RGB2_CCIR(r, g, b, y);
685  ctx->palette[i] = (r << 16) + (g << 8) + b;
686  buf++;
687  }
688  ctx->has_palette = 1;
689  }
690  }
691  }
692  if (ctx->has_palette == 0) {
693  av_log(ctx, AV_LOG_WARNING, "Failed to read palette from IFO file \"%s\"\n", p);
695  }
696 end:
697  fclose(ifo);
698  return ret;
699 }
700 
702 {
704  char *dataorig, *data;
705  int ret = 1;
706 
707  if (!avctx->extradata || !avctx->extradata_size)
708  return 1;
709 
710  dataorig = data = av_malloc(avctx->extradata_size+1);
711  if (!data)
712  return AVERROR(ENOMEM);
713  memcpy(data, avctx->extradata, avctx->extradata_size);
714  data[avctx->extradata_size] = '\0';
715 
716  for(;;) {
717  int pos = strcspn(data, "\n\r");
718  if (pos==0 && *data==0)
719  break;
720 
721  if (strncmp("palette:", data, 8) == 0) {
722  parse_palette(ctx, data + 8);
723  } else if (strncmp("size:", data, 5) == 0) {
724  int w, h;
725  if (sscanf(data + 5, "%dx%d", &w, &h) == 2) {
726  ret = ff_set_dimensions(avctx, w, h);
727  if (ret < 0)
728  goto fail;
729  }
730  }
731 
732  data += pos;
733  data += strspn(data, "\n\r");
734  }
735 
736 fail:
737  av_free(dataorig);
738  return ret;
739 }
740 
742 {
743  DVDSubContext *ctx = avctx->priv_data;
744  int ret;
745 
746  if ((ret = dvdsub_parse_extradata(avctx)) < 0)
747  return ret;
748 
749  if (ctx->ifo_str)
750  parse_ifo_palette(ctx, ctx->ifo_str);
751  if (ctx->palette_str)
752  parse_palette(ctx, ctx->palette_str);
753  if (ctx->has_palette) {
754  int i;
755  av_log(avctx, AV_LOG_DEBUG, "palette:");
756  for(i=0;i<16;i++)
757  av_log(avctx, AV_LOG_DEBUG, " 0x%06"PRIx32, ctx->palette[i]);
758  av_log(avctx, AV_LOG_DEBUG, "\n");
759  }
760 
761  return 1;
762 }
763 
764 static void dvdsub_flush(AVCodecContext *avctx)
765 {
766  DVDSubContext *ctx = avctx->priv_data;
767  ctx->buf_size = 0;
768 }
769 
771 {
772  dvdsub_flush(avctx);
773  return 0;
774 }
775 
776 #define OFFSET(field) offsetof(DVDSubContext, field)
777 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
778 static const AVOption options[] = {
779  { "palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
780  { "ifo_palette", "obtain the global palette from .IFO file", OFFSET(ifo_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
781  { "forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SD},
782  { NULL }
783 };
784 static const AVClass dvdsub_class = {
785  .class_name = "dvdsubdec",
786  .item_name = av_default_item_name,
787  .option = options,
788  .version = LIBAVUTIL_VERSION_INT,
789 };
790 
792  .name = "dvdsub",
793  .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
794  .type = AVMEDIA_TYPE_SUBTITLE,
796  .priv_data_size = sizeof(DVDSubContext),
797  .init = dvdsub_init,
799  .flush = dvdsub_flush,
800  .close = dvdsub_close,
801  .priv_class = &dvdsub_class,
802 };
AVSubtitle
Definition: avcodec.h:3933
options
static const AVOption options[]
Definition: dvdsubdec.c:778
AVCodec
AVCodec.
Definition: avcodec.h:3481
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:85
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:182
level
uint8_t level
Definition: svq3.c:207
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
ff_dvdsub_decoder
AVCodec ff_dvdsub_decoder
Definition: dvdsubdec.c:791
r
const char * r
Definition: vf_curves.c:114
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:3938
opt.h
parse_palette
static void parse_palette(DVDSubContext *ctx, char *p)
Definition: dvdsubdec.c:629
color
Definition: vf_paletteuse.c:588
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:112
n
int n
Definition: avisynth_c.h:760
dvdsub_close
static av_cold int dvdsub_close(AVCodecContext *avctx)
Definition: dvdsubdec.c:770
READ_OFFSET
#define READ_OFFSET(a)
Definition: dvdsubdec.c:219
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:741
reset_rects
static void reset_rects(AVSubtitle *sub_header)
Definition: dvdsubdec.c:204
AVSubtitleRect
Definition: avcodec.h:3898
DVDSubContext::palette_str
char * palette_str
Definition: dvdsubdec.c:37
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:3937
dvdsub_flush
static void dvdsub_flush(AVCodecContext *avctx)
Definition: dvdsubdec.c:764
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
av_isspace
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
w
uint8_t w
Definition: llviddspenc.c:38
internal.h
AVPacket::data
uint8_t * data
Definition: avcodec.h:1477
AVOption
AVOption.
Definition: opt.h:246
DVDSubContext::ifo_str
char * ifo_str
Definition: dvdsubdec.c:38
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:91
DVDSubContext::forced_subs_only
int forced_subs_only
Definition: dvdsubdec.c:44
SD
#define SD
Definition: dvdsubdec.c:777
DVDSubContext::palette
uint32_t palette[16]
Definition: dvdsubdec.c:36
AVSubtitleRect::linesize
int linesize[4]
Definition: avcodec.h:3917
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:3868
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:701
U
#define U(x)
Definition: vp56_arith.h:37
fail
#define fail()
Definition: checkasm.h:120
start
void INT64 start
Definition: avisynth_c.h:767
GetBitContext
Definition: get_bits.h:61
AVSubtitleRect::x
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3899
find_smallest_bounding_rectangle
static int find_smallest_bounding_rectangle(DVDSubContext *ctx, AVSubtitle *s)
Definition: dvdsubdec.c:452
append_to_cached_buf
static int append_to_cached_buf(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:552
colorspace.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
av_cold
#define av_cold
Definition: attributes.h:84
decode
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:42
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:1667
s
#define s(width, name)
Definition: cbs_vp9.c:257
g
const char * g
Definition: vf_curves.c:115
AVSubtitleRect::y
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3900
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:197
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:3901
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:33
flush
static void flush(AVCodecContext *avctx)
Definition: aacdec_template.c:500
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: avcodec.h:658
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
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:3916
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:29
DVDSubContext::used_color
uint8_t used_color[256]
Definition: dvdsubdec.c:45
AVPacket::size
int size
Definition: avcodec.h:1478
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:188
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:11134
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:92
AVSubtitle::end_display_time
uint32_t end_display_time
Definition: avcodec.h:3936
AVSubtitleRect::type
enum AVSubtitleType type
Definition: avcodec.h:3919
dvdsub_class
static const AVClass dvdsub_class
Definition: dvdsubdec.c:784
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
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:3896
SUBTITLE_BITMAP
@ SUBTITLE_BITMAP
A bitmap, pict will be set.
Definition: avcodec.h:3881
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:3930
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1666
AVSubtitleRect::nb_colors
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:3903
parse_ifo_palette
static int parse_ifo_palette(DVDSubContext *ctx, char *p)
Definition: dvdsubdec.c:641
uint8_t
uint8_t
Definition: audio_convert.c:194
AVSubtitleRect::pict
attribute_deprecated AVPicture pict
Definition: avcodec.h:3910
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:236
AVCodec::name
const char * name
Name of the codec implementation.
Definition: avcodec.h:3488
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:3902
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:439
align_get_bits
static const uint8_t * align_get_bits(GetBitContext *s)
Definition: get_bits.h:693
AVCodecContext
main external API structure.
Definition: avcodec.h:1565
DVDSubContext::has_palette
int has_palette
Definition: dvdsubdec.c:39
cm
#define cm
Definition: dvbsubdec.c:37
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
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:104
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
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:776
AVPacket
This structure stores compressed data.
Definition: avcodec.h:1454
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:1592
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
cr
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:113
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:3870
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:43
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
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:569
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:3935
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:94
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