annotate dvdsubdec.c @ 4437:42ad7d63fb5d libavcodec

Fix a bug in the DVD subtitle decoder where subtitles with odd heights would not have the last line decoded, leaving the bottom line of the bitmap array uninitialised. Patch by Ian Caulfield, ian dot caulfield gmail dot com.
author takis
date Tue, 30 Jan 2007 14:19:43 +0000
parents 3c00eb82db0d
children fe3179006730
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
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
3 * Copyright (c) 2005 Fabrice Bellard.
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"
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
22
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
23 //#define DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
24
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
25 static int dvdsub_init_decoder(AVCodecContext *avctx)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
26 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
27 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
28 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
29
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
30 static uint16_t getbe16(const uint8_t *p)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
31 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
32 return (p[0] << 8) | p[1];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
33 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
34
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
35 static int get_nibble(const uint8_t *buf, int nibble_offset)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
36 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
37 return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
38 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
39
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
40 static int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
41 const uint8_t *buf, int nibble_offset, int buf_size)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
42 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
43 unsigned int v;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
44 int x, y, len, color, nibble_end;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
45 uint8_t *d;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
46
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
47 nibble_end = buf_size * 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
48 x = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
49 y = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
50 d = bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
51 for(;;) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
52 if (nibble_offset >= nibble_end)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
53 return -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
54 v = get_nibble(buf, nibble_offset++);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
55 if (v < 0x4) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
56 v = (v << 4) | get_nibble(buf, nibble_offset++);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
57 if (v < 0x10) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
58 v = (v << 4) | get_nibble(buf, nibble_offset++);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
59 if (v < 0x040) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
60 v = (v << 4) | get_nibble(buf, nibble_offset++);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
61 if (v < 4) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
62 v |= (w - x) << 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
63 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
64 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
65 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
66 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
67 len = v >> 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
68 if (len > (w - x))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
69 len = (w - x);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
70 color = v & 0x03;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
71 memset(d + x, color, len);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
72 x += len;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
73 if (x >= w) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
74 y++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
75 if (y >= h)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
76 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
77 d += linesize;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
78 x = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
79 /* byte align */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
80 nibble_offset += (nibble_offset & 1);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
81 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
82 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
83 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
84 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
85
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
86 static void guess_palette(uint32_t *rgba_palette,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
87 uint8_t *palette,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
88 uint8_t *alpha,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
89 uint32_t subtitle_color)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
90 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
91 uint8_t color_used[16];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
92 int nb_opaque_colors, i, level, j, r, g, b;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
93
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
94 for(i = 0; i < 4; i++)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
95 rgba_palette[i] = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
96
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
97 memset(color_used, 0, 16);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
98 nb_opaque_colors = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
99 for(i = 0; i < 4; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
100 if (alpha[i] != 0 && !color_used[palette[i]]) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
101 color_used[palette[i]] = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
102 nb_opaque_colors++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
103 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
104 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
105
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
106 if (nb_opaque_colors == 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
107 return;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
108
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
109 j = nb_opaque_colors;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
110 memset(color_used, 0, 16);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
111 for(i = 0; i < 4; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
112 if (alpha[i] != 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
113 if (!color_used[palette[i]]) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
114 level = (0xff * j) / nb_opaque_colors;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
115 r = (((subtitle_color >> 16) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
116 g = (((subtitle_color >> 8) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
117 b = (((subtitle_color >> 0) & 0xff) * level) >> 8;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
118 rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
119 color_used[palette[i]] = (i + 1);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
120 j--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
121 } else {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
122 rgba_palette[i] = (rgba_palette[color_used[palette[i]] - 1] & 0x00ffffff) |
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
123 ((alpha[i] * 17) << 24);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
124 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
125 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
126 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
127 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
128
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
129 static int decode_dvd_subtitles(AVSubtitle *sub_header,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
130 const uint8_t *buf, int buf_size)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
131 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
132 int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
133 uint8_t palette[4], alpha[4];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
134 int date;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
135 int i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
136 int is_menu = 0;
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 (buf_size < 4)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
139 return -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
140 sub_header->rects = NULL;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
141 sub_header->num_rects = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
142 sub_header->start_display_time = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
143 sub_header->end_display_time = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
144
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
145 cmd_pos = getbe16(buf + 2);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
146 while ((cmd_pos + 4) < buf_size) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
147 date = getbe16(buf + cmd_pos);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
148 next_cmd_pos = getbe16(buf + cmd_pos + 2);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
149 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
150 av_log(NULL, AV_LOG_INFO, "cmd_pos=0x%04x next=0x%04x date=%d\n",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
151 cmd_pos, next_cmd_pos, date);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
152 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
153 pos = cmd_pos + 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
154 offset1 = -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
155 offset2 = -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
156 x1 = y1 = x2 = y2 = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
157 while (pos < buf_size) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
158 cmd = buf[pos++];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
159 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
160 av_log(NULL, AV_LOG_INFO, "cmd=%02x\n", cmd);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
161 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
162 switch(cmd) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
163 case 0x00:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
164 /* menu subpicture */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
165 is_menu = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
166 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
167 case 0x01:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
168 /* set start date */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
169 sub_header->start_display_time = (date << 10) / 90;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
170 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
171 case 0x02:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
172 /* set end date */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
173 sub_header->end_display_time = (date << 10) / 90;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
174 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
175 case 0x03:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
176 /* set palette */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
177 if ((buf_size - pos) < 2)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
178 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
179 palette[3] = buf[pos] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
180 palette[2] = buf[pos] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
181 palette[1] = buf[pos + 1] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
182 palette[0] = buf[pos + 1] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
183 pos += 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
184 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
185 case 0x04:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
186 /* set alpha */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
187 if ((buf_size - pos) < 2)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
188 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
189 alpha[3] = buf[pos] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
190 alpha[2] = buf[pos] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
191 alpha[1] = buf[pos + 1] >> 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
192 alpha[0] = buf[pos + 1] & 0x0f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
193 pos += 2;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
194 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
195 av_log(NULL, AV_LOG_INFO, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
196 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
197 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
198 case 0x05:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
199 if ((buf_size - pos) < 6)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
200 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
201 x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
202 x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
203 y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
204 y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
205 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
206 av_log(NULL, AV_LOG_INFO, "x1=%d x2=%d y1=%d y2=%d\n",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
207 x1, x2, y1, y2);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
208 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
209 pos += 6;
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 0x06:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
212 if ((buf_size - pos) < 4)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
213 goto fail;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
214 offset1 = getbe16(buf + pos);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
215 offset2 = getbe16(buf + pos + 2);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
216 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
217 av_log(NULL, AV_LOG_INFO, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
218 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
219 pos += 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
220 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
221 case 0xff:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
222 default:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
223 goto the_end;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
224 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
225 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
226 the_end:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
227 if (offset1 >= 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
228 int w, h;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
229 uint8_t *bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
230
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
231 /* decode the bitmap */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
232 w = x2 - x1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
233 if (w < 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
234 w = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
235 h = y2 - y1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
236 if (h < 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
237 h = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
238 if (w > 0 && h > 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
239 if (sub_header->rects != NULL) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
240 for (i = 0; i < sub_header->num_rects; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
241 av_free(sub_header->rects[i].bitmap);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
242 av_free(sub_header->rects[i].rgba_palette);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
243 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
244 av_freep(&sub_header->rects);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
245 sub_header->num_rects = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
246 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
247
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
248 bitmap = av_malloc(w * h);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
249 sub_header->rects = av_mallocz(sizeof(AVSubtitleRect));
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
250 sub_header->num_rects = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
251 sub_header->rects[0].rgba_palette = av_malloc(4 * 4);
4437
42ad7d63fb5d Fix a bug in the DVD subtitle decoder where subtitles with odd heights would not
takis
parents: 4091
diff changeset
252 decode_rle(bitmap, w * 2, w, (h + 1) / 2,
4091
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
253 buf, offset1 * 2, buf_size);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
254 decode_rle(bitmap + w, w * 2, w, h / 2,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
255 buf, offset2 * 2, buf_size);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
256 guess_palette(sub_header->rects[0].rgba_palette,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
257 palette, alpha, 0xffff00);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
258 sub_header->rects[0].x = x1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
259 sub_header->rects[0].y = y1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
260 sub_header->rects[0].w = w;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
261 sub_header->rects[0].h = h;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
262 sub_header->rects[0].nb_colors = 4;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
263 sub_header->rects[0].linesize = w;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
264 sub_header->rects[0].bitmap = bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
265 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
266 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
267 if (next_cmd_pos == cmd_pos)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
268 break;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
269 cmd_pos = next_cmd_pos;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
270 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
271 if (sub_header->num_rects > 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
272 return is_menu;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
273 fail:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
274 return -1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
275 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
276
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
277 static int is_transp(const uint8_t *buf, int pitch, int n,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
278 const uint8_t *transp_color)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
279 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
280 int i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
281 for(i = 0; i < n; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
282 if (!transp_color[*buf])
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
283 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
284 buf += pitch;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
285 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
286 return 1;
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 /* return 0 if empty rectangle, 1 if non empty */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
290 static int find_smallest_bounding_rectangle(AVSubtitle *s)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
291 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
292 uint8_t transp_color[256];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
293 int y1, y2, x1, x2, y, w, h, i;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
294 uint8_t *bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
295
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
296 if (s->num_rects == 0 || s->rects == NULL || s->rects[0].w <= 0 || s->rects[0].h <= 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
297 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
298
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
299 memset(transp_color, 0, 256);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
300 for(i = 0; i < s->rects[0].nb_colors; i++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
301 if ((s->rects[0].rgba_palette[i] >> 24) == 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
302 transp_color[i] = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
303 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
304 y1 = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
305 while (y1 < s->rects[0].h && is_transp(s->rects[0].bitmap + y1 * s->rects[0].linesize,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
306 1, s->rects[0].w, transp_color))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
307 y1++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
308 if (y1 == s->rects[0].h) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
309 av_freep(&s->rects[0].bitmap);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
310 s->rects[0].w = s->rects[0].h = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
311 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
312 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
313
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
314 y2 = s->rects[0].h - 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
315 while (y2 > 0 && is_transp(s->rects[0].bitmap + y2 * s->rects[0].linesize, 1,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
316 s->rects[0].w, transp_color))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
317 y2--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
318 x1 = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
319 while (x1 < (s->rects[0].w - 1) && is_transp(s->rects[0].bitmap + x1, s->rects[0].linesize,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
320 s->rects[0].h, transp_color))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
321 x1++;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
322 x2 = s->rects[0].w - 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
323 while (x2 > 0 && is_transp(s->rects[0].bitmap + x2, s->rects[0].linesize, s->rects[0].h,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
324 transp_color))
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
325 x2--;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
326 w = x2 - x1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
327 h = y2 - y1 + 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
328 bitmap = av_malloc(w * h);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
329 if (!bitmap)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
330 return 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
331 for(y = 0; y < h; y++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
332 memcpy(bitmap + w * y, s->rects[0].bitmap + x1 + (y1 + y) * s->rects[0].linesize, w);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
333 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
334 av_freep(&s->rects[0].bitmap);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
335 s->rects[0].bitmap = bitmap;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
336 s->rects[0].linesize = w;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
337 s->rects[0].w = w;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
338 s->rects[0].h = h;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
339 s->rects[0].x += x1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
340 s->rects[0].y += y1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
341 return 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
342 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
343
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
344 static int dvdsub_close_decoder(AVCodecContext *avctx)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
345 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
346 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
347 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
348
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
349 #ifdef DEBUG
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
350 #undef fprintf
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
351 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
352 uint32_t *rgba_palette)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
353 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
354 int x, y, v;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
355 FILE *f;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
356
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
357 f = fopen(filename, "w");
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
358 if (!f) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
359 perror(filename);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
360 exit(1);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
361 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
362 fprintf(f, "P6\n"
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
363 "%d %d\n"
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
364 "%d\n",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
365 w, h, 255);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
366 for(y = 0; y < h; y++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
367 for(x = 0; x < w; x++) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
368 v = rgba_palette[bitmap[y * w + x]];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
369 putc((v >> 16) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
370 putc((v >> 8) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
371 putc((v >> 0) & 0xff, f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
372 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
373 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
374 fclose(f);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
375 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
376 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
377
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
378 static int dvdsub_decode(AVCodecContext *avctx,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
379 void *data, int *data_size,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
380 uint8_t *buf, int buf_size)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
381 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
382 AVSubtitle *sub = (void *)data;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
383 int is_menu;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
384
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
385 is_menu = decode_dvd_subtitles(sub, buf, buf_size);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
386
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
387 if (is_menu < 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
388 no_subtitle:
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
389 *data_size = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
390
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
391 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
392 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
393 if (!is_menu && find_smallest_bounding_rectangle(sub) == 0)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
394 goto no_subtitle;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
395
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
396 #if defined(DEBUG)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
397 av_log(NULL, AV_LOG_INFO, "start=%d ms end =%d ms\n",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
398 sub->start_display_time,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
399 sub->end_display_time);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
400 ppm_save("/tmp/a.ppm", sub->rects[0].bitmap,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
401 sub->rects[0].w, sub->rects[0].h, sub->rects[0].rgba_palette);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
402 #endif
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
403
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
404 *data_size = 1;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
405 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
406 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
407
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
408 AVCodec dvdsub_decoder = {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
409 "dvdsub",
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
410 CODEC_TYPE_SUBTITLE,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
411 CODEC_ID_DVD_SUBTITLE,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
412 0,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
413 dvdsub_init_decoder,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
414 NULL,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
415 dvdsub_close_decoder,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
416 dvdsub_decode,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
417 };
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
418
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
419 /* parser definition */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
420 typedef struct DVDSubParseContext {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
421 uint8_t *packet;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
422 int packet_len;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
423 int packet_index;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
424 } DVDSubParseContext;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
425
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
426 static int dvdsub_parse_init(AVCodecParserContext *s)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
427 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
428 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
429 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
430
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
431 static int dvdsub_parse(AVCodecParserContext *s,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
432 AVCodecContext *avctx,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
433 uint8_t **poutbuf, int *poutbuf_size,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
434 const uint8_t *buf, int buf_size)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
435 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
436 DVDSubParseContext *pc = s->priv_data;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
437
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
438 if (pc->packet_index == 0) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
439 if (buf_size < 2)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
440 return 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
441 pc->packet_len = (buf[0] << 8) | buf[1];
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
442 av_freep(&pc->packet);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
443 pc->packet = av_malloc(pc->packet_len);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
444 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
445 if (pc->packet) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
446 if (pc->packet_index + buf_size <= pc->packet_len) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
447 memcpy(pc->packet + pc->packet_index, buf, buf_size);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
448 pc->packet_index += buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
449 if (pc->packet_index >= pc->packet_len) {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
450 *poutbuf = pc->packet;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
451 *poutbuf_size = pc->packet_len;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
452 pc->packet_index = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
453 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
454 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
455 } else {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
456 /* erroneous size */
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
457 pc->packet_index = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
458 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
459 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
460 *poutbuf = NULL;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
461 *poutbuf_size = 0;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
462 return buf_size;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
463 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
464
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
465 static void dvdsub_parse_close(AVCodecParserContext *s)
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
466 {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
467 DVDSubParseContext *pc = s->priv_data;
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
468 av_freep(&pc->packet);
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
469 }
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
470
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
471 AVCodecParser dvdsub_parser = {
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
472 { CODEC_ID_DVD_SUBTITLE },
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
473 sizeof(DVDSubParseContext),
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
474 dvdsub_parse_init,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
475 dvdsub_parse,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
476 dvdsub_parse_close,
3c00eb82db0d Rename dvdsub.c to dvdsubdec.c.
diego
parents:
diff changeset
477 };