Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeniccvid.c
Go to the documentation of this file.
00001 /* 00002 * Radius Cinepak Video Decoder 00003 * 00004 * Copyright 2001 Dr. Tim Ferguson (see below) 00005 * Portions Copyright 2003 Mike McCormack for CodeWeavers 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 /* Copyright notice from original source: 00023 * ------------------------------------------------------------------------ 00024 * Radius Cinepak Video Decoder 00025 * 00026 * Dr. Tim Ferguson, 2001. 00027 * For more details on the algorithm: 00028 * http://www.csse.monash.edu.au/~timf/videocodec.html 00029 * 00030 * This is basically a vector quantiser with adaptive vector density. The 00031 * frame is segmented into 4x4 pixel blocks, and each block is coded using 00032 * either 1 or 4 vectors. 00033 * 00034 * There are still some issues with this code yet to be resolved. In 00035 * particular with decoding in the strip boundaries. However, I have not 00036 * yet found a sequence it doesn't work on. Ill keep trying :) 00037 * 00038 * You may freely use this source code. I only ask that you reference its 00039 * source in your projects documentation: 00040 * Tim Ferguson: http://www.csse.monash.edu.au/~timf/ 00041 * ------------------------------------------------------------------------ */ 00042 00043 #include <stdarg.h> 00044 #include "windef.h" 00045 #include "winbase.h" 00046 #include "wingdi.h" 00047 #include "winuser.h" 00048 #include "commdlg.h" 00049 #include "vfw.h" 00050 #include "mmsystem.h" 00051 #include "iccvid_private.h" 00052 00053 #include "wine/debug.h" 00054 00055 WINE_DEFAULT_DEBUG_CHANNEL(iccvid); 00056 00057 static HINSTANCE ICCVID_hModule; 00058 00059 #define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd') 00060 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020) 00061 00062 #define DBUG 0 00063 #define MAX_STRIPS 32 00064 00065 /* ------------------------------------------------------------------------ */ 00066 typedef struct 00067 { 00068 unsigned char y0, y1, y2, y3; 00069 char u, v; 00070 unsigned char r[4], g[4], b[4]; 00071 } cvid_codebook; 00072 00073 typedef struct { 00074 cvid_codebook *v4_codebook[MAX_STRIPS]; 00075 cvid_codebook *v1_codebook[MAX_STRIPS]; 00076 unsigned int strip_num; 00077 } cinepak_info; 00078 00079 typedef struct _ICCVID_Info 00080 { 00081 DWORD dwMagic; 00082 int bits_per_pixel; 00083 cinepak_info *cvinfo; 00084 } ICCVID_Info; 00085 00086 static inline LPVOID heap_alloc( size_t size ) 00087 { 00088 return HeapAlloc( GetProcessHeap(), 0, size ); 00089 } 00090 00091 static inline BOOL heap_free( LPVOID ptr ) 00092 { 00093 return HeapFree( GetProcessHeap(), 0, ptr ); 00094 } 00095 00096 00097 /* ------------------------------------------------------------------------ */ 00098 static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL; 00099 00100 #define get_byte() *(in_buffer++) 00101 #define skip_byte() in_buffer++ 00102 #define get_word() ((unsigned short)(in_buffer += 2, \ 00103 (in_buffer[-2] << 8 | in_buffer[-1]))) 00104 #define get_long() ((unsigned long)(in_buffer += 4, \ 00105 (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1]))) 00106 00107 00108 /* ---------------------------------------------------------------------- */ 00109 static inline void read_codebook(cvid_codebook *c, int mode) 00110 { 00111 int uvr, uvg, uvb; 00112 00113 if(mode) /* black and white */ 00114 { 00115 c->y0 = get_byte(); 00116 c->y1 = get_byte(); 00117 c->y2 = get_byte(); 00118 c->y3 = get_byte(); 00119 c->u = c->v = 0; 00120 00121 c->r[0] = c->g[0] = c->b[0] = c->y0; 00122 c->r[1] = c->g[1] = c->b[1] = c->y1; 00123 c->r[2] = c->g[2] = c->b[2] = c->y2; 00124 c->r[3] = c->g[3] = c->b[3] = c->y3; 00125 } 00126 else /* colour */ 00127 { 00128 c->y0 = get_byte(); /* luma */ 00129 c->y1 = get_byte(); 00130 c->y2 = get_byte(); 00131 c->y3 = get_byte(); 00132 c->u = get_byte(); /* chroma */ 00133 c->v = get_byte(); 00134 00135 uvr = c->v << 1; 00136 uvg = -((c->u+1) >> 1) - c->v; 00137 uvb = c->u << 1; 00138 00139 c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb]; 00140 c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb]; 00141 c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb]; 00142 c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb]; 00143 } 00144 } 00145 00146 00147 #define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b)) 00148 /*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/ 00149 #define MAKECOLOUR16(r,g,b) (((r) >> 3) << 11)| (((g) >> 2) << 5)| (((b) >> 3) << 0) 00150 #define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0) 00151 00152 /* ------------------------------------------------------------------------ */ 00153 static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) 00154 { 00155 unsigned long *vptr = (unsigned long *)frm; 00156 #ifndef ORIGINAL 00157 int row_inc = -stride/4; 00158 #else 00159 int row_inc = stride/4; 00160 #endif 00161 int x, y; 00162 00163 /* fill 4x4 block of pixels with colour values from codebook */ 00164 for (y = 0; y < 4; y++) 00165 { 00166 if (&vptr[y*row_inc] < (unsigned long *)limit) return; 00167 for (x = 0; x < 4; x++) 00168 vptr[y*row_inc + x] = MAKECOLOUR32(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]); 00169 } 00170 } 00171 00172 00173 /* ------------------------------------------------------------------------ */ 00174 static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, 00175 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) 00176 { 00177 unsigned long *vptr = (unsigned long *)frm; 00178 #ifndef ORIGINAL 00179 int row_inc = -stride/4; 00180 #else 00181 int row_inc = stride/4; 00182 #endif 00183 int x, y; 00184 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; 00185 00186 /* fill 4x4 block of pixels with colour values from codebooks */ 00187 for (y = 0; y < 4; y++) 00188 { 00189 if (&vptr[y*row_inc] < (unsigned long *)limit) return; 00190 for (x = 0; x < 4; x++) 00191 vptr[y*row_inc + x] = MAKECOLOUR32(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]); 00192 } 00193 } 00194 00195 00196 /* ------------------------------------------------------------------------ */ 00197 static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb) 00198 { 00199 #ifndef ORIGINAL 00200 int row_inc = -stride; 00201 #else 00202 int row_inc = stride; 00203 #endif 00204 int x, y; 00205 00206 /* fill 4x4 block of pixels with colour values from codebook */ 00207 for (y = 0; y < 4; y++) 00208 { 00209 if (&vptr[y*row_inc] < limit) return; 00210 for (x = 0; x < 4; x++) 00211 { 00212 vptr[y*row_inc + x*3 + 0] = cb->b[x/2+(y/2)*2]; 00213 vptr[y*row_inc + x*3 + 1] = cb->g[x/2+(y/2)*2]; 00214 vptr[y*row_inc + x*3 + 2] = cb->r[x/2+(y/2)*2]; 00215 } 00216 } 00217 } 00218 00219 00220 /* ------------------------------------------------------------------------ */ 00221 static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0, 00222 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) 00223 { 00224 #ifndef ORIGINAL 00225 int row_inc = -stride; 00226 #else 00227 int row_inc = stride; 00228 #endif 00229 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; 00230 int x, y; 00231 00232 /* fill 4x4 block of pixels with colour values from codebooks */ 00233 for (y = 0; y < 4; y++) 00234 { 00235 if (&vptr[y*row_inc] < limit) return; 00236 for (x = 0; x < 4; x++) 00237 { 00238 vptr[y*row_inc + x*3 + 0] = cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]; 00239 vptr[y*row_inc + x*3 + 1] = cb[x/2+(y/2)*2]->g[x%2+(y%2)*2]; 00240 vptr[y*row_inc + x*3 + 2] = cb[x/2+(y/2)*2]->r[x%2+(y%2)*2]; 00241 } 00242 } 00243 } 00244 00245 00246 /* ------------------------------------------------------------------------ */ 00247 static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) 00248 { 00249 unsigned short *vptr = (unsigned short *)frm; 00250 #ifndef ORIGINAL 00251 int row_inc = -stride/2; 00252 #else 00253 int row_inc = stride/2; 00254 #endif 00255 int x, y; 00256 00257 /* fill 4x4 block of pixels with colour values from codebook */ 00258 for (y = 0; y < 4; y++) 00259 { 00260 if (&vptr[y*row_inc] < (unsigned short *)limit) return; 00261 for (x = 0; x < 4; x++) 00262 vptr[y*row_inc + x] = MAKECOLOUR16(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]); 00263 } 00264 } 00265 00266 00267 /* ------------------------------------------------------------------------ */ 00268 static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, 00269 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) 00270 { 00271 unsigned short *vptr = (unsigned short *)frm; 00272 #ifndef ORIGINAL 00273 int row_inc = -stride/2; 00274 #else 00275 int row_inc = stride/2; 00276 #endif 00277 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; 00278 int x, y; 00279 00280 /* fill 4x4 block of pixels with colour values from codebooks */ 00281 for (y = 0; y < 4; y++) 00282 { 00283 if (&vptr[y*row_inc] < (unsigned short *)limit) return; 00284 for (x = 0; x < 4; x++) 00285 vptr[y*row_inc + x] = MAKECOLOUR16(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]); 00286 } 00287 } 00288 00289 /* ------------------------------------------------------------------------ */ 00290 static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) 00291 { 00292 unsigned short *vptr = (unsigned short *)frm; 00293 #ifndef ORIGINAL 00294 int row_inc = -stride/2; 00295 #else 00296 int row_inc = stride/2; 00297 #endif 00298 int x, y; 00299 00300 /* fill 4x4 block of pixels with colour values from codebook */ 00301 for (y = 0; y < 4; y++) 00302 { 00303 if (&vptr[y*row_inc] < (unsigned short *)limit) return; 00304 for (x = 0; x < 4; x++) 00305 vptr[y*row_inc + x] = MAKECOLOUR15(cb->r[x/2+(y/2)*2], cb->g[x/2+(y/2)*2], cb->b[x/2+(y/2)*2]); 00306 } 00307 } 00308 00309 00310 /* ------------------------------------------------------------------------ */ 00311 static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, 00312 cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) 00313 { 00314 unsigned short *vptr = (unsigned short *)frm; 00315 #ifndef ORIGINAL 00316 int row_inc = -stride/2; 00317 #else 00318 int row_inc = stride/2; 00319 #endif 00320 cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; 00321 int x, y; 00322 00323 /* fill 4x4 block of pixels with colour values from codebooks */ 00324 for (y = 0; y < 4; y++) 00325 { 00326 if (&vptr[y*row_inc] < (unsigned short *)limit) return; 00327 for (x = 0; x < 4; x++) 00328 vptr[y*row_inc + x] = MAKECOLOUR15(cb[x/2+(y/2)*2]->r[x%2+(y%2)*2], cb[x/2+(y/2)*2]->g[x%2+(y%2)*2], cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]); 00329 } 00330 } 00331 00332 00333 /* ------------------------------------------------------------------------ 00334 * Call this function once at the start of the sequence and save the 00335 * returned context for calls to decode_cinepak(). 00336 */ 00337 static cinepak_info *decode_cinepak_init(void) 00338 { 00339 cinepak_info *cvinfo; 00340 int i; 00341 00342 cvinfo = heap_alloc( sizeof (cinepak_info) ); 00343 if( !cvinfo ) 00344 return NULL; 00345 cvinfo->strip_num = 0; 00346 00347 if(uiclp == NULL) 00348 { 00349 uiclp = uiclip+512; 00350 for(i = -512; i < 512; i++) 00351 uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i)); 00352 } 00353 00354 return cvinfo; 00355 } 00356 00357 static void free_cvinfo( cinepak_info *cvinfo ) 00358 { 00359 unsigned int i; 00360 00361 for( i=0; i<cvinfo->strip_num; i++ ) 00362 { 00363 heap_free(cvinfo->v4_codebook[i]); 00364 heap_free(cvinfo->v1_codebook[i]); 00365 } 00366 heap_free( cvinfo ); 00367 } 00368 00369 typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit, 00370 int stride, cvid_codebook *cb); 00371 typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride, 00372 cvid_codebook *cb0, cvid_codebook *cb1, 00373 cvid_codebook *cb2, cvid_codebook *cb3); 00374 00375 /* ------------------------------------------------------------------------ 00376 * This function decodes a buffer containing a Cinepak encoded frame. 00377 * 00378 * context - the context created by decode_cinepak_init(). 00379 * buf - the input buffer to be decoded 00380 * size - the size of the input buffer 00381 * frame - the output frame buffer (24 or 32 bit per pixel) 00382 * width - the width of the output frame 00383 * height - the height of the output frame 00384 * bit_per_pixel - the number of bits per pixel allocated to the output 00385 * frame (only 24 or 32 bpp are supported) 00386 */ 00387 static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size, 00388 unsigned char *frame, unsigned int width, unsigned int height, int bit_per_pixel) 00389 { 00390 cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL; 00391 unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height, 00392 cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask; 00393 long len, top_size, chunk_size; 00394 unsigned char *frm_ptr; 00395 unsigned int i, cur_strip; 00396 int d0, d1, d2, d3, frm_stride, bpp = 3; 00397 fn_cvid_v1 cvid_v1 = cvid_v1_24; 00398 fn_cvid_v4 cvid_v4 = cvid_v4_24; 00399 00400 y = 0; 00401 y_bottom = 0; 00402 in_buffer = buf; 00403 00404 frame_flags = get_byte(); 00405 len = get_byte() << 16; 00406 len |= get_byte() << 8; 00407 len |= get_byte(); 00408 00409 switch(bit_per_pixel) 00410 { 00411 case 15: 00412 bpp = 2; 00413 cvid_v1 = cvid_v1_15; 00414 cvid_v4 = cvid_v4_15; 00415 break; 00416 case 16: 00417 bpp = 2; 00418 cvid_v1 = cvid_v1_16; 00419 cvid_v4 = cvid_v4_16; 00420 break; 00421 case 24: 00422 bpp = 3; 00423 cvid_v1 = cvid_v1_24; 00424 cvid_v4 = cvid_v4_24; 00425 break; 00426 case 32: 00427 bpp = 4; 00428 cvid_v1 = cvid_v1_32; 00429 cvid_v4 = cvid_v4_32; 00430 break; 00431 } 00432 00433 frm_stride = width * bpp; 00434 frm_ptr = frame; 00435 00436 if(len != size) 00437 { 00438 if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ 00439 if(len != size) 00440 { 00441 ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len); 00442 /* return; */ 00443 } 00444 } 00445 00446 cv_width = get_word(); 00447 cv_height = get_word(); 00448 strips = get_word(); 00449 00450 if(strips > cvinfo->strip_num) 00451 { 00452 if(strips >= MAX_STRIPS) 00453 { 00454 ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS); 00455 return; 00456 } 00457 00458 for(i = cvinfo->strip_num; i < strips; i++) 00459 { 00460 if((cvinfo->v4_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL) 00461 { 00462 ERR("CVID: codebook v4 alloc err\n"); 00463 return; 00464 } 00465 00466 if((cvinfo->v1_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL) 00467 { 00468 ERR("CVID: codebook v1 alloc err\n"); 00469 return; 00470 } 00471 } 00472 } 00473 cvinfo->strip_num = strips; 00474 00475 TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips); 00476 00477 for(cur_strip = 0; cur_strip < strips; cur_strip++) 00478 { 00479 v4_codebook = cvinfo->v4_codebook[cur_strip]; 00480 v1_codebook = cvinfo->v1_codebook[cur_strip]; 00481 00482 if((cur_strip > 0) && (!(frame_flags & 0x01))) 00483 { 00484 memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); 00485 memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); 00486 } 00487 00488 strip_id = get_word(); /* 1000 = key strip, 1100 = iter strip */ 00489 top_size = get_word(); 00490 y0 = get_word(); /* FIXME: most of these are ignored at the moment */ 00491 x0 = get_word(); 00492 y1 = get_word(); 00493 x1 = get_word(); 00494 00495 y_bottom += y1; 00496 top_size -= 12; 00497 x = 0; 00498 if(x1 != width) 00499 WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width); 00500 00501 TRACE(" %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n", 00502 cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom); 00503 00504 while(top_size > 0) 00505 { 00506 chunk_id = get_word(); 00507 chunk_size = get_word(); 00508 00509 TRACE(" %04lx %04ld\n", chunk_id, chunk_size); 00510 top_size -= chunk_size; 00511 chunk_size -= 4; 00512 00513 switch(chunk_id) 00514 { 00515 /* -------------------- Codebook Entries -------------------- */ 00516 case 0x2000: 00517 case 0x2200: 00518 codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook); 00519 cnum = chunk_size/6; 00520 for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0); 00521 break; 00522 00523 case 0x2400: 00524 case 0x2600: /* 8 bit per pixel */ 00525 codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook); 00526 cnum = chunk_size/4; 00527 for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1); 00528 break; 00529 00530 case 0x2100: 00531 case 0x2300: 00532 codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook); 00533 00534 ci = 0; 00535 while(chunk_size > 0) 00536 { 00537 flag = get_long(); 00538 chunk_size -= 4; 00539 00540 for(i = 0; i < 32; i++) 00541 { 00542 if(flag & 0x80000000) 00543 { 00544 chunk_size -= 6; 00545 read_codebook(codebook+ci, 0); 00546 } 00547 00548 ci++; 00549 flag <<= 1; 00550 } 00551 } 00552 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00553 break; 00554 00555 case 0x2500: 00556 case 0x2700: /* 8 bit per pixel */ 00557 codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook); 00558 00559 ci = 0; 00560 while(chunk_size > 0) 00561 { 00562 flag = get_long(); 00563 chunk_size -= 4; 00564 00565 for(i = 0; i < 32; i++) 00566 { 00567 if(flag & 0x80000000) 00568 { 00569 chunk_size -= 4; 00570 read_codebook(codebook+ci, 1); 00571 } 00572 00573 ci++; 00574 flag <<= 1; 00575 } 00576 } 00577 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00578 break; 00579 00580 /* -------------------- Frame -------------------- */ 00581 case 0x3000: 00582 while((chunk_size > 0) && (y < y_bottom)) 00583 { 00584 flag = get_long(); 00585 chunk_size -= 4; 00586 00587 for(i = 0; i < 32; i++) 00588 { 00589 if(y >= y_bottom) break; 00590 if(flag & 0x80000000) /* 4 bytes per block */ 00591 { 00592 d0 = get_byte(); 00593 d1 = get_byte(); 00594 d2 = get_byte(); 00595 d3 = get_byte(); 00596 chunk_size -= 4; 00597 #ifdef ORIGINAL 00598 cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); 00599 #else 00600 cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); 00601 #endif 00602 } 00603 else /* 1 byte per block */ 00604 { 00605 #ifdef ORIGINAL 00606 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); 00607 #else 00608 cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); 00609 #endif 00610 chunk_size--; 00611 } 00612 00613 x += 4; 00614 if(x >= width) 00615 { 00616 x = 0; 00617 y += 4; 00618 } 00619 flag <<= 1; 00620 } 00621 } 00622 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00623 break; 00624 00625 case 0x3100: 00626 while((chunk_size > 0) && (y < y_bottom)) 00627 { 00628 /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */ 00629 flag = get_long(); 00630 chunk_size -= 4; 00631 mask = 0x80000000; 00632 00633 while((mask) && (y < y_bottom)) 00634 { 00635 if(flag & mask) 00636 { 00637 if(mask == 1) 00638 { 00639 if(chunk_size < 0) break; 00640 flag = get_long(); 00641 chunk_size -= 4; 00642 mask = 0x80000000; 00643 } 00644 else mask >>= 1; 00645 00646 if(flag & mask) /* V4 */ 00647 { 00648 d0 = get_byte(); 00649 d1 = get_byte(); 00650 d2 = get_byte(); 00651 d3 = get_byte(); 00652 chunk_size -= 4; 00653 #ifdef ORIGINAL 00654 cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); 00655 #else 00656 cvid_v4(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3); 00657 #endif 00658 } 00659 else /* V1 */ 00660 { 00661 chunk_size--; 00662 #ifdef ORIGINAL 00663 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); 00664 #else 00665 cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); 00666 #endif 00667 } 00668 } /* else SKIP */ 00669 00670 mask >>= 1; 00671 x += 4; 00672 if(x >= width) 00673 { 00674 x = 0; 00675 y += 4; 00676 } 00677 } 00678 } 00679 00680 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00681 break; 00682 00683 case 0x3200: /* each byte is a V1 codebook */ 00684 while((chunk_size > 0) && (y < y_bottom)) 00685 { 00686 #ifdef ORIGINAL 00687 cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); 00688 #else 00689 cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); 00690 #endif 00691 chunk_size--; 00692 x += 4; 00693 if(x >= width) 00694 { 00695 x = 0; 00696 y += 4; 00697 } 00698 } 00699 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00700 break; 00701 00702 default: 00703 ERR("CVID: unknown chunk_id %08lx\n", chunk_id); 00704 while(chunk_size > 0) { skip_byte(); chunk_size--; } 00705 break; 00706 } 00707 } 00708 } 00709 00710 if(len != size) 00711 { 00712 if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ 00713 if(len != size) 00714 { 00715 long xlen; 00716 skip_byte(); 00717 xlen = get_byte() << 16; 00718 xlen |= get_byte() << 8; 00719 xlen |= get_byte(); /* Read Len */ 00720 WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n", 00721 size, len, xlen); 00722 } 00723 } 00724 } 00725 00726 static void ICCVID_dump_BITMAPINFO(const BITMAPINFO * bmi) 00727 { 00728 TRACE( 00729 "planes = %d\n" 00730 "bpp = %d\n" 00731 "height = %d\n" 00732 "width = %d\n" 00733 "compr = %s\n", 00734 bmi->bmiHeader.biPlanes, 00735 bmi->bmiHeader.biBitCount, 00736 bmi->bmiHeader.biHeight, 00737 bmi->bmiHeader.biWidth, 00738 debugstr_an( (const char *)&bmi->bmiHeader.biCompression, 4 ) ); 00739 } 00740 00741 static inline int ICCVID_CheckMask(RGBQUAD bmiColors[3], COLORREF redMask, COLORREF blueMask, COLORREF greenMask) 00742 { 00743 COLORREF realRedMask = MAKECOLOUR32(bmiColors[0].rgbRed, bmiColors[0].rgbGreen, bmiColors[0].rgbBlue); 00744 COLORREF realBlueMask = MAKECOLOUR32(bmiColors[1].rgbRed, bmiColors[1].rgbGreen, bmiColors[1].rgbBlue); 00745 COLORREF realGreenMask = MAKECOLOUR32(bmiColors[2].rgbRed, bmiColors[2].rgbGreen, bmiColors[2].rgbBlue); 00746 00747 TRACE("\nbmiColors[0] = 0x%08x\nbmiColors[1] = 0x%08x\nbmiColors[2] = 0x%08x\n", 00748 realRedMask, realBlueMask, realGreenMask); 00749 00750 if ((realRedMask == redMask) && 00751 (realBlueMask == blueMask) && 00752 (realGreenMask == greenMask)) 00753 return TRUE; 00754 return FALSE; 00755 } 00756 00757 static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) 00758 { 00759 TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out); 00760 00761 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00762 return ICERR_BADPARAM; 00763 00764 TRACE("in: "); 00765 ICCVID_dump_BITMAPINFO(in); 00766 00767 if( in->bmiHeader.biCompression != ICCVID_MAGIC ) 00768 return ICERR_BADFORMAT; 00769 00770 if( out ) 00771 { 00772 TRACE("out: "); 00773 ICCVID_dump_BITMAPINFO(out); 00774 00775 if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) 00776 return ICERR_BADFORMAT; 00777 if( in->bmiHeader.biHeight != out->bmiHeader.biHeight ) 00778 return ICERR_BADFORMAT; 00779 if( in->bmiHeader.biWidth != out->bmiHeader.biWidth ) 00780 return ICERR_BADFORMAT; 00781 00782 switch( out->bmiHeader.biBitCount ) 00783 { 00784 case 16: 00785 if ( out->bmiHeader.biCompression == BI_BITFIELDS ) 00786 { 00787 if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) && 00788 !ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) ) 00789 { 00790 TRACE("unsupported output bit field(s) for 16-bit colors\n"); 00791 return ICERR_BADFORMAT; 00792 } 00793 } 00794 break; 00795 case 24: 00796 case 32: 00797 break; 00798 default: 00799 TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount ); 00800 return ICERR_BADFORMAT; 00801 } 00802 } 00803 00804 return ICERR_OK; 00805 } 00806 00807 static LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) 00808 { 00809 DWORD size; 00810 00811 TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out); 00812 00813 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00814 return ICERR_BADPARAM; 00815 00816 size = in->bmiHeader.biSize; 00817 if (in->bmiHeader.biBitCount <= 8) 00818 size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD); 00819 00820 if( out ) 00821 { 00822 memcpy( out, in, size ); 00823 out->bmiHeader.biCompression = BI_RGB; 00824 out->bmiHeader.biSizeImage = in->bmiHeader.biHeight 00825 * in->bmiHeader.biWidth *4; 00826 return ICERR_OK; 00827 } 00828 return size; 00829 } 00830 00831 static LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) 00832 { 00833 TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out); 00834 00835 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00836 return ICERR_BADPARAM; 00837 00838 info->bits_per_pixel = out->bmiHeader.biBitCount; 00839 00840 if (info->bits_per_pixel == 16) 00841 { 00842 if ( out->bmiHeader.biCompression == BI_BITFIELDS ) 00843 { 00844 if ( ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) ) 00845 info->bits_per_pixel = 15; 00846 else if ( ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) ) 00847 info->bits_per_pixel = 16; 00848 else 00849 { 00850 TRACE("unsupported output bit field(s) for 16-bit colors\n"); 00851 return ICERR_UNSUPPORTED; 00852 } 00853 } 00854 else 00855 info->bits_per_pixel = 15; 00856 } 00857 00858 TRACE("bit_per_pixel = %d\n", info->bits_per_pixel); 00859 00860 if( info->cvinfo ) 00861 free_cvinfo( info->cvinfo ); 00862 info->cvinfo = decode_cinepak_init(); 00863 00864 return ICERR_OK; 00865 } 00866 00867 static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size ) 00868 { 00869 LONG width, height; 00870 00871 TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size); 00872 00873 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00874 return ICERR_BADPARAM; 00875 if (info->cvinfo==NULL) 00876 { 00877 ERR("ICM_DECOMPRESS sent after ICM_DECOMPRESS_END\n"); 00878 return ICERR_BADPARAM; 00879 } 00880 00881 width = icd->lpbiInput->biWidth; 00882 height = icd->lpbiInput->biHeight; 00883 00884 decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage, 00885 icd->lpOutput, width, height, info->bits_per_pixel); 00886 00887 return ICERR_OK; 00888 } 00889 00890 static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size ) 00891 { 00892 LONG width, height; 00893 00894 TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size); 00895 00896 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00897 return ICERR_BADPARAM; 00898 if (info->cvinfo==NULL) 00899 { 00900 ERR("ICM_DECOMPRESSEX sent after ICM_DECOMPRESS_END\n"); 00901 return ICERR_BADPARAM; 00902 } 00903 00904 /* FIXME: flags are ignored */ 00905 00906 width = icd->lpbiSrc->biWidth; 00907 height = icd->lpbiSrc->biHeight; 00908 00909 decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage, 00910 icd->lpDst, width, height, info->bits_per_pixel); 00911 00912 return ICERR_OK; 00913 } 00914 00915 static LRESULT ICCVID_Close( ICCVID_Info *info ) 00916 { 00917 if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) 00918 return 0; 00919 if( info->cvinfo ) 00920 free_cvinfo( info->cvinfo ); 00921 heap_free( info ); 00922 return 1; 00923 } 00924 00925 static LRESULT ICCVID_GetInfo( ICCVID_Info *info, ICINFO *icinfo, DWORD dwSize ) 00926 { 00927 if (!icinfo) return sizeof(ICINFO); 00928 if (dwSize < sizeof(ICINFO)) return 0; 00929 00930 icinfo->dwSize = sizeof(ICINFO); 00931 icinfo->fccType = ICTYPE_VIDEO; 00932 icinfo->fccHandler = info ? info->dwMagic : ICCVID_MAGIC; 00933 icinfo->dwFlags = 0; 00934 icinfo->dwVersion = ICVERSION; 00935 icinfo->dwVersionICM = ICVERSION; 00936 00937 LoadStringW(ICCVID_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR)); 00938 LoadStringW(ICCVID_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR)); 00939 /* msvfw32 will fill icinfo->szDriver for us */ 00940 00941 return sizeof(ICINFO); 00942 } 00943 00944 static LRESULT ICCVID_DecompressEnd( ICCVID_Info *info ) 00945 { 00946 if( info->cvinfo ) 00947 { 00948 free_cvinfo( info->cvinfo ); 00949 info->cvinfo = NULL; 00950 } 00951 return ICERR_OK; 00952 } 00953 00954 LRESULT WINAPI ICCVID_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg, 00955 LPARAM lParam1, LPARAM lParam2) 00956 { 00957 ICCVID_Info *info = (ICCVID_Info *) dwDriverId; 00958 00959 TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2); 00960 00961 switch( msg ) 00962 { 00963 case DRV_LOAD: 00964 TRACE("Loaded\n"); 00965 return 1; 00966 case DRV_ENABLE: 00967 return 0; 00968 case DRV_DISABLE: 00969 return 0; 00970 case DRV_FREE: 00971 return 0; 00972 00973 case DRV_OPEN: 00974 { 00975 ICINFO *icinfo = (ICINFO *)lParam2; 00976 00977 TRACE("Opened\n"); 00978 00979 if (icinfo && compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return 0; 00980 00981 info = heap_alloc( sizeof (ICCVID_Info) ); 00982 if( info ) 00983 { 00984 info->dwMagic = ICCVID_MAGIC; 00985 info->cvinfo = NULL; 00986 } 00987 return (LRESULT) info; 00988 } 00989 00990 case DRV_CLOSE: 00991 return ICCVID_Close( info ); 00992 00993 case ICM_GETINFO: 00994 return ICCVID_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 ); 00995 00996 case ICM_DECOMPRESS_QUERY: 00997 return ICCVID_DecompressQuery( info, (LPBITMAPINFO) lParam1, 00998 (LPBITMAPINFO) lParam2 ); 00999 case ICM_DECOMPRESS_GET_FORMAT: 01000 return ICCVID_DecompressGetFormat( info, (LPBITMAPINFO) lParam1, 01001 (LPBITMAPINFO) lParam2 ); 01002 case ICM_DECOMPRESS_BEGIN: 01003 return ICCVID_DecompressBegin( info, (LPBITMAPINFO) lParam1, 01004 (LPBITMAPINFO) lParam2 ); 01005 case ICM_DECOMPRESS: 01006 return ICCVID_Decompress( info, (ICDECOMPRESS*) lParam1, 01007 (DWORD) lParam2 ); 01008 case ICM_DECOMPRESSEX: 01009 return ICCVID_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, 01010 (DWORD) lParam2 ); 01011 01012 case ICM_DECOMPRESS_END: 01013 return ICCVID_DecompressEnd( info ); 01014 01015 case ICM_COMPRESS_QUERY: 01016 FIXME("compression not implemented\n"); 01017 return ICERR_BADFORMAT; 01018 01019 case ICM_CONFIGURE: 01020 return ICERR_UNSUPPORTED; 01021 01022 default: 01023 FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2); 01024 } 01025 return ICERR_UNSUPPORTED; 01026 } 01027 01028 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) 01029 { 01030 TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved); 01031 01032 switch (dwReason) 01033 { 01034 case DLL_PROCESS_ATTACH: 01035 DisableThreadLibraryCalls(hModule); 01036 ICCVID_hModule = hModule; 01037 break; 01038 01039 case DLL_PROCESS_DETACH: 01040 break; 01041 } 01042 return TRUE; 01043 } Generated on Sat May 26 2012 04:22:38 for ReactOS by
1.7.6.1
|