Mercurial > libavcodec.hg
annotate vmnc.c @ 6920:d02af7474bff libavcodec
Prevent 128*1<<trellis from becoming 0 and creating 0 sized arrays.
fixes CID84 RUN2
CID85 RUN2
CID86 RUN2
CID87 RUN2
CID88 RUN2
CID89 RUN2
CID90 RUN2
CID91 RUN2
CID92 RUN2
CID93 RUN2
CID94 RUN2
CID95 RUN2
CID96 RUN2
CID97 RUN2
CID98 RUN2
CID99 RUN2
CID100 RUN2
CID101 RUN2
CID102 RUN2
CID103 RUN2
CID104 RUN2
CID105 RUN2
CID106 RUN2
author | michael |
---|---|
date | Wed, 28 May 2008 11:59:41 +0000 |
parents | 2ced96d3cde0 |
children | e943e1409077 |
rev | line source |
---|---|
3677 | 1 /* |
2 * VMware Screen Codec (VMnc) decoder | |
3 * Copyright (c) 2006 Konstantin Shishkov | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
3677 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
3677 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
3677 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3677 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | |
21 | |
22 /** | |
23 * @file vmnc.c | |
24 * VMware Screen Codec (VMnc) decoder | |
25 * As Alex Beregszaszi discovered, this is effectively RFB data dump | |
26 */ | |
27 | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 | |
31 #include "avcodec.h" | |
32 | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
33 enum EncTypes { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
34 MAGIC_WMVd = 0x574D5664, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
35 MAGIC_WMVe, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
36 MAGIC_WMVf, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
37 MAGIC_WMVg, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
38 MAGIC_WMVh, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
39 MAGIC_WMVi, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
40 MAGIC_WMVj |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
41 }; |
3677 | 42 |
43 enum HexTile_Flags { | |
44 HT_RAW = 1, // tile is raw | |
45 HT_BKG = 2, // background color is present | |
46 HT_FG = 4, // foreground color is present | |
47 HT_SUB = 8, // subrects are present | |
48 HT_CLR = 16 // each subrect has own color | |
49 }; | |
50 | |
51 /* | |
52 * Decoder context | |
53 */ | |
54 typedef struct VmncContext { | |
55 AVCodecContext *avctx; | |
56 AVFrame pic; | |
57 | |
58 int bpp; | |
59 int bpp2; | |
60 int bigendian; | |
61 uint8_t pal[768]; | |
62 int width, height; | |
3684 | 63 |
64 /* cursor data */ | |
65 int cur_w, cur_h; | |
66 int cur_x, cur_y; | |
67 int cur_hx, cur_hy; | |
68 uint8_t* curbits, *curmask; | |
69 uint8_t* screendta; | |
3677 | 70 } VmncContext; |
71 | |
72 /* read pixel value from stream */ | |
6293 | 73 static av_always_inline int vmnc_get_pixel(const uint8_t* buf, int bpp, int be) { |
3677 | 74 switch(bpp * 2 + be) { |
75 case 2: | |
76 case 3: return *buf; | |
4364 | 77 case 4: return AV_RL16(buf); |
78 case 5: return AV_RB16(buf); | |
79 case 8: return AV_RL32(buf); | |
80 case 9: return AV_RB32(buf); | |
3677 | 81 default: return 0; |
82 } | |
83 } | |
84 | |
6293 | 85 static void load_cursor(VmncContext *c, const uint8_t *src) |
3684 | 86 { |
87 int i, j, p; | |
88 const int bpp = c->bpp2; | |
89 uint8_t *dst8 = c->curbits; | |
90 uint16_t *dst16 = (uint16_t*)c->curbits; | |
91 uint32_t *dst32 = (uint32_t*)c->curbits; | |
92 | |
93 for(j = 0; j < c->cur_h; j++) { | |
94 for(i = 0; i < c->cur_w; i++) { | |
95 p = vmnc_get_pixel(src, bpp, c->bigendian); | |
96 src += bpp; | |
97 if(bpp == 1) *dst8++ = p; | |
98 if(bpp == 2) *dst16++ = p; | |
99 if(bpp == 4) *dst32++ = p; | |
100 } | |
101 } | |
102 dst8 = c->curmask; | |
103 dst16 = (uint16_t*)c->curmask; | |
104 dst32 = (uint32_t*)c->curmask; | |
105 for(j = 0; j < c->cur_h; j++) { | |
106 for(i = 0; i < c->cur_w; i++) { | |
107 p = vmnc_get_pixel(src, bpp, c->bigendian); | |
108 src += bpp; | |
109 if(bpp == 1) *dst8++ = p; | |
110 if(bpp == 2) *dst16++ = p; | |
111 if(bpp == 4) *dst32++ = p; | |
112 } | |
113 } | |
114 } | |
115 | |
116 static void put_cursor(uint8_t *dst, int stride, VmncContext *c, int dx, int dy) | |
117 { | |
3920
3a151ccc6ed7
Remove unused variables and the corresponding warnings along with them.
diego
parents:
3800
diff
changeset
|
118 int i, j; |
3684 | 119 int w, h, x, y; |
120 w = c->cur_w; | |
121 if(c->width < c->cur_x + c->cur_w) w = c->width - c->cur_x; | |
122 h = c->cur_h; | |
123 if(c->height < c->cur_y + c->cur_h) h = c->height - c->cur_y; | |
124 x = c->cur_x; | |
125 y = c->cur_y; | |
126 if(x < 0) { | |
127 w += x; | |
128 x = 0; | |
129 } | |
130 if(y < 0) { | |
131 h += y; | |
132 y = 0; | |
133 } | |
134 | |
135 if((w < 1) || (h < 1)) return; | |
136 dst += x * c->bpp2 + y * stride; | |
137 | |
138 if(c->bpp2 == 1) { | |
139 uint8_t* cd = c->curbits, *msk = c->curmask; | |
140 for(j = 0; j < h; j++) { | |
141 for(i = 0; i < w; i++) | |
142 dst[i] = (dst[i] & cd[i]) ^ msk[i]; | |
143 msk += c->cur_w; | |
144 cd += c->cur_w; | |
145 dst += stride; | |
146 } | |
147 } else if(c->bpp2 == 2) { | |
148 uint16_t* cd = (uint16_t*)c->curbits, *msk = (uint16_t*)c->curmask; | |
149 uint16_t* dst2; | |
150 for(j = 0; j < h; j++) { | |
151 dst2 = (uint16_t*)dst; | |
152 for(i = 0; i < w; i++) | |
153 dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; | |
154 msk += c->cur_w; | |
155 cd += c->cur_w; | |
156 dst += stride; | |
157 } | |
158 } else if(c->bpp2 == 4) { | |
159 uint32_t* cd = (uint32_t*)c->curbits, *msk = (uint32_t*)c->curmask; | |
160 uint32_t* dst2; | |
161 for(j = 0; j < h; j++) { | |
162 dst2 = (uint32_t*)dst; | |
163 for(i = 0; i < w; i++) | |
164 dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; | |
165 msk += c->cur_w; | |
166 cd += c->cur_w; | |
167 dst += stride; | |
168 } | |
169 } | |
170 } | |
171 | |
5967
15ed47af1838
Misc spelling fixes, prefer American over British English.
diego
parents:
5215
diff
changeset
|
172 /* fill rectangle with given color */ |
4283
d6f83e2f8804
rename always_inline to av_always_inline and move to common.h
mru
parents:
3947
diff
changeset
|
173 static av_always_inline void paint_rect(uint8_t *dst, int dx, int dy, int w, int h, int color, int bpp, int stride) |
3677 | 174 { |
175 int i, j; | |
176 dst += dx * bpp + dy * stride; | |
177 if(bpp == 1){ | |
178 for(j = 0; j < h; j++) { | |
179 memset(dst, color, w); | |
180 dst += stride; | |
181 } | |
182 }else if(bpp == 2){ | |
183 uint16_t* dst2; | |
184 for(j = 0; j < h; j++) { | |
185 dst2 = (uint16_t*)dst; | |
186 for(i = 0; i < w; i++) { | |
187 *dst2++ = color; | |
188 } | |
189 dst += stride; | |
190 } | |
191 }else if(bpp == 4){ | |
192 uint32_t* dst2; | |
193 for(j = 0; j < h; j++) { | |
194 dst2 = (uint32_t*)dst; | |
195 for(i = 0; i < w; i++) { | |
196 dst2[i] = color; | |
197 } | |
198 dst += stride; | |
199 } | |
200 } | |
201 } | |
202 | |
6293 | 203 static av_always_inline void paint_raw(uint8_t *dst, int w, int h, const uint8_t* src, int bpp, int be, int stride) |
3677 | 204 { |
205 int i, j, p; | |
206 for(j = 0; j < h; j++) { | |
207 for(i = 0; i < w; i++) { | |
208 p = vmnc_get_pixel(src, bpp, be); | |
209 src += bpp; | |
3678
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
210 switch(bpp){ |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
211 case 1: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
212 dst[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
213 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
214 case 2: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
215 ((uint16_t*)dst)[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
216 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
217 case 4: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
218 ((uint32_t*)dst)[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
219 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
220 } |
3677 | 221 } |
222 dst += stride; | |
223 } | |
224 } | |
225 | |
6293 | 226 static int decode_hextile(VmncContext *c, uint8_t* dst, const uint8_t* src, int ssize, int w, int h, int stride) |
3677 | 227 { |
228 int i, j, k; | |
229 int bg = 0, fg = 0, rects, color, flags, xy, wh; | |
230 const int bpp = c->bpp2; | |
231 uint8_t *dst2; | |
232 int bw = 16, bh = 16; | |
6293 | 233 const uint8_t *ssrc=src; |
3677 | 234 |
235 for(j = 0; j < h; j += 16) { | |
236 dst2 = dst; | |
237 bw = 16; | |
238 if(j + 16 > h) bh = h - j; | |
239 for(i = 0; i < w; i += 16, dst2 += 16 * bpp) { | |
3685 | 240 if(src - ssrc >= ssize) { |
241 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
242 return -1; | |
243 } | |
3677 | 244 if(i + 16 > w) bw = w - i; |
245 flags = *src++; | |
246 if(flags & HT_RAW) { | |
3685 | 247 if(src - ssrc > ssize - bw * bh * bpp) { |
248 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
249 return -1; | |
250 } | |
3677 | 251 paint_raw(dst2, bw, bh, src, bpp, c->bigendian, stride); |
3678
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
252 src += bw * bh * bpp; |
3677 | 253 } else { |
254 if(flags & HT_BKG) { | |
255 bg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
256 } | |
257 if(flags & HT_FG) { | |
258 fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
259 } | |
260 rects = 0; | |
261 if(flags & HT_SUB) | |
262 rects = *src++; | |
3685 | 263 color = !!(flags & HT_CLR); |
3677 | 264 |
265 paint_rect(dst2, 0, 0, bw, bh, bg, bpp, stride); | |
266 | |
3685 | 267 if(src - ssrc > ssize - rects * (color * bpp + 2)) { |
268 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
269 return -1; | |
270 } | |
3677 | 271 for(k = 0; k < rects; k++) { |
272 if(color) { | |
273 fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
274 } | |
275 xy = *src++; | |
276 wh = *src++; | |
277 paint_rect(dst2, xy >> 4, xy & 0xF, (wh>>4)+1, (wh & 0xF)+1, fg, bpp, stride); | |
278 } | |
279 } | |
280 } | |
281 dst += stride * 16; | |
282 } | |
283 return src - ssrc; | |
284 } | |
285 | |
6293 | 286 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) |
3677 | 287 { |
4827 | 288 VmncContext * const c = avctx->priv_data; |
3677 | 289 uint8_t *outptr; |
6293 | 290 const uint8_t *src = buf; |
3685 | 291 int dx, dy, w, h, depth, enc, chunks, res, size_left; |
3677 | 292 |
293 c->pic.reference = 1; | |
294 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
295 if(avctx->reget_buffer(avctx, &c->pic) < 0){ | |
296 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
297 return -1; | |
298 } | |
299 | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
300 c->pic.key_frame = 0; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
301 c->pic.pict_type = FF_P_TYPE; |
3677 | 302 |
3684 | 303 //restore screen after cursor |
304 if(c->screendta) { | |
305 int i; | |
306 w = c->cur_w; | |
307 if(c->width < c->cur_x + w) w = c->width - c->cur_x; | |
308 h = c->cur_h; | |
309 if(c->height < c->cur_y + h) h = c->height - c->cur_y; | |
310 dx = c->cur_x; | |
311 if(dx < 0) { | |
312 w += dx; | |
313 dx = 0; | |
314 } | |
315 dy = c->cur_y; | |
316 if(dy < 0) { | |
317 h += dy; | |
318 dy = 0; | |
319 } | |
320 if((w > 0) && (h > 0)) { | |
321 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; | |
322 for(i = 0; i < h; i++) { | |
323 memcpy(outptr, c->screendta + i * c->cur_w * c->bpp2, w * c->bpp2); | |
324 outptr += c->pic.linesize[0]; | |
325 } | |
326 } | |
327 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
328 src += 2; |
4364 | 329 chunks = AV_RB16(src); src += 2; |
3677 | 330 while(chunks--) { |
4364 | 331 dx = AV_RB16(src); src += 2; |
332 dy = AV_RB16(src); src += 2; | |
333 w = AV_RB16(src); src += 2; | |
334 h = AV_RB16(src); src += 2; | |
335 enc = AV_RB32(src); src += 4; | |
3684 | 336 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; |
3685 | 337 size_left = buf_size - (src - buf); |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
338 switch(enc) { |
3684 | 339 case MAGIC_WMVd: // cursor |
3685 | 340 if(size_left < 2 + w * h * c->bpp2 * 2) { |
341 av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", 2 + w * h * c->bpp2 * 2, size_left); | |
342 return -1; | |
343 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
344 src += 2; |
3684 | 345 c->cur_w = w; |
346 c->cur_h = h; | |
347 c->cur_hx = dx; | |
348 c->cur_hy = dy; | |
349 if((c->cur_hx > c->cur_w) || (c->cur_hy > c->cur_h)) { | |
350 av_log(avctx, AV_LOG_ERROR, "Cursor hot spot is not in image: %ix%i of %ix%i cursor size\n", c->cur_hx, c->cur_hy, c->cur_w, c->cur_h); | |
351 c->cur_hx = c->cur_hy = 0; | |
352 } | |
353 c->curbits = av_realloc(c->curbits, c->cur_w * c->cur_h * c->bpp2); | |
354 c->curmask = av_realloc(c->curmask, c->cur_w * c->cur_h * c->bpp2); | |
355 c->screendta = av_realloc(c->screendta, c->cur_w * c->cur_h * c->bpp2); | |
356 load_cursor(c, src); | |
357 src += w * h * c->bpp2 * 2; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
358 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
359 case MAGIC_WMVe: // unknown |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
360 src += 2; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
361 break; |
3684 | 362 case MAGIC_WMVf: // update cursor position |
363 c->cur_x = dx - c->cur_hx; | |
364 c->cur_y = dy - c->cur_hy; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
365 break; |
3686 | 366 case MAGIC_WMVg: // unknown |
367 src += 10; | |
368 break; | |
369 case MAGIC_WMVh: // unknown | |
370 src += 4; | |
371 break; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
372 case MAGIC_WMVi: // ServerInitialization struct |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
373 c->pic.key_frame = 1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
374 c->pic.pict_type = FF_I_TYPE; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
375 depth = *src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
376 if(depth != c->bpp) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
377 av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
378 } |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
379 src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
380 c->bigendian = *src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
381 if(c->bigendian & (~1)) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
382 av_log(avctx, AV_LOG_INFO, "Invalid header: bigendian flag = %i\n", c->bigendian); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
383 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
384 } |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
385 //skip the rest of pixel format data |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
386 src += 13; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
387 break; |
3686 | 388 case MAGIC_WMVj: // unknown |
389 src += 2; | |
390 break; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
391 case 0x00000000: // raw rectangle data |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
392 if((dx + w > c->width) || (dy + h > c->height)) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
393 av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
394 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
395 } |
3685 | 396 if(size_left < w * h * c->bpp2) { |
397 av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", w * h * c->bpp2, size_left); | |
398 return -1; | |
399 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
400 paint_raw(outptr, w, h, src, c->bpp2, c->bigendian, c->pic.linesize[0]); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
401 src += w * h * c->bpp2; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
402 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
403 case 0x00000005: // HexTile encoded rectangle |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
404 if((dx + w > c->width) || (dy + h > c->height)) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
405 av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
406 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
407 } |
3685 | 408 res = decode_hextile(c, outptr, src, size_left, w, h, c->pic.linesize[0]); |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
409 if(res < 0) |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
410 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
411 src += res; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
412 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
413 default: |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
414 av_log(avctx, AV_LOG_ERROR, "Unsupported block type 0x%08X\n", enc); |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
415 chunks = 0; // leave chunks decoding loop |
3677 | 416 } |
417 } | |
3684 | 418 if(c->screendta){ |
419 int i; | |
420 //save screen data before painting cursor | |
421 w = c->cur_w; | |
422 if(c->width < c->cur_x + w) w = c->width - c->cur_x; | |
423 h = c->cur_h; | |
424 if(c->height < c->cur_y + h) h = c->height - c->cur_y; | |
425 dx = c->cur_x; | |
426 if(dx < 0) { | |
427 w += dx; | |
428 dx = 0; | |
429 } | |
430 dy = c->cur_y; | |
431 if(dy < 0) { | |
432 h += dy; | |
433 dy = 0; | |
434 } | |
435 if((w > 0) && (h > 0)) { | |
436 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; | |
437 for(i = 0; i < h; i++) { | |
438 memcpy(c->screendta + i * c->cur_w * c->bpp2, outptr, w * c->bpp2); | |
439 outptr += c->pic.linesize[0]; | |
440 } | |
441 outptr = c->pic.data[0]; | |
442 put_cursor(outptr, c->pic.linesize[0], c, c->cur_x, c->cur_y); | |
443 } | |
444 } | |
3677 | 445 *data_size = sizeof(AVFrame); |
446 *(AVFrame*)data = c->pic; | |
447 | |
448 /* always report that the buffer was completely consumed */ | |
449 return buf_size; | |
450 } | |
451 | |
452 | |
453 | |
454 /* | |
455 * | |
456 * Init VMnc decoder | |
457 * | |
458 */ | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6293
diff
changeset
|
459 static av_cold int decode_init(AVCodecContext *avctx) |
3677 | 460 { |
4827 | 461 VmncContext * const c = avctx->priv_data; |
3677 | 462 |
463 c->avctx = avctx; | |
464 | |
465 c->pic.data[0] = NULL; | |
466 c->width = avctx->width; | |
467 c->height = avctx->height; | |
468 | |
3800
9b75ab171fa9
1l: correct argument order in avcodec_check_dimensions
kostya
parents:
3686
diff
changeset
|
469 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { |
3677 | 470 return 1; |
471 } | |
472 c->bpp = avctx->bits_per_sample; | |
473 c->bpp2 = c->bpp/8; | |
474 | |
475 switch(c->bpp){ | |
476 case 8: | |
477 avctx->pix_fmt = PIX_FMT_PAL8; | |
478 break; | |
479 case 16: | |
480 avctx->pix_fmt = PIX_FMT_RGB555; | |
481 break; | |
482 case 32: | |
483 avctx->pix_fmt = PIX_FMT_RGB32; | |
484 break; | |
485 default: | |
486 av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp); | |
487 } | |
488 | |
489 return 0; | |
490 } | |
491 | |
492 | |
493 | |
494 /* | |
495 * | |
496 * Uninit VMnc decoder | |
497 * | |
498 */ | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6293
diff
changeset
|
499 static av_cold int decode_end(AVCodecContext *avctx) |
3677 | 500 { |
4827 | 501 VmncContext * const c = avctx->priv_data; |
3677 | 502 |
503 if (c->pic.data[0]) | |
504 avctx->release_buffer(avctx, &c->pic); | |
505 | |
3684 | 506 av_free(c->curbits); |
507 av_free(c->curmask); | |
508 av_free(c->screendta); | |
3677 | 509 return 0; |
510 } | |
511 | |
512 AVCodec vmnc_decoder = { | |
6723 | 513 "vmnc", |
3677 | 514 CODEC_TYPE_VIDEO, |
515 CODEC_ID_VMNC, | |
516 sizeof(VmncContext), | |
517 decode_init, | |
518 NULL, | |
519 decode_end, | |
6722 | 520 decode_frame, |
521 .long_name = "VMware Screen Codec / VMware Video", | |
3677 | 522 }; |
523 |