Mercurial > libavcodec.hg
annotate vmnc.c @ 10401:b44eae1b1971 libavcodec
Use cbrtf and exp2f instead of pow to calculate tables for MPEG audio decoding.
This hopefully is fast enough so that it is reasonable to use the same formula
directly instead of the table for CONFIG_SMALL.
author | reimar |
---|---|
date | Thu, 15 Oct 2009 06:59:23 +0000 |
parents | d7ed9dcc78e3 |
children | 8a4984c5cacc |
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 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8573
diff
changeset
|
23 * @file libavcodec/vmnc.c |
3677 | 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 | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7823
diff
changeset
|
31 #include "libavutil/intreadwrite.h" |
3677 | 32 #include "avcodec.h" |
33 | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
34 enum EncTypes { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
35 MAGIC_WMVd = 0x574D5664, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
36 MAGIC_WMVe, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
37 MAGIC_WMVf, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
38 MAGIC_WMVg, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
39 MAGIC_WMVh, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
40 MAGIC_WMVi, |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
41 MAGIC_WMVj |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
42 }; |
3677 | 43 |
44 enum HexTile_Flags { | |
45 HT_RAW = 1, // tile is raw | |
46 HT_BKG = 2, // background color is present | |
47 HT_FG = 4, // foreground color is present | |
48 HT_SUB = 8, // subrects are present | |
49 HT_CLR = 16 // each subrect has own color | |
50 }; | |
51 | |
52 /* | |
53 * Decoder context | |
54 */ | |
55 typedef struct VmncContext { | |
56 AVCodecContext *avctx; | |
57 AVFrame pic; | |
58 | |
59 int bpp; | |
60 int bpp2; | |
61 int bigendian; | |
62 uint8_t pal[768]; | |
63 int width, height; | |
3684 | 64 |
65 /* cursor data */ | |
66 int cur_w, cur_h; | |
67 int cur_x, cur_y; | |
68 int cur_hx, cur_hy; | |
69 uint8_t* curbits, *curmask; | |
70 uint8_t* screendta; | |
3677 | 71 } VmncContext; |
72 | |
73 /* read pixel value from stream */ | |
6293 | 74 static av_always_inline int vmnc_get_pixel(const uint8_t* buf, int bpp, int be) { |
3677 | 75 switch(bpp * 2 + be) { |
76 case 2: | |
77 case 3: return *buf; | |
4364 | 78 case 4: return AV_RL16(buf); |
79 case 5: return AV_RB16(buf); | |
80 case 8: return AV_RL32(buf); | |
81 case 9: return AV_RB32(buf); | |
3677 | 82 default: return 0; |
83 } | |
84 } | |
85 | |
6293 | 86 static void load_cursor(VmncContext *c, const uint8_t *src) |
3684 | 87 { |
88 int i, j, p; | |
89 const int bpp = c->bpp2; | |
90 uint8_t *dst8 = c->curbits; | |
91 uint16_t *dst16 = (uint16_t*)c->curbits; | |
92 uint32_t *dst32 = (uint32_t*)c->curbits; | |
93 | |
94 for(j = 0; j < c->cur_h; j++) { | |
95 for(i = 0; i < c->cur_w; i++) { | |
96 p = vmnc_get_pixel(src, bpp, c->bigendian); | |
97 src += bpp; | |
98 if(bpp == 1) *dst8++ = p; | |
99 if(bpp == 2) *dst16++ = p; | |
100 if(bpp == 4) *dst32++ = p; | |
101 } | |
102 } | |
103 dst8 = c->curmask; | |
104 dst16 = (uint16_t*)c->curmask; | |
105 dst32 = (uint32_t*)c->curmask; | |
106 for(j = 0; j < c->cur_h; j++) { | |
107 for(i = 0; i < c->cur_w; i++) { | |
108 p = vmnc_get_pixel(src, bpp, c->bigendian); | |
109 src += bpp; | |
110 if(bpp == 1) *dst8++ = p; | |
111 if(bpp == 2) *dst16++ = p; | |
112 if(bpp == 4) *dst32++ = p; | |
113 } | |
114 } | |
115 } | |
116 | |
117 static void put_cursor(uint8_t *dst, int stride, VmncContext *c, int dx, int dy) | |
118 { | |
3920
3a151ccc6ed7
Remove unused variables and the corresponding warnings along with them.
diego
parents:
3800
diff
changeset
|
119 int i, j; |
3684 | 120 int w, h, x, y; |
121 w = c->cur_w; | |
122 if(c->width < c->cur_x + c->cur_w) w = c->width - c->cur_x; | |
123 h = c->cur_h; | |
124 if(c->height < c->cur_y + c->cur_h) h = c->height - c->cur_y; | |
125 x = c->cur_x; | |
126 y = c->cur_y; | |
127 if(x < 0) { | |
128 w += x; | |
129 x = 0; | |
130 } | |
131 if(y < 0) { | |
132 h += y; | |
133 y = 0; | |
134 } | |
135 | |
136 if((w < 1) || (h < 1)) return; | |
137 dst += x * c->bpp2 + y * stride; | |
138 | |
139 if(c->bpp2 == 1) { | |
140 uint8_t* cd = c->curbits, *msk = c->curmask; | |
141 for(j = 0; j < h; j++) { | |
142 for(i = 0; i < w; i++) | |
143 dst[i] = (dst[i] & cd[i]) ^ msk[i]; | |
144 msk += c->cur_w; | |
145 cd += c->cur_w; | |
146 dst += stride; | |
147 } | |
148 } else if(c->bpp2 == 2) { | |
149 uint16_t* cd = (uint16_t*)c->curbits, *msk = (uint16_t*)c->curmask; | |
150 uint16_t* dst2; | |
151 for(j = 0; j < h; j++) { | |
152 dst2 = (uint16_t*)dst; | |
153 for(i = 0; i < w; i++) | |
154 dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; | |
155 msk += c->cur_w; | |
156 cd += c->cur_w; | |
157 dst += stride; | |
158 } | |
159 } else if(c->bpp2 == 4) { | |
160 uint32_t* cd = (uint32_t*)c->curbits, *msk = (uint32_t*)c->curmask; | |
161 uint32_t* dst2; | |
162 for(j = 0; j < h; j++) { | |
163 dst2 = (uint32_t*)dst; | |
164 for(i = 0; i < w; i++) | |
165 dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; | |
166 msk += c->cur_w; | |
167 cd += c->cur_w; | |
168 dst += stride; | |
169 } | |
170 } | |
171 } | |
172 | |
5967
15ed47af1838
Misc spelling fixes, prefer American over British English.
diego
parents:
5215
diff
changeset
|
173 /* fill rectangle with given color */ |
4283
d6f83e2f8804
rename always_inline to av_always_inline and move to common.h
mru
parents:
3947
diff
changeset
|
174 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 | 175 { |
176 int i, j; | |
177 dst += dx * bpp + dy * stride; | |
178 if(bpp == 1){ | |
179 for(j = 0; j < h; j++) { | |
180 memset(dst, color, w); | |
181 dst += stride; | |
182 } | |
183 }else if(bpp == 2){ | |
184 uint16_t* dst2; | |
185 for(j = 0; j < h; j++) { | |
186 dst2 = (uint16_t*)dst; | |
187 for(i = 0; i < w; i++) { | |
188 *dst2++ = color; | |
189 } | |
190 dst += stride; | |
191 } | |
192 }else if(bpp == 4){ | |
193 uint32_t* dst2; | |
194 for(j = 0; j < h; j++) { | |
195 dst2 = (uint32_t*)dst; | |
196 for(i = 0; i < w; i++) { | |
197 dst2[i] = color; | |
198 } | |
199 dst += stride; | |
200 } | |
201 } | |
202 } | |
203 | |
6293 | 204 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 | 205 { |
206 int i, j, p; | |
207 for(j = 0; j < h; j++) { | |
208 for(i = 0; i < w; i++) { | |
209 p = vmnc_get_pixel(src, bpp, be); | |
210 src += bpp; | |
3678
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
211 switch(bpp){ |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
212 case 1: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
213 dst[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
214 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
215 case 2: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
216 ((uint16_t*)dst)[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
217 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
218 case 4: |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
219 ((uint32_t*)dst)[i] = p; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
220 break; |
93a961e40d65
Handle raw blocks correctly (both updating pointer and storing to memory)
kostya
parents:
3677
diff
changeset
|
221 } |
3677 | 222 } |
223 dst += stride; | |
224 } | |
225 } | |
226 | |
6293 | 227 static int decode_hextile(VmncContext *c, uint8_t* dst, const uint8_t* src, int ssize, int w, int h, int stride) |
3677 | 228 { |
229 int i, j, k; | |
230 int bg = 0, fg = 0, rects, color, flags, xy, wh; | |
231 const int bpp = c->bpp2; | |
232 uint8_t *dst2; | |
233 int bw = 16, bh = 16; | |
6293 | 234 const uint8_t *ssrc=src; |
3677 | 235 |
236 for(j = 0; j < h; j += 16) { | |
237 dst2 = dst; | |
238 bw = 16; | |
239 if(j + 16 > h) bh = h - j; | |
240 for(i = 0; i < w; i += 16, dst2 += 16 * bpp) { | |
3685 | 241 if(src - ssrc >= ssize) { |
242 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
243 return -1; | |
244 } | |
3677 | 245 if(i + 16 > w) bw = w - i; |
246 flags = *src++; | |
247 if(flags & HT_RAW) { | |
3685 | 248 if(src - ssrc > ssize - bw * bh * bpp) { |
249 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
250 return -1; | |
251 } | |
3677 | 252 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
|
253 src += bw * bh * bpp; |
3677 | 254 } else { |
255 if(flags & HT_BKG) { | |
256 bg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
257 } | |
258 if(flags & HT_FG) { | |
259 fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
260 } | |
261 rects = 0; | |
262 if(flags & HT_SUB) | |
263 rects = *src++; | |
3685 | 264 color = !!(flags & HT_CLR); |
3677 | 265 |
266 paint_rect(dst2, 0, 0, bw, bh, bg, bpp, stride); | |
267 | |
3685 | 268 if(src - ssrc > ssize - rects * (color * bpp + 2)) { |
269 av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); | |
270 return -1; | |
271 } | |
3677 | 272 for(k = 0; k < rects; k++) { |
273 if(color) { | |
274 fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; | |
275 } | |
276 xy = *src++; | |
277 wh = *src++; | |
278 paint_rect(dst2, xy >> 4, xy & 0xF, (wh>>4)+1, (wh & 0xF)+1, fg, bpp, stride); | |
279 } | |
280 } | |
281 } | |
282 dst += stride * 16; | |
283 } | |
284 return src - ssrc; | |
285 } | |
286 | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
287 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
3677 | 288 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
289 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
290 int buf_size = avpkt->size; |
4827 | 291 VmncContext * const c = avctx->priv_data; |
3677 | 292 uint8_t *outptr; |
6293 | 293 const uint8_t *src = buf; |
3685 | 294 int dx, dy, w, h, depth, enc, chunks, res, size_left; |
3677 | 295 |
296 c->pic.reference = 1; | |
297 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
298 if(avctx->reget_buffer(avctx, &c->pic) < 0){ | |
299 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
300 return -1; | |
301 } | |
302 | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
303 c->pic.key_frame = 0; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
304 c->pic.pict_type = FF_P_TYPE; |
3677 | 305 |
3684 | 306 //restore screen after cursor |
307 if(c->screendta) { | |
308 int i; | |
309 w = c->cur_w; | |
310 if(c->width < c->cur_x + w) w = c->width - c->cur_x; | |
311 h = c->cur_h; | |
312 if(c->height < c->cur_y + h) h = c->height - c->cur_y; | |
313 dx = c->cur_x; | |
314 if(dx < 0) { | |
315 w += dx; | |
316 dx = 0; | |
317 } | |
318 dy = c->cur_y; | |
319 if(dy < 0) { | |
320 h += dy; | |
321 dy = 0; | |
322 } | |
323 if((w > 0) && (h > 0)) { | |
324 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; | |
325 for(i = 0; i < h; i++) { | |
326 memcpy(outptr, c->screendta + i * c->cur_w * c->bpp2, w * c->bpp2); | |
327 outptr += c->pic.linesize[0]; | |
328 } | |
329 } | |
330 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
331 src += 2; |
4364 | 332 chunks = AV_RB16(src); src += 2; |
3677 | 333 while(chunks--) { |
4364 | 334 dx = AV_RB16(src); src += 2; |
335 dy = AV_RB16(src); src += 2; | |
336 w = AV_RB16(src); src += 2; | |
337 h = AV_RB16(src); src += 2; | |
338 enc = AV_RB32(src); src += 4; | |
3684 | 339 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; |
3685 | 340 size_left = buf_size - (src - buf); |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
341 switch(enc) { |
3684 | 342 case MAGIC_WMVd: // cursor |
3685 | 343 if(size_left < 2 + w * h * c->bpp2 * 2) { |
344 av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", 2 + w * h * c->bpp2 * 2, size_left); | |
345 return -1; | |
346 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
347 src += 2; |
3684 | 348 c->cur_w = w; |
349 c->cur_h = h; | |
350 c->cur_hx = dx; | |
351 c->cur_hy = dy; | |
352 if((c->cur_hx > c->cur_w) || (c->cur_hy > c->cur_h)) { | |
353 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); | |
354 c->cur_hx = c->cur_hy = 0; | |
355 } | |
356 c->curbits = av_realloc(c->curbits, c->cur_w * c->cur_h * c->bpp2); | |
357 c->curmask = av_realloc(c->curmask, c->cur_w * c->cur_h * c->bpp2); | |
358 c->screendta = av_realloc(c->screendta, c->cur_w * c->cur_h * c->bpp2); | |
359 load_cursor(c, src); | |
360 src += w * h * c->bpp2 * 2; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
361 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
362 case MAGIC_WMVe: // unknown |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
363 src += 2; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
364 break; |
3684 | 365 case MAGIC_WMVf: // update cursor position |
366 c->cur_x = dx - c->cur_hx; | |
367 c->cur_y = dy - c->cur_hy; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
368 break; |
3686 | 369 case MAGIC_WMVg: // unknown |
370 src += 10; | |
371 break; | |
372 case MAGIC_WMVh: // unknown | |
373 src += 4; | |
374 break; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
375 case MAGIC_WMVi: // ServerInitialization struct |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
376 c->pic.key_frame = 1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
377 c->pic.pict_type = FF_I_TYPE; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
378 depth = *src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
379 if(depth != c->bpp) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
380 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
|
381 } |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
382 src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
383 c->bigendian = *src++; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
384 if(c->bigendian & (~1)) { |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
385 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
|
386 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
387 } |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
388 //skip the rest of pixel format data |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
389 src += 13; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
390 break; |
3686 | 391 case MAGIC_WMVj: // unknown |
392 src += 2; | |
393 break; | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
394 case 0x00000000: // raw rectangle data |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
395 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
|
396 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
|
397 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
398 } |
3685 | 399 if(size_left < w * h * c->bpp2) { |
400 av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", w * h * c->bpp2, size_left); | |
401 return -1; | |
402 } | |
3679
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
403 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
|
404 src += w * h * c->bpp2; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
405 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
406 case 0x00000005: // HexTile encoded rectangle |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
407 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
|
408 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
|
409 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
410 } |
3685 | 411 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
|
412 if(res < 0) |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
413 return -1; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
414 src += res; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
415 break; |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
416 default: |
2702eec8c8b9
Try to handle all chunks, previous scheme was not correct.
kostya
parents:
3678
diff
changeset
|
417 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
|
418 chunks = 0; // leave chunks decoding loop |
3677 | 419 } |
420 } | |
3684 | 421 if(c->screendta){ |
422 int i; | |
423 //save screen data before painting cursor | |
424 w = c->cur_w; | |
425 if(c->width < c->cur_x + w) w = c->width - c->cur_x; | |
426 h = c->cur_h; | |
427 if(c->height < c->cur_y + h) h = c->height - c->cur_y; | |
428 dx = c->cur_x; | |
429 if(dx < 0) { | |
430 w += dx; | |
431 dx = 0; | |
432 } | |
433 dy = c->cur_y; | |
434 if(dy < 0) { | |
435 h += dy; | |
436 dy = 0; | |
437 } | |
438 if((w > 0) && (h > 0)) { | |
439 outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; | |
440 for(i = 0; i < h; i++) { | |
441 memcpy(c->screendta + i * c->cur_w * c->bpp2, outptr, w * c->bpp2); | |
442 outptr += c->pic.linesize[0]; | |
443 } | |
444 outptr = c->pic.data[0]; | |
445 put_cursor(outptr, c->pic.linesize[0], c, c->cur_x, c->cur_y); | |
446 } | |
447 } | |
3677 | 448 *data_size = sizeof(AVFrame); |
449 *(AVFrame*)data = c->pic; | |
450 | |
451 /* always report that the buffer was completely consumed */ | |
452 return buf_size; | |
453 } | |
454 | |
455 | |
456 | |
457 /* | |
458 * | |
459 * Init VMnc decoder | |
460 * | |
461 */ | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6293
diff
changeset
|
462 static av_cold int decode_init(AVCodecContext *avctx) |
3677 | 463 { |
4827 | 464 VmncContext * const c = avctx->priv_data; |
3677 | 465 |
466 c->avctx = avctx; | |
467 | |
468 c->width = avctx->width; | |
469 c->height = avctx->height; | |
470 | |
7823
4525dcd81357
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
7040
diff
changeset
|
471 c->bpp = avctx->bits_per_coded_sample; |
3677 | 472 c->bpp2 = c->bpp/8; |
473 | |
474 switch(c->bpp){ | |
475 case 8: | |
476 avctx->pix_fmt = PIX_FMT_PAL8; | |
477 break; | |
478 case 16: | |
479 avctx->pix_fmt = PIX_FMT_RGB555; | |
480 break; | |
481 case 32: | |
482 avctx->pix_fmt = PIX_FMT_RGB32; | |
483 break; | |
484 default: | |
485 av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp); | |
486 } | |
487 | |
488 return 0; | |
489 } | |
490 | |
491 | |
492 | |
493 /* | |
494 * | |
495 * Uninit VMnc decoder | |
496 * | |
497 */ | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6293
diff
changeset
|
498 static av_cold int decode_end(AVCodecContext *avctx) |
3677 | 499 { |
4827 | 500 VmncContext * const c = avctx->priv_data; |
3677 | 501 |
502 if (c->pic.data[0]) | |
503 avctx->release_buffer(avctx, &c->pic); | |
504 | |
3684 | 505 av_free(c->curbits); |
506 av_free(c->curmask); | |
507 av_free(c->screendta); | |
3677 | 508 return 0; |
509 } | |
510 | |
511 AVCodec vmnc_decoder = { | |
6723 | 512 "vmnc", |
3677 | 513 CODEC_TYPE_VIDEO, |
514 CODEC_ID_VMNC, | |
515 sizeof(VmncContext), | |
516 decode_init, | |
517 NULL, | |
518 decode_end, | |
6722 | 519 decode_frame, |
9817
eb2a897f89d5
vmware video decoder uses reget_buffer, set CODEC_CAP_DR1
bcoudurier
parents:
9553
diff
changeset
|
520 CODEC_CAP_DR1, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6723
diff
changeset
|
521 .long_name = NULL_IF_CONFIG_SMALL("VMware Screen Codec / VMware Video"), |
3677 | 522 }; |
523 |