Merge pull request #473 from Montellese/onplaybackspeedchanged
[vuplus_xbmc] / lib / ffmpeg / libavcodec / dvdsubdec.c
1 /*
2  * DVD subtitle decoding for ffmpeg
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 #include "avcodec.h"
22 #include "get_bits.h"
23 #include "dsputil.h"
24 #include "libavutil/colorspace.h"
25
26 //#define DEBUG
27
28 typedef struct DVDSubContext
29 {
30   uint8_t  colormap[4];
31   uint8_t  alpha[256];
32   uint32_t palette[16];
33   int      has_palette;
34 } DVDSubContext;
35
36 static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values)
37 {
38     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
39     uint8_t r, g, b;
40     int i, y, cb, cr;
41     int r_add, g_add, b_add;
42
43     for (i = num_values; i > 0; i--) {
44         y = *ycbcr++;
45         cb = *ycbcr++;
46         cr = *ycbcr++;
47         YUV_TO_RGB1_CCIR(cb, cr);
48         YUV_TO_RGB2_CCIR(r, g, b, y);
49         *rgba++ = (*alpha++ << 24) | (r << 16) | (g << 8) | b;
50     }
51 }
52
53 static void ayvu_to_argb(const uint8_t *ayvu, uint32_t *argb, int num_values)
54 {
55     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
56     uint8_t r, g, b;
57     int i, y, cb, cr, a;
58     int r_add, g_add, b_add;
59
60     for (i = num_values; i > 0; i--) {
61         a = *ayvu++;
62         y = *ayvu++;
63         cr = *ayvu++;
64         cb = *ayvu++;
65         YUV_TO_RGB1_CCIR(cb, cr);
66         YUV_TO_RGB2_CCIR(r, g, b, y);
67         *argb++ = (a << 24) | (r << 16) | (g << 8) | b;
68     }
69 }
70
71 static int decode_run_2bit(GetBitContext *gb, int *color)
72 {
73     unsigned int v, t;
74
75     v = 0;
76     for (t = 1; v < t && t <= 0x40; t <<= 2)
77         v = (v << 4) | get_bits(gb, 4);
78     *color = v & 3;
79     if (v < 4) { /* Code for fill rest of line */
80         return INT_MAX;
81     }
82     return v >> 2;
83 }
84
85 static int decode_run_8bit(GetBitContext *gb, int *color)
86 {
87     int len;
88     int has_run = get_bits1(gb);
89     if (get_bits1(gb))
90         *color = get_bits(gb, 8);
91     else
92         *color = get_bits(gb, 2);
93     if (has_run) {
94         if (get_bits1(gb)) {
95             len = get_bits(gb, 7);
96             if (len == 0)
97                 len = INT_MAX;
98             else
99                 len += 9;
100         } else
101             len = get_bits(gb, 3) + 2;
102     } else
103         len = 1;
104     return len;
105 }
106
107 static int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
108                       const uint8_t *buf, int start, int buf_size, int is_8bit)
109 {
110     GetBitContext gb;
111     int bit_len;
112     int x, y, len, color;
113     uint8_t *d;
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         len = FFMIN(len, w - x);
129         memset(d + x, color, len);
130         x += len;
131         if (x >= w) {
132             y++;
133             if (y >= h)
134                 break;
135             d += linesize;
136             x = 0;
137             /* byte align */
138             align_get_bits(&gb);
139         }
140     }
141     return 0;
142 }
143
144 static void fill_palette(DVDSubContext* ctx,
145                          uint32_t *rgba_palette,
146                          uint32_t subtitle_color)
147 {
148     uint8_t color_used[16];
149     int nb_opaque_colors, i, level, j, r, g, b;
150     uint8_t *colormap = ctx->colormap;
151     uint8_t *alpha = ctx->alpha;
152
153     if(ctx->has_palette) {
154         for(i = 0; i < 4; i++)
155             rgba_palette[i] = (ctx->palette[ctx->colormap[i]] & 0x00ffffff)
156                               | ((alpha[i] * 17) << 24);
157         return;
158     }
159
160     for(i = 0; i < 4; i++)
161         rgba_palette[i] = 0;
162
163     memset(color_used, 0, 16);
164     nb_opaque_colors = 0;
165     for(i = 0; i < 4; i++) {
166         if (alpha[i] != 0 && !color_used[colormap[i]]) {
167             color_used[colormap[i]] = 1;
168             nb_opaque_colors++;
169         }
170     }
171
172     if (nb_opaque_colors == 0)
173         return;
174
175     j = nb_opaque_colors;
176     memset(color_used, 0, 16);
177     for(i = 0; i < 4; i++) {
178         if (alpha[i] != 0) {
179             if (!color_used[colormap[i]])  {
180                 level = (0xff * j) / nb_opaque_colors;
181                 r = (((subtitle_color >> 16) & 0xff) * level) >> 8;
182                 g = (((subtitle_color >> 8) & 0xff) * level) >> 8;
183                 b = (((subtitle_color >> 0) & 0xff) * level) >> 8;
184                 rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24);
185                 color_used[colormap[i]] = (i + 1);
186                 j--;
187             } else {
188                 rgba_palette[i] = (rgba_palette[color_used[colormap[i]] - 1] & 0x00ffffff) |
189                                     ((alpha[i] * 17) << 24);
190             }
191         }
192     }
193 }
194
195 #define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a))
196
197 static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header,
198                                 const uint8_t *buf, int buf_size)
199 {
200     int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos;
201     int big_offsets, offset_size, is_8bit = 0;
202     const uint8_t *yuv_palette = 0;
203     uint8_t *colormap = ctx->colormap;
204     uint8_t *alpha = ctx->alpha;
205     int date;
206     int i;
207     int is_menu = 0;
208
209     if (buf_size < 10)
210         return -1;
211     memset(sub_header, 0, sizeof(*sub_header));
212
213     if (AV_RB16(buf) == 0) {   /* HD subpicture with 4-byte offsets */
214         big_offsets = 1;
215         offset_size = 4;
216         cmd_pos = 6;
217     } else {
218         big_offsets = 0;
219         offset_size = 2;
220         cmd_pos = 2;
221     }
222
223     cmd_pos = READ_OFFSET(buf + cmd_pos);
224
225     while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) {
226         date = AV_RB16(buf + cmd_pos);
227         next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2);
228         av_dlog(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n",
229                 cmd_pos, next_cmd_pos, date);
230         pos = cmd_pos + 2 + offset_size;
231         offset1 = -1;
232         offset2 = -1;
233         x1 = y1 = x2 = y2 = 0;
234         while (pos < buf_size) {
235             cmd = buf[pos++];
236             av_dlog(NULL, "cmd=%02x\n", cmd);
237             switch(cmd) {
238             case 0x00:
239                 /* menu subpicture */
240                 is_menu = 1;
241                 break;
242             case 0x01:
243                 /* set start date */
244                 sub_header->start_display_time = (date << 10) / 90;
245                 break;
246             case 0x02:
247                 /* set end date */
248                 sub_header->end_display_time = (date << 10) / 90;
249                 break;
250             case 0x03:
251                 /* set colormap */
252                 if ((buf_size - pos) < 2)
253                     goto fail;
254                 colormap[3] = buf[pos] >> 4;
255                 colormap[2] = buf[pos] & 0x0f;
256                 colormap[1] = buf[pos + 1] >> 4;
257                 colormap[0] = buf[pos + 1] & 0x0f;
258                 pos += 2;
259                 break;
260             case 0x04:
261                 /* set alpha */
262                 if ((buf_size - pos) < 2)
263                     goto fail;
264                 alpha[3] = buf[pos] >> 4;
265                 alpha[2] = buf[pos] & 0x0f;
266                 alpha[1] = buf[pos + 1] >> 4;
267                 alpha[0] = buf[pos + 1] & 0x0f;
268                 pos += 2;
269             av_dlog(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]);
270                 break;
271             case 0x05:
272             case 0x85:
273                 if ((buf_size - pos) < 6)
274                     goto fail;
275                 x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4);
276                 x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2];
277                 y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4);
278                 y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5];
279                 if (cmd & 0x80)
280                     is_8bit = 1;
281                 av_dlog(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2);
282                 pos += 6;
283                 break;
284             case 0x06:
285                 if ((buf_size - pos) < 4)
286                     goto fail;
287                 offset1 = AV_RB16(buf + pos);
288                 offset2 = AV_RB16(buf + pos + 2);
289                 av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
290                 pos += 4;
291                 break;
292             case 0x86:
293                 if ((buf_size - pos) < 8)
294                     goto fail;
295                 offset1 = AV_RB32(buf + pos);
296                 offset2 = AV_RB32(buf + pos + 4);
297                 av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
298                 pos += 8;
299                 break;
300
301             case 0x83:
302                 /* HD set palette */
303                 if ((buf_size - pos) < 768)
304                     goto fail;
305                 yuv_palette = buf + pos;
306                 pos += 768;
307                 break;
308             case 0x84:
309                 /* HD set contrast (alpha) */
310                 if ((buf_size - pos) < 256)
311                     goto fail;
312                 for (i = 0; i < 256; i++)
313                     alpha[i] = 0xFF - buf[pos+i];
314                 pos += 256;
315                 break;
316
317             case 0xff:
318                 goto the_end;
319             default:
320                 av_dlog(NULL, "unrecognised subpicture command 0x%x\n", cmd);
321                 goto the_end;
322             }
323         }
324     the_end:
325         if (offset1 >= 0) {
326             int w, h;
327             uint8_t *bitmap;
328
329             /* decode the bitmap */
330             w = x2 - x1 + 1;
331             if (w < 0)
332                 w = 0;
333             h = y2 - y1;
334             if (h < 0)
335                 h = 0;
336             if (w > 0 && h > 0) {
337                 if (sub_header->rects != NULL) {
338                     for (i = 0; i < sub_header->num_rects; i++) {
339                         av_freep(&sub_header->rects[i]->pict.data[0]);
340                         av_freep(&sub_header->rects[i]->pict.data[1]);
341                         av_freep(&sub_header->rects[i]);
342                     }
343                     av_freep(&sub_header->rects);
344                     sub_header->num_rects = 0;
345                 }
346
347                 bitmap = av_malloc(w * h);
348                 sub_header->rects = av_mallocz(sizeof(*sub_header->rects));
349                 sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect));
350                 sub_header->num_rects = 1;
351                 sub_header->rects[0]->pict.data[0] = bitmap;
352                 decode_rle(bitmap, w * 2, w, (h + 1) / 2,
353                            buf, offset1, buf_size, is_8bit);
354                 decode_rle(bitmap + w, w * 2, w, h / 2,
355                            buf, offset2, buf_size, is_8bit);
356                 sub_header->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
357                 if (is_8bit) {
358                     if (yuv_palette == 0)
359                         goto fail;
360                     sub_header->rects[0]->nb_colors = 256;
361                     yuv_a_to_rgba(yuv_palette, alpha, (uint32_t*)sub_header->rects[0]->pict.data[1], 256);
362                 } else {
363                     sub_header->rects[0]->nb_colors = 4;
364                     fill_palette(ctx, sub_header->rects[0]->pict.data[1], 0xffff00);
365                 }
366                 sub_header->rects[0]->x = x1;
367                 sub_header->rects[0]->y = y1;
368                 sub_header->rects[0]->w = w;
369                 sub_header->rects[0]->h = h;
370                 sub_header->rects[0]->type = SUBTITLE_BITMAP;
371                 sub_header->rects[0]->pict.linesize[0] = w;
372             }
373         }
374         if (next_cmd_pos == cmd_pos)
375             break;
376         cmd_pos = next_cmd_pos;
377     }
378     if (sub_header->num_rects > 0)
379         return is_menu;
380  fail:
381     if (sub_header->rects != NULL) {
382         for (i = 0; i < sub_header->num_rects; i++) {
383             av_freep(&sub_header->rects[i]->pict.data[0]);
384             av_freep(&sub_header->rects[i]->pict.data[1]);
385             av_freep(&sub_header->rects[i]);
386         }
387         av_freep(&sub_header->rects);
388         sub_header->num_rects = 0;
389     }
390     return -1;
391 }
392
393 static int is_transp(const uint8_t *buf, int pitch, int n,
394                      const uint8_t *transp_color)
395 {
396     int i;
397     for(i = 0; i < n; i++) {
398         if (!transp_color[*buf])
399             return 0;
400         buf += pitch;
401     }
402     return 1;
403 }
404
405 /* return 0 if empty rectangle, 1 if non empty */
406 static int find_smallest_bounding_rectangle(AVSubtitle *s)
407 {
408     uint8_t transp_color[256];
409     int y1, y2, x1, x2, y, w, h, i;
410     uint8_t *bitmap;
411
412     if (s->num_rects == 0 || s->rects == NULL || s->rects[0]->w <= 0 || s->rects[0]->h <= 0)
413         return 0;
414
415     memset(transp_color, 0, 256);
416     for(i = 0; i < s->rects[0]->nb_colors; i++) {
417         if ((((uint32_t*)s->rects[0]->pict.data[1])[i] >> 24) == 0)
418             transp_color[i] = 1;
419     }
420     y1 = 0;
421     while (y1 < s->rects[0]->h && is_transp(s->rects[0]->pict.data[0] + y1 * s->rects[0]->pict.linesize[0],
422                                   1, s->rects[0]->w, transp_color))
423         y1++;
424     if (y1 == s->rects[0]->h) {
425         av_freep(&s->rects[0]->pict.data[0]);
426         s->rects[0]->w = s->rects[0]->h = 0;
427         return 0;
428     }
429
430     y2 = s->rects[0]->h - 1;
431     while (y2 > 0 && is_transp(s->rects[0]->pict.data[0] + y2 * s->rects[0]->pict.linesize[0], 1,
432                                s->rects[0]->w, transp_color))
433         y2--;
434     x1 = 0;
435     while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->pict.data[0] + x1, s->rects[0]->pict.linesize[0],
436                                         s->rects[0]->h, transp_color))
437         x1++;
438     x2 = s->rects[0]->w - 1;
439     while (x2 > 0 && is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0], s->rects[0]->h,
440                                   transp_color))
441         x2--;
442     w = x2 - x1 + 1;
443     h = y2 - y1 + 1;
444     bitmap = av_malloc(w * h);
445     if (!bitmap)
446         return 1;
447     for(y = 0; y < h; y++) {
448         memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 + (y1 + y) * s->rects[0]->pict.linesize[0], w);
449     }
450     av_freep(&s->rects[0]->pict.data[0]);
451     s->rects[0]->pict.data[0] = bitmap;
452     s->rects[0]->pict.linesize[0] = w;
453     s->rects[0]->w = w;
454     s->rects[0]->h = h;
455     s->rects[0]->x += x1;
456     s->rects[0]->y += y1;
457     return 1;
458 }
459
460 #ifdef DEBUG
461 #undef fprintf
462 #undef perror
463 #undef exit
464 static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
465                      uint32_t *rgba_palette)
466 {
467     int x, y, v;
468     FILE *f;
469
470     f = fopen(filename, "w");
471     if (!f) {
472         perror(filename);
473         exit(1);
474     }
475     fprintf(f, "P6\n"
476             "%d %d\n"
477             "%d\n",
478             w, h, 255);
479     for(y = 0; y < h; y++) {
480         for(x = 0; x < w; x++) {
481             v = rgba_palette[bitmap[y * w + x]];
482             putc((v >> 16) & 0xff, f);
483             putc((v >> 8) & 0xff, f);
484             putc((v >> 0) & 0xff, f);
485         }
486     }
487     fclose(f);
488 }
489 #endif
490
491 static int dvdsub_decode(AVCodecContext *avctx,
492                          void *data, int *data_size,
493                          AVPacket *avpkt)
494 {
495     DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data;
496     const uint8_t *buf = avpkt->data;
497     int buf_size = avpkt->size;
498     AVSubtitle *sub = data;
499     int is_menu;
500
501     is_menu = decode_dvd_subtitles(ctx, sub, buf, buf_size);
502
503     if (is_menu < 0) {
504     no_subtitle:
505         *data_size = 0;
506
507         return buf_size;
508     }
509     if (!is_menu && find_smallest_bounding_rectangle(sub) == 0)
510         goto no_subtitle;
511
512 #if defined(DEBUG)
513     av_dlog(NULL, "start=%d ms end =%d ms\n",
514             sub->start_display_time,
515             sub->end_display_time);
516     ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0],
517              sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]);
518 #endif
519
520     *data_size = 1;
521     return buf_size;
522 }
523
524 static int dvdsub_init(AVCodecContext *avctx)
525 {
526     DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data;
527     char *data = avctx->extradata;
528
529     if (!avctx->extradata || !avctx->extradata_size)
530         return 1;
531
532     data[avctx->extradata_size] = '\0';
533
534     for(;;) {
535         int pos = strcspn(data, "\n\r");
536         if (pos==0 && *data==0)
537             break;
538
539         if (strncmp("palette:", data, 8) == 0) {
540             int i;
541             char *p = data+8;
542             ctx->has_palette = 1;
543             for(i=0;i<16;i++) {
544                 ctx->palette[i] = strtoul(p, &p, 16);
545                 while(*p == ',' || isspace(*p))
546                     p++;
547             }
548 #if defined(DEBUG)
549             av_log(avctx, AV_LOG_INFO, "palette:");
550             for(i=0;i<16;i++)
551                 av_log(avctx, AV_LOG_WARNING, " 0x%06x", ctx->palette[i]);
552             av_log(avctx, AV_LOG_INFO, "\n");
553 #endif
554         }
555
556         data += pos;
557         data += strspn(data, "\n\r");
558     }
559
560     if(!ctx->has_palette && avctx->extradata_size == 64)
561         ayvu_to_argb((uint8_t*)avctx->extradata, ctx->palette, 16);
562
563     return 1;
564 }
565
566 AVCodec ff_dvdsub_decoder = {
567     "dvdsub",
568     AVMEDIA_TYPE_SUBTITLE,
569     CODEC_ID_DVD_SUBTITLE,
570     sizeof(DVDSubContext),
571     dvdsub_init,
572     NULL,
573     NULL,
574     dvdsub_decode,
575     .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
576 };