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++;
61  YUV_TO_RGB1_CCIR(cb, cr);
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);
645  ret = AVERROR_INVALIDDATA;
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;
670  YUV_TO_RGB1_CCIR(cb, cr);
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);
681  ret = AVERROR_INVALIDDATA;
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;
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;
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 };
uint8_t colormap[4]
Definition: dvdsubdec.c:39
#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:754
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3978
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
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:379
#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:40
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:3982
int size
Definition: avcodec.h:1534
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
#define MAX_NEG_CROP
Definition: mathops.h:31
unsigned num_rects
Definition: avcodec.h:4016
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:35
AVCodec.
Definition: avcodec.h:3555
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
static av_cold int dvdsub_close(AVCodecContext *avctx)
Definition: dvdsubdec.c:760
attribute_deprecated AVPicture pict
Definition: avcodec.h:3989
Macro definitions for various function/variable attributes.
AVSubtitleRect ** rects
Definition: avcodec.h:4017
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:3980
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:215
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:3949
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1722
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:37
static void reset_rects(AVSubtitle *sub_header)
Definition: dvdsubdec.c:203
uint8_t * data
Definition: avcodec.h:1533
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
#define ff_dlog(a,...)
#define READ_OFFSET(a)
Definition: dvdsubdec.c:218
#define AVERROR_EOF
End of file.
Definition: error.h:55
bitstream reader API header.
ptrdiff_t size
Definition: opengl_enc.c:100
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:3981
static av_cold int dvdsub_init(AVCodecContext *avctx)
Definition: dvdsubdec.c:729
#define av_log(a,...)
#define cm
Definition: dvbsubdec.c:37
#define SD
Definition: dvdsubdec.c:767
#define U(x)
Definition: vp56_arith.h:37
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#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:3979
uint8_t used_color[256]
Definition: dvdsubdec.c:44
#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
unsigned int pos
Definition: spdifenc.c:410
#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:451
const char * name
Name of the codec implementation.
Definition: avcodec.h:3562
static int append_to_cached_buf(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:551
#define fail()
Definition: checkasm.h:122
#define OFFSET(field)
Definition: dvdsubdec.c:766
uint32_t end_display_time
Definition: avcodec.h:4015
uint8_t buf[0x10000]
Definition: dvdsubdec.c:41
static int decode_run_8bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:81
A bitmap, pict will be set.
Definition: avcodec.h:3960
#define AV_SUBTITLE_FLAG_FORCED
Definition: avcodec.h:3975
int linesize[4]
Definition: avcodec.h:3996
#define b
Definition: input.c:41
static const AVClass dvdsub_class
Definition: dvdsubdec.c:774
#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:100
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:50
#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:628
static int is_transp(const uint8_t *buf, int pitch, int n, const uint8_t *transp_color)
Definition: dvdsubdec.c:438
attribute_deprecated uint8_t * data[AV_NUM_DATA_POINTERS]
pointers to the image data planes
Definition: avcodec.h:3947
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:760
int has_palette
Definition: dvdsubdec.c:38
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:3995
if(ret)
AVCodec ff_dvdsub_decoder
Definition: dvdsubdec.c:781
#define YUV_TO_RGB1_CCIR(cb1, cr1)
Definition: colorspace.h:34
Libavcodec external API header.
main external API structure.
Definition: avcodec.h:1621
static const AVOption options[]
Definition: dvdsubdec.c:768
static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, const uint8_t *buf, int buf_size)
Definition: dvdsubdec.c:220
int extradata_size
Definition: avcodec.h:1723
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
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:659
byte swapping routines
static int decode_run_2bit(GetBitContext *gb, int *color)
Definition: dvdsubdec.c:67
#define snprintf
Definition: snprintf.h:34
void ff_dvdsub_parse_palette(uint32_t *palette, const char *p)
Definition: dvdsub.c:26
uint8_t level
Definition: svq3.c:209
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
common internal api header.
static int dvdsub_parse_extradata(AVCodecContext *avctx)
Definition: dvdsubdec.c:688
uint32_t start_display_time
Definition: avcodec.h:4014
static void guess_palette(DVDSubContext *ctx, uint32_t *rgba_palette, uint32_t subtitle_color)
Definition: dvdsubdec.c:146
#define ff_crop_tab
void * priv_data
Definition: avcodec.h:1648
#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:568
static const uint8_t * align_get_bits(GetBitContext *s)
Definition: get_bits.h:693
#define av_freep(p)
void INT64 start
Definition: avisynth_c.h:766
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:216
enum AVSubtitleType type
Definition: avcodec.h:3998
This structure stores compressed data.
Definition: avcodec.h:1510
char * palette_str
Definition: dvdsubdec.c:36
int forced_subs_only
Definition: dvdsubdec.c:43