annotate dvdsubdec.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents de55a539a2e1
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
1 /*
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
2 * DVD subtitle decoding for ffmpeg
8629
04423b2f6e0b cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents: 8516
diff changeset
3 * Copyright (c) 2005 Fabrice Bellard
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
4 *
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
5 * This file is part of FFmpeg.
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
6 *
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
11 *
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
15 * Lesser General Public License for more details.
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
16 *
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
20 */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
21 #include "avcodec.h"
9428
0dce4fe6e6f3 Rename bitstream.h to get_bits.h.
stefano
parents: 9355
diff changeset
22 #include "get_bits.h"
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
23 #include "dsputil.h"
12039
d5705b52b76e Move colorspace.h from libavcodec to libavutil.
stefano
parents: 11560
diff changeset
24 #include "libavutil/colorspace.h"
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
25
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
26 //#define DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
27
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
28 static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
29 {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
30 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
31 uint8_t r, g, b;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
32 int i, y, cb, cr;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
33 int r_add, g_add, b_add;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
34
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
35 for (i = num_values; i > 0; i--) {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
36 y = *ycbcr++;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
37 cb = *ycbcr++;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
38 cr = *ycbcr++;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
39 YUV_TO_RGB1_CCIR(cb, cr);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
40 YUV_TO_RGB2_CCIR(r, g, b, y);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
41 *rgba++ = (*alpha++ << 24) | (r << 16) | (g << 8) | b;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
42 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
43 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
44
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
45 static int decode_run_2bit(GetBitContext *gb, int *color)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
46 {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
47 unsigned int v, t;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
48
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
49 v = 0;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
50 for (t = 1; v < t && t <= 0x40; t <<= 2)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
51 v = (v << 4) | get_bits(gb, 4);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
52 *color = v & 3;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
53 if (v < 4) { /* Code for fill rest of line */
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
54 return INT_MAX;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
55 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
56 return v >> 2;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
57 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
58
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
59 static int decode_run_8bit(GetBitContext *gb, int *color)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
60 {
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
61 int len;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
62 int has_run = get_bits1(gb);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
63 if (get_bits1(gb))
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
64 *color = get_bits(gb, 8);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
65 else
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
66 *color = get_bits(gb, 2);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
67 if (has_run) {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
68 if (get_bits1(gb)) {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
69 len = get_bits(gb, 7);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
70 if (len == 0)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
71 len = INT_MAX;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
72 else
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
73 len += 9;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
74 } else
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
75 len = get_bits(gb, 3) + 2;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
76 } else
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
77 len = 1;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
78 return len;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
79 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
80
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
81 static int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
82 const uint8_t *buf, int start, int buf_size, int is_8bit)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
83 {
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
84 GetBitContext gb;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
85 int bit_len;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
86 int x, y, len, color;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
87 uint8_t *d;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
88
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
89 bit_len = (buf_size - start) * 8;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
90 init_get_bits(&gb, buf + start, bit_len);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
91
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
92 x = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
93 y = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
94 d = bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
95 for(;;) {
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
96 if (get_bits_count(&gb) > bit_len)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
97 return -1;
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
98 if (is_8bit)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
99 len = decode_run_8bit(&gb, &color);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
100 else
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
101 len = decode_run_2bit(&gb, &color);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
102 len = FFMIN(len, w - x);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
103 memset(d + x, color, len);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
104 x += len;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
105 if (x >= w) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
106 y++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
107 if (y >= h)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
108 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
109 d += linesize;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
110 x = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
111 /* byte align */
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
112 align_get_bits(&gb);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
113 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
114 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
115 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
116 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
117
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
118 static void guess_palette(uint32_t *rgba_palette,
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
119 uint8_t *colormap,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
120 uint8_t *alpha,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
121 uint32_t subtitle_color)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
122 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
123 uint8_t color_used[16];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
124 int nb_opaque_colors, i, level, j, r, g, b;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
125
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
126 for(i = 0; i < 4; i++)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
127 rgba_palette[i] = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
128
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
129 memset(color_used, 0, 16);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
130 nb_opaque_colors = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
131 for(i = 0; i < 4; i++) {
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
132 if (alpha[i] != 0 && !color_used[colormap[i]]) {
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
133 color_used[colormap[i]] = 1;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
134 nb_opaque_colors++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
135 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
136 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
137
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
138 if (nb_opaque_colors == 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
139 return;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
140
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
141 j = nb_opaque_colors;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
142 memset(color_used, 0, 16);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
143 for(i = 0; i < 4; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
144 if (alpha[i] != 0) {
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
145 if (!color_used[colormap[i]]) {
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
146 level = (0xff * j) / nb_opaque_colors;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
147 r = (((subtitle_color >> 16) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
148 g = (((subtitle_color >> 8) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
149 b = (((subtitle_color >> 0) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
150 rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24);
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
151 color_used[colormap[i]] = (i + 1);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
152 j--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
153 } else {
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
154 rgba_palette[i] = (rgba_palette[color_used[colormap[i]] - 1] & 0x00ffffff) |
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
155 ((alpha[i] * 17) << 24);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
156 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
157 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
158 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
159 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
160
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
161 #define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a))
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
162
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
163 static int decode_dvd_subtitles(AVSubtitle *sub_header,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
164 const uint8_t *buf, int buf_size)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
165 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
166 int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos;
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
167 int big_offsets, offset_size, is_8bit = 0;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
168 const uint8_t *yuv_palette = 0;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
169 uint8_t colormap[4], alpha[256];
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
170 int date;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
171 int i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
172 int is_menu = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
173
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
174 if (buf_size < 10)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
175 return -1;
10051
e73c688ca84c Simplify initialization of AVSubtitle by using memset.
reimar
parents: 10049
diff changeset
176 memset(sub_header, 0, sizeof(*sub_header));
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
177
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
178 if (AV_RB16(buf) == 0) { /* HD subpicture with 4-byte offsets */
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
179 big_offsets = 1;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
180 offset_size = 4;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
181 cmd_pos = 6;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
182 } else {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
183 big_offsets = 0;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
184 offset_size = 2;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
185 cmd_pos = 2;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
186 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
187
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
188 cmd_pos = READ_OFFSET(buf + cmd_pos);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
189
10049
a1b42791b13d Fix cmd_pos bounds check to avoid the overflow case.
reimar
parents: 9999
diff changeset
190 while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) {
4438
fe3179006730 Remove the getbe16 functions and use the AV_RB16 macro instead. Patch by Ian
takis
parents: 4437
diff changeset
191 date = AV_RB16(buf + cmd_pos);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
192 next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2);
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
193 dprintf(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n",
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
194 cmd_pos, next_cmd_pos, date);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
195 pos = cmd_pos + 2 + offset_size;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
196 offset1 = -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
197 offset2 = -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
198 x1 = y1 = x2 = y2 = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
199 while (pos < buf_size) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
200 cmd = buf[pos++];
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
201 dprintf(NULL, "cmd=%02x\n", cmd);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
202 switch(cmd) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
203 case 0x00:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
204 /* menu subpicture */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
205 is_menu = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
206 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
207 case 0x01:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
208 /* set start date */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
209 sub_header->start_display_time = (date << 10) / 90;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
210 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
211 case 0x02:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
212 /* set end date */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
213 sub_header->end_display_time = (date << 10) / 90;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
214 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
215 case 0x03:
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
216 /* set colormap */
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
217 if ((buf_size - pos) < 2)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
218 goto fail;
5396
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
219 colormap[3] = buf[pos] >> 4;
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
220 colormap[2] = buf[pos] & 0x0f;
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
221 colormap[1] = buf[pos + 1] >> 4;
9f0f022ca8e7 Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents: 4924
diff changeset
222 colormap[0] = buf[pos + 1] & 0x0f;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
223 pos += 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
224 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
225 case 0x04:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
226 /* set alpha */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
227 if ((buf_size - pos) < 2)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
228 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
229 alpha[3] = buf[pos] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
230 alpha[2] = buf[pos] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
231 alpha[1] = buf[pos + 1] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
232 alpha[0] = buf[pos + 1] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
233 pos += 2;
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
234 dprintf(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
235 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
236 case 0x05:
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
237 case 0x85:
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
238 if ((buf_size - pos) < 6)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
239 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
240 x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
241 x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
242 y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
243 y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5];
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
244 if (cmd & 0x80)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
245 is_8bit = 1;
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
246 dprintf(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
247 pos += 6;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
248 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
249 case 0x06:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
250 if ((buf_size - pos) < 4)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
251 goto fail;
4438
fe3179006730 Remove the getbe16 functions and use the AV_RB16 macro instead. Patch by Ian
takis
parents: 4437
diff changeset
252 offset1 = AV_RB16(buf + pos);
fe3179006730 Remove the getbe16 functions and use the AV_RB16 macro instead. Patch by Ian
takis
parents: 4437
diff changeset
253 offset2 = AV_RB16(buf + pos + 2);
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
254 dprintf(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
255 pos += 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
256 break;
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
257 case 0x86:
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
258 if ((buf_size - pos) < 8)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
259 goto fail;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
260 offset1 = AV_RB32(buf + pos);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
261 offset2 = AV_RB32(buf + pos + 4);
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
262 dprintf(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
263 pos += 8;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
264 break;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
265
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
266 case 0x83:
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
267 /* HD set palette */
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
268 if ((buf_size - pos) < 768)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
269 goto fail;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
270 yuv_palette = buf + pos;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
271 pos += 768;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
272 break;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
273 case 0x84:
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
274 /* HD set contrast (alpha) */
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
275 if ((buf_size - pos) < 256)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
276 goto fail;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
277 for (i = 0; i < 256; i++)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
278 alpha[i] = 0xFF - buf[pos+i];
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
279 pos += 256;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
280 break;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
281
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
282 case 0xff:
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
283 goto the_end;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
284 default:
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
285 dprintf(NULL, "unrecognised subpicture command 0x%x\n", cmd);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
286 goto the_end;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
287 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
288 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
289 the_end:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
290 if (offset1 >= 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
291 int w, h;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
292 uint8_t *bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
293
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
294 /* decode the bitmap */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
295 w = x2 - x1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
296 if (w < 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
297 w = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
298 h = y2 - y1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
299 if (h < 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
300 h = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
301 if (w > 0 && h > 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
302 if (sub_header->rects != NULL) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
303 for (i = 0; i < sub_header->num_rects; i++) {
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
304 av_freep(&sub_header->rects[i]->pict.data[0]);
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
305 av_freep(&sub_header->rects[i]->pict.data[1]);
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
306 av_freep(&sub_header->rects[i]);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
307 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
308 av_freep(&sub_header->rects);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
309 sub_header->num_rects = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
310 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
311
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
312 bitmap = av_malloc(w * h);
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
313 sub_header->rects = av_mallocz(sizeof(*sub_header->rects));
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
314 sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect));
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
315 sub_header->num_rects = 1;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
316 sub_header->rects[0]->pict.data[0] = bitmap;
4437
42ad7d63fb5d Fix a bug in the DVD subtitle decoder where subtitles with odd heights would not
takis
parents: 4091
diff changeset
317 decode_rle(bitmap, w * 2, w, (h + 1) / 2,
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
318 buf, offset1, buf_size, is_8bit);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
319 decode_rle(bitmap + w, w * 2, w, h / 2,
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
320 buf, offset2, buf_size, is_8bit);
10069
8ac9bc10b485 Always allocate a buffer of AVPALETTE_SIZE for palette in the subtitle
reimar
parents: 10051
diff changeset
321 sub_header->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
322 if (is_8bit) {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
323 if (yuv_palette == 0)
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
324 goto fail;
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
325 sub_header->rects[0]->nb_colors = 256;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
326 yuv_a_to_rgba(yuv_palette, alpha, (uint32_t*)sub_header->rects[0]->pict.data[1], 256);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
327 } else {
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
328 sub_header->rects[0]->nb_colors = 4;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
329 guess_palette((uint32_t*)sub_header->rects[0]->pict.data[1],
5398
392483301260 Reindent two lines.
takis
parents: 5397
diff changeset
330 colormap, alpha, 0xffff00);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
331 }
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
332 sub_header->rects[0]->x = x1;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
333 sub_header->rects[0]->y = y1;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
334 sub_header->rects[0]->w = w;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
335 sub_header->rects[0]->h = h;
9988
b8a9cfe64488 Set subtitle type in DVD and XSUB subtitle decoders.
stefano
parents: 9428
diff changeset
336 sub_header->rects[0]->type = SUBTITLE_BITMAP;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
337 sub_header->rects[0]->pict.linesize[0] = w;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
338 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
339 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
340 if (next_cmd_pos == cmd_pos)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
341 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
342 cmd_pos = next_cmd_pos;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
343 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
344 if (sub_header->num_rects > 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
345 return is_menu;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
346 fail:
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
347 if (sub_header->rects != NULL) {
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
348 for (i = 0; i < sub_header->num_rects; i++) {
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
349 av_freep(&sub_header->rects[i]->pict.data[0]);
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
350 av_freep(&sub_header->rects[i]->pict.data[1]);
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
351 av_freep(&sub_header->rects[i]);
5397
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
352 }
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
353 av_freep(&sub_header->rects);
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
354 sub_header->num_rects = 0;
31f367bf1a99 Add HD-DVD subpicture decoding.
takis
parents: 5396
diff changeset
355 }
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
356 return -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
357 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
358
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
359 static int is_transp(const uint8_t *buf, int pitch, int n,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
360 const uint8_t *transp_color)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
361 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
362 int i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
363 for(i = 0; i < n; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
364 if (!transp_color[*buf])
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
365 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
366 buf += pitch;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
367 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
368 return 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
369 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
370
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
371 /* return 0 if empty rectangle, 1 if non empty */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
372 static int find_smallest_bounding_rectangle(AVSubtitle *s)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
373 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
374 uint8_t transp_color[256];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
375 int y1, y2, x1, x2, y, w, h, i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
376 uint8_t *bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
377
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
378 if (s->num_rects == 0 || s->rects == NULL || s->rects[0]->w <= 0 || s->rects[0]->h <= 0)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
379 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
380
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
381 memset(transp_color, 0, 256);
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
382 for(i = 0; i < s->rects[0]->nb_colors; i++) {
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
383 if ((((uint32_t*)s->rects[0]->pict.data[1])[i] >> 24) == 0)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
384 transp_color[i] = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
385 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
386 y1 = 0;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
387 while (y1 < s->rects[0]->h && is_transp(s->rects[0]->pict.data[0] + y1 * s->rects[0]->pict.linesize[0],
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
388 1, s->rects[0]->w, transp_color))
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
389 y1++;
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
390 if (y1 == s->rects[0]->h) {
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
391 av_freep(&s->rects[0]->pict.data[0]);
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
392 s->rects[0]->w = s->rects[0]->h = 0;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
393 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
394 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
395
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
396 y2 = s->rects[0]->h - 1;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
397 while (y2 > 0 && is_transp(s->rects[0]->pict.data[0] + y2 * s->rects[0]->pict.linesize[0], 1,
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
398 s->rects[0]->w, transp_color))
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
399 y2--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
400 x1 = 0;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
401 while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->pict.data[0] + x1, s->rects[0]->pict.linesize[0],
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
402 s->rects[0]->h, transp_color))
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
403 x1++;
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
404 x2 = s->rects[0]->w - 1;
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
405 while (x2 > 0 && is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0], s->rects[0]->h,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
406 transp_color))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
407 x2--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
408 w = x2 - x1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
409 h = y2 - y1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
410 bitmap = av_malloc(w * h);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
411 if (!bitmap)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
412 return 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
413 for(y = 0; y < h; y++) {
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
414 memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 + (y1 + y) * s->rects[0]->pict.linesize[0], w);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
415 }
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
416 av_freep(&s->rects[0]->pict.data[0]);
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
417 s->rects[0]->pict.data[0] = bitmap;
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
418 s->rects[0]->pict.linesize[0] = w;
8514
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
419 s->rects[0]->w = w;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
420 s->rects[0]->h = h;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
421 s->rects[0]->x += x1;
b866cb2a5330 Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents: 7264
diff changeset
422 s->rects[0]->y += y1;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
423 return 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
424 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
425
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
426 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
427 #undef fprintf
7264
a9ca5a1b8a1e dvdsubdec: allow compilation with -DDEBUG
mru
parents: 7040
diff changeset
428 #undef perror
a9ca5a1b8a1e dvdsubdec: allow compilation with -DDEBUG
mru
parents: 7040
diff changeset
429 #undef exit
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
430 static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
431 uint32_t *rgba_palette)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
432 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
433 int x, y, v;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
434 FILE *f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
435
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
436 f = fopen(filename, "w");
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
437 if (!f) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
438 perror(filename);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
439 exit(1);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
440 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
441 fprintf(f, "P6\n"
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
442 "%d %d\n"
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
443 "%d\n",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
444 w, h, 255);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
445 for(y = 0; y < h; y++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
446 for(x = 0; x < w; x++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
447 v = rgba_palette[bitmap[y * w + x]];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
448 putc((v >> 16) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
449 putc((v >> 8) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
450 putc((v >> 0) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
451 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
452 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
453 fclose(f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
454 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
455 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
456
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
457 static int dvdsub_decode(AVCodecContext *avctx,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
458 void *data, int *data_size,
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8810
diff changeset
459 AVPacket *avpkt)
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
460 {
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8810
diff changeset
461 const uint8_t *buf = avpkt->data;
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8810
diff changeset
462 int buf_size = avpkt->size;
12285
de55a539a2e1 remove useless cast
aurel
parents: 12039
diff changeset
463 AVSubtitle *sub = data;
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
464 int is_menu;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
465
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
466 is_menu = decode_dvd_subtitles(sub, buf, buf_size);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
467
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
468 if (is_menu < 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
469 no_subtitle:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
470 *data_size = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
471
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
472 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
473 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
474 if (!is_menu && find_smallest_bounding_rectangle(sub) == 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
475 goto no_subtitle;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
476
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
477 #if defined(DEBUG)
9999
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
478 dprintf(NULL, "start=%d ms end =%d ms\n",
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
479 sub->start_display_time,
c78fd9154378 Change av_log() calls surrounded by '#ifdef DEBUG' into dprintf macros.
diego
parents: 9988
diff changeset
480 sub->end_display_time);
8516
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
481 ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0],
315b302fcd1d Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents: 8514
diff changeset
482 sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]);
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
483 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
484
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
485 *data_size = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
486 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
487 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
488
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
489 AVCodec dvdsub_decoder = {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
490 "dvdsub",
11560
8a4984c5cacc Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 10069
diff changeset
491 AVMEDIA_TYPE_SUBTITLE,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
492 CODEC_ID_DVD_SUBTITLE,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
493 0,
5941
d030978bcd93 remove some empty close/init functions in avcodec
aurel
parents: 5398
diff changeset
494 NULL,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
495 NULL,
5941
d030978bcd93 remove some empty close/init functions in avcodec
aurel
parents: 5398
diff changeset
496 NULL,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
497 dvdsub_decode,
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6712
diff changeset
498 .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
499 };