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++;
62  YUV_TO_RGB1_CCIR(cb, cr);
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);
658  ret = AVERROR_INVALIDDATA;
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;
683  YUV_TO_RGB1_CCIR(cb, cr);
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);
694  ret = AVERROR_INVALIDDATA;
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 };
uint8_t colormap[4]
Definition: dvdsubdec.c:40
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void dvdsub_flush(AVCodecContext *avctx)
Definition: dvdsubdec.c:764
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3886
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static void flush(AVCodecContext *avctx)
misc image utilities
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:381
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
uint8_t alpha[256]
Definition: dvdsubdec.c:41
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
const char * g
Definition: vf_curves.c:115
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:3890
int size
Definition: avcodec.h:1469
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
#define MAX_NEG_CROP
Definition: mathops.h:31
unsigned num_rects
Definition: avcodec.h:3924
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
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:87
#define av_be2ne32(x)
Definition: bswap.h:93
uint32_t palette[16]
Definition: dvdsubdec.c:36
AVCodec.
Definition: avcodec.h:3468
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:42
static av_cold int dvdsub_close(AVCodecContext *avctx)
Definition: dvdsubdec.c:770
attribute_deprecated AVPicture pict
Definition: avcodec.h:3897
Macro definitions for various function/variable attributes.
AVSubtitleRect ** rects
Definition: avcodec.h:3925
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:3888
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
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:112
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
AVOptions.
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
#define f(width, name)
Definition: cbs_vp9.c:255
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
attribute_deprecated int linesize[AV_NUM_DATA_POINTERS]
number of bytes per line
Definition: avcodec.h:3857
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1657
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:87
char * ifo_str
Definition: dvdsubdec.c:38
static void reset_rects(AVSubtitle *sub_header)
Definition: dvdsubdec.c:204
uint8_t * data
Definition: avcodec.h:1468
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
#define ff_dlog(a,...)
#define READ_OFFSET(a)
Definition: dvdsubdec.c:219
#define AVERROR_EOF
End of file.
Definition: error.h:55
bitstream reader API header.
ptrdiff_t size
Definition: opengl_enc.c:101
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:3889
static av_cold int dvdsub_init(AVCodecContext *avctx)
Definition: dvdsubdec.c:741
#define av_log(a,...)
#define cm
Definition: dvbsubdec.c:37
#define SD
Definition: dvdsubdec.c:777
#define U(x)
Definition: vp56_arith.h:37
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
Various defines for YUV<->RGB conversion.
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3887
uint8_t used_color[256]
Definition: dvdsubdec.c:45
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const char * r
Definition: vf_curves.c:114
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
static int find_smallest_bounding_rectangle(DVDSubContext *ctx, AVSubtitle *s)
Definition: dvdsubdec.c:452
const char * name
Name of the codec implementation.
Definition: avcodec.h:3475
static int append_to_cached_buf(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:552
#define fail()
Definition: checkasm.h:118
#define OFFSET(field)
Definition: dvdsubdec.c:776
uint32_t end_display_time
Definition: avcodec.h:3923
uint8_t buf[0x10000]
Definition: dvdsubdec.c:42
static int decode_run_8bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:82
A bitmap, pict will be set.
Definition: avcodec.h:3868
#define AV_SUBTITLE_FLAG_FORCED
Definition: avcodec.h:3883
int linesize[4]
Definition: avcodec.h:3904
#define b
Definition: input.c:41
static const AVClass dvdsub_class
Definition: dvdsubdec.c:784
#define FFMIN(a, b)
Definition: common.h:96
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
uint8_t w
Definition: llviddspenc.c:38
#define YUV_TO_RGB2_CCIR(r, g, b, y1)
Definition: colorspace.h:55
static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values)
Definition: dvdsubdec.c:51
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
AVFormatContext * ctx
Definition: movenc.c:48
static int parse_ifo_palette(DVDSubContext *ctx, char *p)
Definition: dvdsubdec.c:641
static int is_transp(const uint8_t *buf, int pitch, int n, const uint8_t *transp_color)
Definition: dvdsubdec.c:439
attribute_deprecated uint8_t * data[AV_NUM_DATA_POINTERS]
pointers to the image data planes
Definition: avcodec.h:3855
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:684
int has_palette
Definition: dvdsubdec.c:39
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:3903
if(ret)
AVCodec ff_dvdsub_decoder
Definition: dvdsubdec.c:791
#define YUV_TO_RGB1_CCIR(cb1, cr1)
Definition: colorspace.h:34
static void parse_palette(DVDSubContext *ctx, char *p)
Definition: dvdsubdec.c:629
Libavcodec external API header.
main external API structure.
Definition: avcodec.h:1556
static const AVOption options[]
Definition: dvdsubdec.c:778
static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:221
int extradata_size
Definition: avcodec.h:1658
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:488
Describe the class of an AVClass context structure.
Definition: log.h:67
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:616
byte swapping routines
static int decode_run_2bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:68
#define snprintf
Definition: snprintf.h:34
uint8_t level
Definition: svq3.c:207
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
common internal api header.
static int dvdsub_parse_extradata(AVCodecContext *avctx)
Definition: dvdsubdec.c:701
uint32_t start_display_time
Definition: avcodec.h:3922
static void guess_palette(DVDSubContext *ctx, uint32_t *rgba_palette, uint32_t subtitle_color)
Definition: dvdsubdec.c:147
#define ff_crop_tab
void * priv_data
Definition: avcodec.h:1583
#define av_free(p)
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:85
int len
static int dvdsub_decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
Definition: dvdsubdec.c:569
static const uint8_t * align_get_bits(GetBitContext *s)
Definition: get_bits.h:659
#define av_freep(p)
void INT64 start
Definition: avisynth_c.h:690
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
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:113
enum AVSubtitleType type
Definition: avcodec.h:3906
This structure stores compressed data.
Definition: avcodec.h:1445
char * palette_str
Definition: dvdsubdec.c:37
int forced_subs_only
Definition: dvdsubdec.c:44