Mercurial > libavcodec.hg
annotate dvdsubdec.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Fri, 20 Feb 2009 16:20:01 +0000 |
parents | 367e4d405cd9 |
children | 54bc8a2727b0 |
rev | line source |
---|---|
4091 | 1 /* |
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 | 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" | |
5397 | 22 #include "bitstream.h" |
23 #include "colorspace.h" | |
24 #include "dsputil.h" | |
4091 | 25 |
26 //#define DEBUG | |
27 | |
5397 | 28 static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values) |
29 { | |
30 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; | |
31 uint8_t r, g, b; | |
32 int i, y, cb, cr; | |
33 int r_add, g_add, b_add; | |
34 | |
35 for (i = num_values; i > 0; i--) { | |
36 y = *ycbcr++; | |
37 cb = *ycbcr++; | |
38 cr = *ycbcr++; | |
39 YUV_TO_RGB1_CCIR(cb, cr); | |
40 YUV_TO_RGB2_CCIR(r, g, b, y); | |
41 *rgba++ = (*alpha++ << 24) | (r << 16) | (g << 8) | b; | |
42 } | |
43 } | |
44 | |
45 static int decode_run_2bit(GetBitContext *gb, int *color) | |
46 { | |
47 unsigned int v, t; | |
48 | |
49 v = 0; | |
50 for (t = 1; v < t && t <= 0x40; t <<= 2) | |
51 v = (v << 4) | get_bits(gb, 4); | |
52 *color = v & 3; | |
53 if (v < 4) { /* Code for fill rest of line */ | |
54 return INT_MAX; | |
55 } | |
56 return v >> 2; | |
57 } | |
58 | |
59 static int decode_run_8bit(GetBitContext *gb, int *color) | |
4091 | 60 { |
5397 | 61 int len; |
62 int has_run = get_bits1(gb); | |
63 if (get_bits1(gb)) | |
64 *color = get_bits(gb, 8); | |
65 else | |
66 *color = get_bits(gb, 2); | |
67 if (has_run) { | |
68 if (get_bits1(gb)) { | |
69 len = get_bits(gb, 7); | |
70 if (len == 0) | |
71 len = INT_MAX; | |
72 else | |
73 len += 9; | |
74 } else | |
75 len = get_bits(gb, 3) + 2; | |
76 } else | |
77 len = 1; | |
78 return len; | |
4091 | 79 } |
80 | |
81 static int decode_rle(uint8_t *bitmap, int linesize, int w, int h, | |
5397 | 82 const uint8_t *buf, int start, int buf_size, int is_8bit) |
4091 | 83 { |
5397 | 84 GetBitContext gb; |
85 int bit_len; | |
86 int x, y, len, color; | |
4091 | 87 uint8_t *d; |
88 | |
5397 | 89 bit_len = (buf_size - start) * 8; |
90 init_get_bits(&gb, buf + start, bit_len); | |
91 | |
4091 | 92 x = 0; |
93 y = 0; | |
94 d = bitmap; | |
95 for(;;) { | |
5397 | 96 if (get_bits_count(&gb) > bit_len) |
4091 | 97 return -1; |
5397 | 98 if (is_8bit) |
99 len = decode_run_8bit(&gb, &color); | |
100 else | |
101 len = decode_run_2bit(&gb, &color); | |
102 len = FFMIN(len, w - x); | |
4091 | 103 memset(d + x, color, len); |
104 x += len; | |
105 if (x >= w) { | |
106 y++; | |
107 if (y >= h) | |
108 break; | |
109 d += linesize; | |
110 x = 0; | |
111 /* byte align */ | |
5397 | 112 align_get_bits(&gb); |
4091 | 113 } |
114 } | |
115 return 0; | |
116 } | |
117 | |
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 | 120 uint8_t *alpha, |
121 uint32_t subtitle_color) | |
122 { | |
123 uint8_t color_used[16]; | |
124 int nb_opaque_colors, i, level, j, r, g, b; | |
125 | |
126 for(i = 0; i < 4; i++) | |
127 rgba_palette[i] = 0; | |
128 | |
129 memset(color_used, 0, 16); | |
130 nb_opaque_colors = 0; | |
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 | 134 nb_opaque_colors++; |
135 } | |
136 } | |
137 | |
138 if (nb_opaque_colors == 0) | |
139 return; | |
140 | |
141 j = nb_opaque_colors; | |
142 memset(color_used, 0, 16); | |
143 for(i = 0; i < 4; i++) { | |
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 | 146 level = (0xff * j) / nb_opaque_colors; |
147 r = (((subtitle_color >> 16) & 0xff) * level) >> 8; | |
148 g = (((subtitle_color >> 8) & 0xff) * level) >> 8; | |
149 b = (((subtitle_color >> 0) & 0xff) * level) >> 8; | |
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 | 152 j--; |
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 | 155 ((alpha[i] * 17) << 24); |
156 } | |
157 } | |
158 } | |
159 } | |
160 | |
5397 | 161 #define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a)) |
162 | |
4091 | 163 static int decode_dvd_subtitles(AVSubtitle *sub_header, |
164 const uint8_t *buf, int buf_size) | |
165 { | |
166 int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos; | |
5397 | 167 int big_offsets, offset_size, is_8bit = 0; |
168 const uint8_t *yuv_palette = 0; | |
169 uint8_t colormap[4], alpha[256]; | |
4091 | 170 int date; |
171 int i; | |
172 int is_menu = 0; | |
173 | |
5397 | 174 if (buf_size < 10) |
4091 | 175 return -1; |
176 sub_header->rects = NULL; | |
177 sub_header->num_rects = 0; | |
8810
367e4d405cd9
Set AVSubtitle format to 0. Neither dvdsubdec nor xsubdec intializes format
diego
parents:
8629
diff
changeset
|
178 sub_header->format = 0; |
4091 | 179 sub_header->start_display_time = 0; |
180 sub_header->end_display_time = 0; | |
181 | |
5397 | 182 if (AV_RB16(buf) == 0) { /* HD subpicture with 4-byte offsets */ |
183 big_offsets = 1; | |
184 offset_size = 4; | |
185 cmd_pos = 6; | |
186 } else { | |
187 big_offsets = 0; | |
188 offset_size = 2; | |
189 cmd_pos = 2; | |
190 } | |
191 | |
192 cmd_pos = READ_OFFSET(buf + cmd_pos); | |
193 | |
194 while ((cmd_pos + 2 + offset_size) < buf_size) { | |
4438
fe3179006730
Remove the getbe16 functions and use the AV_RB16 macro instead. Patch by Ian
takis
parents:
4437
diff
changeset
|
195 date = AV_RB16(buf + cmd_pos); |
5397 | 196 next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2); |
4091 | 197 #ifdef DEBUG |
198 av_log(NULL, AV_LOG_INFO, "cmd_pos=0x%04x next=0x%04x date=%d\n", | |
199 cmd_pos, next_cmd_pos, date); | |
200 #endif | |
5397 | 201 pos = cmd_pos + 2 + offset_size; |
4091 | 202 offset1 = -1; |
203 offset2 = -1; | |
204 x1 = y1 = x2 = y2 = 0; | |
205 while (pos < buf_size) { | |
206 cmd = buf[pos++]; | |
207 #ifdef DEBUG | |
208 av_log(NULL, AV_LOG_INFO, "cmd=%02x\n", cmd); | |
209 #endif | |
210 switch(cmd) { | |
211 case 0x00: | |
212 /* menu subpicture */ | |
213 is_menu = 1; | |
214 break; | |
215 case 0x01: | |
216 /* set start date */ | |
217 sub_header->start_display_time = (date << 10) / 90; | |
218 break; | |
219 case 0x02: | |
220 /* set end date */ | |
221 sub_header->end_display_time = (date << 10) / 90; | |
222 break; | |
223 case 0x03: | |
5396
9f0f022ca8e7
Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents:
4924
diff
changeset
|
224 /* set colormap */ |
4091 | 225 if ((buf_size - pos) < 2) |
226 goto fail; | |
5396
9f0f022ca8e7
Rename "palette" to "colormap" when it's referring to the mapping from a 2-bit
takis
parents:
4924
diff
changeset
|
227 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
|
228 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
|
229 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
|
230 colormap[0] = buf[pos + 1] & 0x0f; |
4091 | 231 pos += 2; |
232 break; | |
233 case 0x04: | |
234 /* set alpha */ | |
235 if ((buf_size - pos) < 2) | |
236 goto fail; | |
237 alpha[3] = buf[pos] >> 4; | |
238 alpha[2] = buf[pos] & 0x0f; | |
239 alpha[1] = buf[pos + 1] >> 4; | |
240 alpha[0] = buf[pos + 1] & 0x0f; | |
241 pos += 2; | |
242 #ifdef DEBUG | |
243 av_log(NULL, AV_LOG_INFO, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]); | |
244 #endif | |
245 break; | |
246 case 0x05: | |
5397 | 247 case 0x85: |
4091 | 248 if ((buf_size - pos) < 6) |
249 goto fail; | |
250 x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4); | |
251 x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2]; | |
252 y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4); | |
253 y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5]; | |
5397 | 254 if (cmd & 0x80) |
255 is_8bit = 1; | |
4091 | 256 #ifdef DEBUG |
257 av_log(NULL, AV_LOG_INFO, "x1=%d x2=%d y1=%d y2=%d\n", | |
258 x1, x2, y1, y2); | |
259 #endif | |
260 pos += 6; | |
261 break; | |
262 case 0x06: | |
263 if ((buf_size - pos) < 4) | |
264 goto fail; | |
4438
fe3179006730
Remove the getbe16 functions and use the AV_RB16 macro instead. Patch by Ian
takis
parents:
4437
diff
changeset
|
265 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
|
266 offset2 = AV_RB16(buf + pos + 2); |
4091 | 267 #ifdef DEBUG |
268 av_log(NULL, AV_LOG_INFO, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); | |
269 #endif | |
270 pos += 4; | |
271 break; | |
5397 | 272 case 0x86: |
273 if ((buf_size - pos) < 8) | |
274 goto fail; | |
275 offset1 = AV_RB32(buf + pos); | |
276 offset2 = AV_RB32(buf + pos + 4); | |
277 #ifdef DEBUG | |
278 av_log(NULL, AV_LOG_INFO, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); | |
279 #endif | |
280 pos += 8; | |
281 break; | |
282 | |
283 case 0x83: | |
284 /* HD set palette */ | |
285 if ((buf_size - pos) < 768) | |
286 goto fail; | |
287 yuv_palette = buf + pos; | |
288 pos += 768; | |
289 break; | |
290 case 0x84: | |
291 /* HD set contrast (alpha) */ | |
292 if ((buf_size - pos) < 256) | |
293 goto fail; | |
294 for (i = 0; i < 256; i++) | |
295 alpha[i] = 0xFF - buf[pos+i]; | |
296 pos += 256; | |
297 break; | |
298 | |
4091 | 299 case 0xff: |
5397 | 300 goto the_end; |
4091 | 301 default: |
5397 | 302 #ifdef DEBUG |
303 av_log(NULL, AV_LOG_INFO, "unrecognised subpicture command 0x%x\n", cmd); | |
304 #endif | |
4091 | 305 goto the_end; |
306 } | |
307 } | |
308 the_end: | |
309 if (offset1 >= 0) { | |
310 int w, h; | |
311 uint8_t *bitmap; | |
312 | |
313 /* decode the bitmap */ | |
314 w = x2 - x1 + 1; | |
315 if (w < 0) | |
316 w = 0; | |
317 h = y2 - y1; | |
318 if (h < 0) | |
319 h = 0; | |
320 if (w > 0 && h > 0) { | |
321 if (sub_header->rects != NULL) { | |
322 for (i = 0; i < sub_header->num_rects; i++) { | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
323 av_freep(&sub_header->rects[i]->pict.data[0]); |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
324 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
|
325 av_freep(&sub_header->rects[i]); |
4091 | 326 } |
327 av_freep(&sub_header->rects); | |
328 sub_header->num_rects = 0; | |
329 } | |
330 | |
331 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
|
332 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
|
333 sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect)); |
4091 | 334 sub_header->num_rects = 1; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
335 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
|
336 decode_rle(bitmap, w * 2, w, (h + 1) / 2, |
5397 | 337 buf, offset1, buf_size, is_8bit); |
4091 | 338 decode_rle(bitmap + w, w * 2, w, h / 2, |
5397 | 339 buf, offset2, buf_size, is_8bit); |
340 if (is_8bit) { | |
341 if (yuv_palette == 0) | |
342 goto fail; | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
343 sub_header->rects[0]->pict.data[1] = av_malloc(256 * 4); |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
344 sub_header->rects[0]->nb_colors = 256; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
345 yuv_a_to_rgba(yuv_palette, alpha, (uint32_t*)sub_header->rects[0]->pict.data[1], 256); |
5397 | 346 } else { |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
347 sub_header->rects[0]->pict.data[1] = av_malloc(4 * 4); |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
348 sub_header->rects[0]->nb_colors = 4; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
349 guess_palette((uint32_t*)sub_header->rects[0]->pict.data[1], |
5398 | 350 colormap, alpha, 0xffff00); |
5397 | 351 } |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
352 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
|
353 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
|
354 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
|
355 sub_header->rects[0]->h = h; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
356 sub_header->rects[0]->pict.linesize[0] = w; |
4091 | 357 } |
358 } | |
359 if (next_cmd_pos == cmd_pos) | |
360 break; | |
361 cmd_pos = next_cmd_pos; | |
362 } | |
363 if (sub_header->num_rects > 0) | |
364 return is_menu; | |
365 fail: | |
5397 | 366 if (sub_header->rects != NULL) { |
367 for (i = 0; i < sub_header->num_rects; i++) { | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
368 av_freep(&sub_header->rects[i]->pict.data[0]); |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
369 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
|
370 av_freep(&sub_header->rects[i]); |
5397 | 371 } |
372 av_freep(&sub_header->rects); | |
373 sub_header->num_rects = 0; | |
374 } | |
4091 | 375 return -1; |
376 } | |
377 | |
378 static int is_transp(const uint8_t *buf, int pitch, int n, | |
379 const uint8_t *transp_color) | |
380 { | |
381 int i; | |
382 for(i = 0; i < n; i++) { | |
383 if (!transp_color[*buf]) | |
384 return 0; | |
385 buf += pitch; | |
386 } | |
387 return 1; | |
388 } | |
389 | |
390 /* return 0 if empty rectangle, 1 if non empty */ | |
391 static int find_smallest_bounding_rectangle(AVSubtitle *s) | |
392 { | |
393 uint8_t transp_color[256]; | |
394 int y1, y2, x1, x2, y, w, h, i; | |
395 uint8_t *bitmap; | |
396 | |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
397 if (s->num_rects == 0 || s->rects == NULL || s->rects[0]->w <= 0 || s->rects[0]->h <= 0) |
4091 | 398 return 0; |
399 | |
400 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
|
401 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
|
402 if ((((uint32_t*)s->rects[0]->pict.data[1])[i] >> 24) == 0) |
4091 | 403 transp_color[i] = 1; |
404 } | |
405 y1 = 0; | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
406 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
|
407 1, s->rects[0]->w, transp_color)) |
4091 | 408 y1++; |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
409 if (y1 == s->rects[0]->h) { |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
410 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
|
411 s->rects[0]->w = s->rects[0]->h = 0; |
4091 | 412 return 0; |
413 } | |
414 | |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
415 y2 = s->rects[0]->h - 1; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
416 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
|
417 s->rects[0]->w, transp_color)) |
4091 | 418 y2--; |
419 x1 = 0; | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
420 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
|
421 s->rects[0]->h, transp_color)) |
4091 | 422 x1++; |
8514
b866cb2a5330
Forgot to update (I likely missed it due to its similar name to dvb...)
michael
parents:
7264
diff
changeset
|
423 x2 = s->rects[0]->w - 1; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
424 while (x2 > 0 && is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0], s->rects[0]->h, |
4091 | 425 transp_color)) |
426 x2--; | |
427 w = x2 - x1 + 1; | |
428 h = y2 - y1 + 1; | |
429 bitmap = av_malloc(w * h); | |
430 if (!bitmap) | |
431 return 1; | |
432 for(y = 0; y < h; y++) { | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
433 memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 + (y1 + y) * s->rects[0]->pict.linesize[0], w); |
4091 | 434 } |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
435 av_freep(&s->rects[0]->pict.data[0]); |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
436 s->rects[0]->pict.data[0] = bitmap; |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
437 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
|
438 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
|
439 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
|
440 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
|
441 s->rects[0]->y += y1; |
4091 | 442 return 1; |
443 } | |
444 | |
445 #ifdef DEBUG | |
446 #undef fprintf | |
7264 | 447 #undef perror |
448 #undef exit | |
4091 | 449 static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, |
450 uint32_t *rgba_palette) | |
451 { | |
452 int x, y, v; | |
453 FILE *f; | |
454 | |
455 f = fopen(filename, "w"); | |
456 if (!f) { | |
457 perror(filename); | |
458 exit(1); | |
459 } | |
460 fprintf(f, "P6\n" | |
461 "%d %d\n" | |
462 "%d\n", | |
463 w, h, 255); | |
464 for(y = 0; y < h; y++) { | |
465 for(x = 0; x < w; x++) { | |
466 v = rgba_palette[bitmap[y * w + x]]; | |
467 putc((v >> 16) & 0xff, f); | |
468 putc((v >> 8) & 0xff, f); | |
469 putc((v >> 0) & 0xff, f); | |
470 } | |
471 } | |
472 fclose(f); | |
473 } | |
474 #endif | |
475 | |
476 static int dvdsub_decode(AVCodecContext *avctx, | |
477 void *data, int *data_size, | |
6218 | 478 const uint8_t *buf, int buf_size) |
4091 | 479 { |
480 AVSubtitle *sub = (void *)data; | |
481 int is_menu; | |
482 | |
483 is_menu = decode_dvd_subtitles(sub, buf, buf_size); | |
484 | |
485 if (is_menu < 0) { | |
486 no_subtitle: | |
487 *data_size = 0; | |
488 | |
489 return buf_size; | |
490 } | |
491 if (!is_menu && find_smallest_bounding_rectangle(sub) == 0) | |
492 goto no_subtitle; | |
493 | |
494 #if defined(DEBUG) | |
495 av_log(NULL, AV_LOG_INFO, "start=%d ms end =%d ms\n", | |
496 sub->start_display_time, | |
497 sub->end_display_time); | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8514
diff
changeset
|
498 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
|
499 sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]); |
4091 | 500 #endif |
501 | |
502 *data_size = 1; | |
503 return buf_size; | |
504 } | |
505 | |
506 AVCodec dvdsub_decoder = { | |
507 "dvdsub", | |
508 CODEC_TYPE_SUBTITLE, | |
509 CODEC_ID_DVD_SUBTITLE, | |
510 0, | |
5941 | 511 NULL, |
4091 | 512 NULL, |
5941 | 513 NULL, |
4091 | 514 dvdsub_decode, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
515 .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), |
4091 | 516 }; |