diff --git a/reactos/baseaddress.rbuild b/reactos/baseaddress.rbuild index 2036254cac9..567666925f2 100644 --- a/reactos/baseaddress.rbuild +++ b/reactos/baseaddress.rbuild @@ -18,6 +18,8 @@ + + @@ -119,17 +121,20 @@ + + + diff --git a/reactos/boot/bootdata/hivesft_arm.inf b/reactos/boot/bootdata/hivesft_arm.inf index b4c43a0cecd..4838fdbd198 100644 --- a/reactos/boot/bootdata/hivesft_arm.inf +++ b/reactos/boot/bootdata/hivesft_arm.inf @@ -60,6 +60,23 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midimapper",0x000 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wavemapper",0x00000000,"c:\reactos\system32\msacm32.dll" ;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wave",0x00000000,"sndblst.dll" HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midi",0x00000000,"c:\reactos\system32\beepmidi.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msadpcm",0x00000000,"c:\reactos\system32\msadp32.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msg711",0x00000000,"c:\reactos\system32\msg711.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.imaadpcm",0x00000000,"c:\reactos\system32\imaadp32.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.cvid",0x00000000,"c:\reactos\system32\iccvid.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.mrle",0x00000000,"c:\reactos\system32\msrle32.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.msvc",0x00000000,"c:\reactos\system32\msvidc32.dll" + +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","AVIVideo",0x00000002,"c:\reactos\system32\mciavi32.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","CDAudio",0x00000002,"c:\reactos\system32\mcicda.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","Sequencer",0x00000002,"c:\reactos\system32\mciseq.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","WaveAudio",0x00000002,"c:\reactos\system32\mciwave.dll" + +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","avi",0x00000002,"avivideo" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","cda",0x00000002,"CDAudio" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","mid",0x00000002,"Sequencer" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","rmi",0x00000002,"Sequencer" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","wav",0x00000002,"WaveAudio" ; Mesa OpenGL Driver HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers","DefaultDriver",0x00000000,"Mesa" diff --git a/reactos/boot/bootdata/hivesft_i386.inf b/reactos/boot/bootdata/hivesft_i386.inf index 9c969e1ba27..bc45bfa6ec3 100644 --- a/reactos/boot/bootdata/hivesft_i386.inf +++ b/reactos/boot/bootdata/hivesft_i386.inf @@ -65,6 +65,23 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midimapper",0x000 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wavemapper",0x00000000,"c:\reactos\system32\msacm32.dll" ;HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","wave",0x00000000,"sndblst.dll" HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","midi",0x00000000,"c:\reactos\system32\beepmidi.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msadpcm",0x00000000,"c:\reactos\system32\msadp32.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.msg711",0x00000000,"c:\reactos\system32\msg711.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","msacm.imaadpcm",0x00000000,"c:\reactos\system32\imaadp32.acm" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.cvid",0x00000000,"c:\reactos\system32\iccvid.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.mrle",0x00000000,"c:\reactos\system32\msrle32.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32","vidc.msvc",0x00000000,"c:\reactos\system32\msvidc32.dll" + +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","AVIVideo",0x00000002,"c:\reactos\system32\mciavi32.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","CDAudio",0x00000002,"c:\reactos\system32\mcicda.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","Sequencer",0x00000002,"c:\reactos\system32\mciseq.dll" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI32","WaveAudio",0x00000002,"c:\reactos\system32\mciwave.dll" + +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","avi",0x00000002,"avivideo" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","cda",0x00000002,"CDAudio" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","mid",0x00000002,"Sequencer" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","rmi",0x00000002,"Sequencer" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions","wav",0x00000002,"WaveAudio" ; Mesa OpenGL Driver HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers","DefaultDriver",0x00000000,"Mesa" diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index b578b6ebbf8..a433806d8d4 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -276,7 +276,9 @@ dll\win32\glu32\glu32.dll 1 dll\win32\hhctrl.ocx\hhctrl.ocx 1 dll\win32\hid\hid.dll 1 dll\win32\hlink\hlink.dll 1 +dll\win32\iccvid\iccvid.dll 1 dll\win32\icmp\icmp.dll 1 +dll\win32\imaadp32.acm\imaadp32.acm 1 dll\win32\imagehlp\imagehlp.dll 1 dll\win32\imm32\imm32.dll 1 dll\win32\inetcomm\inetcomm.dll 1 @@ -303,12 +305,14 @@ dll\win32\modemui\modemui.dll 1 dll\win32\mpr\mpr.dll 1 dll\win32\mprapi\mprapi.dll 1 dll\win32\msacm32\msacm32.dll 1 +dll\win32\msadp32.acm\msadp32.acm 1 dll\win32\msafd\msafd.dll 1 dll\win32\mscat32\mscat32.dll 1 dll\win32\mscms\mscms.dll 1 dll\win32\mscoree\mscoree.dll 1 dll\win32\msctf\msctf.dll 1 dll\win32\msftedit\msftedit.dll 1 +dll\win32\msg711.acm\msg711.acm 1 dll\win32\msgina\msgina.dll 1 dll\win32\mshtml\mshtml.dll 1 dll\win32\mshtml.tlb\mshtml.tlb 1 @@ -321,6 +325,7 @@ dll\win32\msvcrt\msvcrt.dll 1 dll\win32\msvcrt20\msvcrt20.dll 1 dll\win32\msvcrt40\msvcrt40.dll 1 dll\win32\msvfw32\msvfw32.dll 1 +dll\win32\msvidc32\msvidc32.dll 1 dll\win32\mswsock\mswsock.dll 1 dll\win32\msxml3\msxml3.dll 1 dll\win32\nddeapi\nddeapi.dll 1 diff --git a/reactos/dll/win32/iccvid/iccvid.c b/reactos/dll/win32/iccvid/iccvid.c new file mode 100644 index 00000000000..77328eabcda --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid.c @@ -0,0 +1,1042 @@ +/* + * Radius Cinepak Video Decoder + * + * Copyright 2001 Dr. Tim Ferguson (see below) + * Portions Copyright 2003 Mike McCormack for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Copyright notice from original source: + * ------------------------------------------------------------------------ + * Radius Cinepak Video Decoder + * + * Dr. Tim Ferguson, 2001. + * For more details on the algorithm: + * http://www.csse.monash.edu.au/~timf/videocodec.html + * + * This is basically a vector quantiser with adaptive vector density. The + * frame is segmented into 4x4 pixel blocks, and each block is coded using + * either 1 or 4 vectors. + * + * There are still some issues with this code yet to be resolved. In + * particular with decoding in the strip boundaries. However, I have not + * yet found a sequence it doesn't work on. Ill keep trying :) + * + * You may freely use this source code. I only ask that you reference its + * source in your projects documentation: + * Tim Ferguson: http://www.csse.monash.edu.au/~timf/ + * ------------------------------------------------------------------------ */ + +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "commdlg.h" +#include "vfw.h" +#include "mmsystem.h" +#include "iccvid_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(iccvid); + +static HINSTANCE ICCVID_hModule; + +#define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd') + +#define DBUG 0 +#define MAX_STRIPS 32 + +/* ------------------------------------------------------------------------ */ +typedef struct +{ + unsigned char y0, y1, y2, y3; + char u, v; + unsigned char r[4], g[4], b[4]; +} cvid_codebook; + +typedef struct { + cvid_codebook *v4_codebook[MAX_STRIPS]; + cvid_codebook *v1_codebook[MAX_STRIPS]; + unsigned int strip_num; +} cinepak_info; + +typedef struct _ICCVID_Info +{ + DWORD dwMagic; + int bits_per_pixel; + cinepak_info *cvinfo; +} ICCVID_Info; + +static inline LPVOID heap_alloc( size_t size ) +{ + return HeapAlloc( GetProcessHeap(), 0, size ); +} + +static inline BOOL heap_free( LPVOID ptr ) +{ + return HeapFree( GetProcessHeap(), 0, ptr ); +} + + +/* ------------------------------------------------------------------------ */ +static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL; + +#define get_byte() *(in_buffer++) +#define skip_byte() in_buffer++ +#define get_word() ((unsigned short)(in_buffer += 2, \ + (in_buffer[-2] << 8 | in_buffer[-1]))) +#define get_long() ((unsigned long)(in_buffer += 4, \ + (in_buffer[-4] << 24 | in_buffer[-3] << 16 | in_buffer[-2] << 8 | in_buffer[-1]))) + + +/* ---------------------------------------------------------------------- */ +static inline void read_codebook(cvid_codebook *c, int mode) +{ +int uvr, uvg, uvb; + + if(mode) /* black and white */ + { + c->y0 = get_byte(); + c->y1 = get_byte(); + c->y2 = get_byte(); + c->y3 = get_byte(); + c->u = c->v = 0; + + c->r[0] = c->g[0] = c->b[0] = c->y0; + c->r[1] = c->g[1] = c->b[1] = c->y1; + c->r[2] = c->g[2] = c->b[2] = c->y2; + c->r[3] = c->g[3] = c->b[3] = c->y3; + } + else /* colour */ + { + c->y0 = get_byte(); /* luma */ + c->y1 = get_byte(); + c->y2 = get_byte(); + c->y3 = get_byte(); + c->u = get_byte(); /* chroma */ + c->v = get_byte(); + + uvr = c->v << 1; + uvg = -((c->u+1) >> 1) - c->v; + uvb = c->u << 1; + + c->r[0] = uiclp[c->y0 + uvr]; c->g[0] = uiclp[c->y0 + uvg]; c->b[0] = uiclp[c->y0 + uvb]; + c->r[1] = uiclp[c->y1 + uvr]; c->g[1] = uiclp[c->y1 + uvg]; c->b[1] = uiclp[c->y1 + uvb]; + c->r[2] = uiclp[c->y2 + uvr]; c->g[2] = uiclp[c->y2 + uvg]; c->b[2] = uiclp[c->y2 + uvb]; + c->r[3] = uiclp[c->y3 + uvr]; c->g[3] = uiclp[c->y3 + uvg]; c->b[3] = uiclp[c->y3 + uvb]; + } +} + + +#define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b)) +/*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/ +#define MAKECOLOUR16(r,g,b) (((r) >> 3) << 11)| (((g) >> 2) << 5)| (((b) >> 3) << 0) +#define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0) + +/* ------------------------------------------------------------------------ */ +static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) +{ +unsigned long *vptr = (unsigned long *)frm; +#ifndef ORIGINAL +int row_inc = -stride/4; +#else +int row_inc = stride/4; +#endif +int x, y; + + /* fill 4x4 block of pixels with colour values from codebook */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned long *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, + cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) +{ +unsigned long *vptr = (unsigned long *)frm; +#ifndef ORIGINAL +int row_inc = -stride/4; +#else +int row_inc = stride/4; +#endif +int x, y; +cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; + + /* fill 4x4 block of pixels with colour values from codebooks */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned long *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb) +{ +#ifndef ORIGINAL +int row_inc = -stride; +#else +int row_inc = stride; +#endif +int x, y; + + /* fill 4x4 block of pixels with colour values from codebook */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < limit) return; + for (x = 0; x < 4; x++) + { + vptr[y*row_inc + x*3 + 0] = cb->b[x/2+(y/2)*2]; + vptr[y*row_inc + x*3 + 1] = cb->g[x/2+(y/2)*2]; + vptr[y*row_inc + x*3 + 2] = cb->r[x/2+(y/2)*2]; + } + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0, + cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) +{ +#ifndef ORIGINAL +int row_inc = -stride; +#else +int row_inc = stride; +#endif +cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; +int x, y; + + /* fill 4x4 block of pixels with colour values from codebooks */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < limit) return; + for (x = 0; x < 4; x++) + { + vptr[y*row_inc + x*3 + 0] = cb[x/2+(y/2)*2]->b[x%2+(y%2)*2]; + vptr[y*row_inc + x*3 + 1] = cb[x/2+(y/2)*2]->g[x%2+(y%2)*2]; + vptr[y*row_inc + x*3 + 2] = cb[x/2+(y/2)*2]->r[x%2+(y%2)*2]; + } + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) +{ +unsigned short *vptr = (unsigned short *)frm; +#ifndef ORIGINAL +int row_inc = -stride/2; +#else +int row_inc = stride/2; +#endif +int x, y; + + /* fill 4x4 block of pixels with colour values from codebook */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned short *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, + cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) +{ +unsigned short *vptr = (unsigned short *)frm; +#ifndef ORIGINAL +int row_inc = -stride/2; +#else +int row_inc = stride/2; +#endif +cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; +int x, y; + + /* fill 4x4 block of pixels with colour values from codebooks */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned short *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + +/* ------------------------------------------------------------------------ */ +static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb) +{ +unsigned short *vptr = (unsigned short *)frm; +#ifndef ORIGINAL +int row_inc = -stride/2; +#else +int row_inc = stride/2; +#endif +int x, y; + + /* fill 4x4 block of pixels with colour values from codebook */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned short *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + + +/* ------------------------------------------------------------------------ */ +static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0, + cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3) +{ +unsigned short *vptr = (unsigned short *)frm; +#ifndef ORIGINAL +int row_inc = -stride/2; +#else +int row_inc = stride/2; +#endif +cvid_codebook * cb[] = {cb0,cb1,cb2,cb3}; +int x, y; + + /* fill 4x4 block of pixels with colour values from codebooks */ + for (y = 0; y < 4; y++) + { + if (&vptr[y*row_inc] < (unsigned short *)limit) return; + for (x = 0; x < 4; x++) + 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]); + } +} + + +/* ------------------------------------------------------------------------ + * Call this function once at the start of the sequence and save the + * returned context for calls to decode_cinepak(). + */ +static cinepak_info *decode_cinepak_init(void) +{ + cinepak_info *cvinfo; + int i; + + cvinfo = heap_alloc( sizeof (cinepak_info) ); + if( !cvinfo ) + return NULL; + cvinfo->strip_num = 0; + + if(uiclp == NULL) + { + uiclp = uiclip+512; + for(i = -512; i < 512; i++) + uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i)); + } + + return cvinfo; +} + +static void free_cvinfo( cinepak_info *cvinfo ) +{ + unsigned int i; + + for( i=0; istrip_num; i++ ) + { + heap_free(cvinfo->v4_codebook[i]); + heap_free(cvinfo->v1_codebook[i]); + } + heap_free( cvinfo ); +} + +typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit, + int stride, cvid_codebook *cb); +typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride, + cvid_codebook *cb0, cvid_codebook *cb1, + cvid_codebook *cb2, cvid_codebook *cb3); + +/* ------------------------------------------------------------------------ + * This function decodes a buffer containing a Cinepak encoded frame. + * + * context - the context created by decode_cinepak_init(). + * buf - the input buffer to be decoded + * size - the size of the input buffer + * frame - the output frame buffer (24 or 32 bit per pixel) + * width - the width of the output frame + * height - the height of the output frame + * bit_per_pixel - the number of bits per pixel allocated to the output + * frame (only 24 or 32 bpp are supported) + */ +static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size, + unsigned char *frame, unsigned int width, unsigned int height, int bit_per_pixel) +{ + cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL; + unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height, + cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask; + long len, top_size, chunk_size; + unsigned char *frm_ptr; + unsigned int i, cur_strip; + int d0, d1, d2, d3, frm_stride, bpp = 3; + fn_cvid_v1 cvid_v1 = cvid_v1_24; + fn_cvid_v4 cvid_v4 = cvid_v4_24; + + y = 0; + y_bottom = 0; + in_buffer = buf; + + frame_flags = get_byte(); + len = get_byte() << 16; + len |= get_byte() << 8; + len |= get_byte(); + + switch(bit_per_pixel) + { + case 15: + bpp = 2; + cvid_v1 = cvid_v1_15; + cvid_v4 = cvid_v4_15; + break; + case 16: + bpp = 2; + cvid_v1 = cvid_v1_16; + cvid_v4 = cvid_v4_16; + break; + case 24: + bpp = 3; + cvid_v1 = cvid_v1_24; + cvid_v4 = cvid_v4_24; + break; + case 32: + bpp = 4; + cvid_v1 = cvid_v1_32; + cvid_v4 = cvid_v4_32; + break; + } + + frm_stride = width * bpp; + frm_ptr = frame; + + if(len != size) + { + if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ + if(len != size) + { + ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len); + /* return; */ + } + } + + cv_width = get_word(); + cv_height = get_word(); + strips = get_word(); + + if(strips > cvinfo->strip_num) + { + if(strips >= MAX_STRIPS) + { + ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS); + return; + } + + for(i = cvinfo->strip_num; i < strips; i++) + { + if((cvinfo->v4_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL) + { + ERR("CVID: codebook v4 alloc err\n"); + return; + } + + if((cvinfo->v1_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL) + { + ERR("CVID: codebook v1 alloc err\n"); + return; + } + } + } + cvinfo->strip_num = strips; + + TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips); + + for(cur_strip = 0; cur_strip < strips; cur_strip++) + { + v4_codebook = cvinfo->v4_codebook[cur_strip]; + v1_codebook = cvinfo->v1_codebook[cur_strip]; + + if((cur_strip > 0) && (!(frame_flags & 0x01))) + { + memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); + memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook)); + } + + strip_id = get_word(); /* 1000 = key strip, 1100 = iter strip */ + top_size = get_word(); + y0 = get_word(); /* FIXME: most of these are ignored at the moment */ + x0 = get_word(); + y1 = get_word(); + x1 = get_word(); + + y_bottom += y1; + top_size -= 12; + x = 0; + if(x1 != width) + WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width); + + TRACE(" %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n", + cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom); + + while(top_size > 0) + { + chunk_id = get_word(); + chunk_size = get_word(); + + TRACE(" %04lx %04ld\n", chunk_id, chunk_size); + top_size -= chunk_size; + chunk_size -= 4; + + switch(chunk_id) + { + /* -------------------- Codebook Entries -------------------- */ + case 0x2000: + case 0x2200: + codebook = (chunk_id == 0x2200 ? v1_codebook : v4_codebook); + cnum = chunk_size/6; + for(i = 0; i < cnum; i++) read_codebook(codebook+i, 0); + break; + + case 0x2400: + case 0x2600: /* 8 bit per pixel */ + codebook = (chunk_id == 0x2600 ? v1_codebook : v4_codebook); + cnum = chunk_size/4; + for(i = 0; i < cnum; i++) read_codebook(codebook+i, 1); + break; + + case 0x2100: + case 0x2300: + codebook = (chunk_id == 0x2300 ? v1_codebook : v4_codebook); + + ci = 0; + while(chunk_size > 0) + { + flag = get_long(); + chunk_size -= 4; + + for(i = 0; i < 32; i++) + { + if(flag & 0x80000000) + { + chunk_size -= 6; + read_codebook(codebook+ci, 0); + } + + ci++; + flag <<= 1; + } + } + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + + case 0x2500: + case 0x2700: /* 8 bit per pixel */ + codebook = (chunk_id == 0x2700 ? v1_codebook : v4_codebook); + + ci = 0; + while(chunk_size > 0) + { + flag = get_long(); + chunk_size -= 4; + + for(i = 0; i < 32; i++) + { + if(flag & 0x80000000) + { + chunk_size -= 4; + read_codebook(codebook+ci, 1); + } + + ci++; + flag <<= 1; + } + } + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + + /* -------------------- Frame -------------------- */ + case 0x3000: + while((chunk_size > 0) && (y < y_bottom)) + { + flag = get_long(); + chunk_size -= 4; + + for(i = 0; i < 32; i++) + { + if(y >= y_bottom) break; + if(flag & 0x80000000) /* 4 bytes per block */ + { + d0 = get_byte(); + d1 = get_byte(); + d2 = get_byte(); + d3 = get_byte(); + chunk_size -= 4; +#ifdef ORIGINAL + 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); +#else + 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); +#endif + } + else /* 1 byte per block */ + { +#ifdef ORIGINAL + cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); +#else + cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); +#endif + chunk_size--; + } + + x += 4; + if(x >= width) + { + x = 0; + y += 4; + } + flag <<= 1; + } + } + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + + case 0x3100: + while((chunk_size > 0) && (y < y_bottom)) + { + /* ---- flag bits: 0 = SKIP, 10 = V1, 11 = V4 ---- */ + flag = get_long(); + chunk_size -= 4; + mask = 0x80000000; + + while((mask) && (y < y_bottom)) + { + if(flag & mask) + { + if(mask == 1) + { + if(chunk_size < 0) break; + flag = get_long(); + chunk_size -= 4; + mask = 0x80000000; + } + else mask >>= 1; + + if(flag & mask) /* V4 */ + { + d0 = get_byte(); + d1 = get_byte(); + d2 = get_byte(); + d3 = get_byte(); + chunk_size -= 4; +#ifdef ORIGINAL + 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); +#else + 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); +#endif + } + else /* V1 */ + { + chunk_size--; +#ifdef ORIGINAL + cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); +#else + cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); +#endif + } + } /* else SKIP */ + + mask >>= 1; + x += 4; + if(x >= width) + { + x = 0; + y += 4; + } + } + } + + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + + case 0x3200: /* each byte is a V1 codebook */ + while((chunk_size > 0) && (y < y_bottom)) + { +#ifdef ORIGINAL + cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte()); +#else + cvid_v1(frm_ptr + ((height - 1 - y) * frm_stride + x * bpp), frame, frm_stride, v1_codebook + get_byte()); +#endif + chunk_size--; + x += 4; + if(x >= width) + { + x = 0; + y += 4; + } + } + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + + default: + ERR("CVID: unknown chunk_id %08lx\n", chunk_id); + while(chunk_size > 0) { skip_byte(); chunk_size--; } + break; + } + } + } + + if(len != size) + { + if(len & 0x01) len++; /* AVIs tend to have a size mismatch */ + if(len != size) + { + long xlen; + skip_byte(); + xlen = get_byte() << 16; + xlen |= get_byte() << 8; + xlen |= get_byte(); /* Read Len */ + WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n", + size, len, xlen); + } + } +} + +static void ICCVID_dump_BITMAPINFO(const BITMAPINFO * bmi) +{ + TRACE( + "planes = %d\n" + "bpp = %d\n" + "height = %d\n" + "width = %d\n" + "compr = %s\n", + bmi->bmiHeader.biPlanes, + bmi->bmiHeader.biBitCount, + bmi->bmiHeader.biHeight, + bmi->bmiHeader.biWidth, + debugstr_an( (const char *)&bmi->bmiHeader.biCompression, 4 ) ); +} + +static inline int ICCVID_CheckMask(RGBQUAD bmiColors[3], COLORREF redMask, COLORREF blueMask, COLORREF greenMask) +{ + COLORREF realRedMask = MAKECOLOUR32(bmiColors[0].rgbRed, bmiColors[0].rgbGreen, bmiColors[0].rgbBlue); + COLORREF realBlueMask = MAKECOLOUR32(bmiColors[1].rgbRed, bmiColors[1].rgbGreen, bmiColors[1].rgbBlue); + COLORREF realGreenMask = MAKECOLOUR32(bmiColors[2].rgbRed, bmiColors[2].rgbGreen, bmiColors[2].rgbBlue); + + TRACE("\nbmiColors[0] = 0x%08x\nbmiColors[1] = 0x%08x\nbmiColors[2] = 0x%08x\n", + realRedMask, realBlueMask, realGreenMask); + + if ((realRedMask == redMask) && + (realBlueMask == blueMask) && + (realGreenMask == greenMask)) + return TRUE; + return FALSE; +} + +static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return ICERR_BADPARAM; + + TRACE("in: "); + ICCVID_dump_BITMAPINFO(in); + + if( in->bmiHeader.biCompression != ICCVID_MAGIC ) + return ICERR_BADFORMAT; + + if( out ) + { + TRACE("out: "); + ICCVID_dump_BITMAPINFO(out); + + if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) + return ICERR_BADFORMAT; + if( in->bmiHeader.biHeight != out->bmiHeader.biHeight ) + return ICERR_BADFORMAT; + if( in->bmiHeader.biWidth != out->bmiHeader.biWidth ) + return ICERR_BADFORMAT; + + switch( out->bmiHeader.biBitCount ) + { + case 16: + if ( out->bmiHeader.biCompression == BI_BITFIELDS ) + { + if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) && + !ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) ) + { + TRACE("unsupported output bit field(s) for 16-bit colors\n"); + return ICERR_BADFORMAT; + } + } + break; + case 24: + case 32: + break; + default: + TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount ); + return ICERR_BADFORMAT; + } + } + + return ICERR_OK; +} + +static LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + DWORD size; + + TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return ICERR_BADPARAM; + + size = in->bmiHeader.biSize; + if (in->bmiHeader.biBitCount <= 8) + size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD); + + if( out ) + { + memcpy( out, in, size ); + out->bmiHeader.biCompression = BI_RGB; + out->bmiHeader.biSizeImage = in->bmiHeader.biHeight + * in->bmiHeader.biWidth *4; + return ICERR_OK; + } + return size; +} + +static LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return ICERR_BADPARAM; + + info->bits_per_pixel = out->bmiHeader.biBitCount; + + if (info->bits_per_pixel == 16) + { + if ( out->bmiHeader.biCompression == BI_BITFIELDS ) + { + if ( ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) ) + info->bits_per_pixel = 15; + else if ( ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) ) + info->bits_per_pixel = 16; + else + { + TRACE("unsupported output bit field(s) for 16-bit colors\n"); + return ICERR_UNSUPPORTED; + } + } + else + info->bits_per_pixel = 15; + } + + TRACE("bit_per_pixel = %d\n", info->bits_per_pixel); + + if( info->cvinfo ) + free_cvinfo( info->cvinfo ); + info->cvinfo = decode_cinepak_init(); + + return ICERR_OK; +} + +static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size ) +{ + LONG width, height; + + TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size); + + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return ICERR_BADPARAM; + if (info->cvinfo==NULL) + { + ERR("ICM_DECOMPRESS sent after ICM_DECOMPRESS_END\n"); + return ICERR_BADPARAM; + } + + width = icd->lpbiInput->biWidth; + height = icd->lpbiInput->biHeight; + + decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage, + icd->lpOutput, width, height, info->bits_per_pixel); + + return ICERR_OK; +} + +static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size ) +{ + LONG width, height; + + TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size); + + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return ICERR_BADPARAM; + if (info->cvinfo==NULL) + { + ERR("ICM_DECOMPRESSEX sent after ICM_DECOMPRESS_END\n"); + return ICERR_BADPARAM; + } + + /* FIXME: flags are ignored */ + + width = icd->lpbiSrc->biWidth; + height = icd->lpbiSrc->biHeight; + + decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage, + icd->lpDst, width, height, info->bits_per_pixel); + + return ICERR_OK; +} + +static LRESULT ICCVID_Close( ICCVID_Info *info ) +{ + if( (info==NULL) || (info->dwMagic!=ICCVID_MAGIC) ) + return 0; + if( info->cvinfo ) + free_cvinfo( info->cvinfo ); + heap_free( info ); + return 1; +} + +static LRESULT ICCVID_GetInfo( ICCVID_Info *info, ICINFO *icinfo, DWORD dwSize ) +{ + if (!icinfo) return sizeof(ICINFO); + if (dwSize < sizeof(ICINFO)) return 0; + + icinfo->dwSize = sizeof(ICINFO); + icinfo->fccType = ICTYPE_VIDEO; + icinfo->fccHandler = info ? info->dwMagic : ICCVID_MAGIC; + icinfo->dwFlags = 0; + icinfo->dwVersion = ICVERSION; + icinfo->dwVersionICM = ICVERSION; + + LoadStringW(ICCVID_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR)); + LoadStringW(ICCVID_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR)); + /* msvfw32 will fill icinfo->szDriver for us */ + + return sizeof(ICINFO); +} + +static LRESULT ICCVID_DecompressEnd( ICCVID_Info *info ) +{ + if( info->cvinfo ) + { + free_cvinfo( info->cvinfo ); + info->cvinfo = NULL; + } + return ICERR_OK; +} + +LRESULT WINAPI ICCVID_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg, + LPARAM lParam1, LPARAM lParam2) +{ + ICCVID_Info *info = (ICCVID_Info *) dwDriverId; + + TRACE("%ld %p %d %ld %ld\n", dwDriverId, hdrvr, msg, lParam1, lParam2); + + switch( msg ) + { + case DRV_LOAD: + TRACE("Loaded\n"); + return 1; + case DRV_ENABLE: + return 0; + case DRV_DISABLE: + return 0; + case DRV_FREE: + return 0; + + case DRV_OPEN: + { + ICINFO *icinfo = (ICINFO *)lParam2; + + TRACE("Opened\n"); + + if (icinfo && icinfo->fccType != ICTYPE_VIDEO) return 0; + + info = heap_alloc( sizeof (ICCVID_Info) ); + if( info ) + { + info->dwMagic = ICCVID_MAGIC; + info->cvinfo = NULL; + } + return (LRESULT) info; + } + + case DRV_CLOSE: + return ICCVID_Close( info ); + + case ICM_GETINFO: + return ICCVID_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 ); + + case ICM_DECOMPRESS_QUERY: + return ICCVID_DecompressQuery( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + case ICM_DECOMPRESS_GET_FORMAT: + return ICCVID_DecompressGetFormat( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + case ICM_DECOMPRESS_BEGIN: + return ICCVID_DecompressBegin( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + case ICM_DECOMPRESS: + return ICCVID_Decompress( info, (ICDECOMPRESS*) lParam1, + (DWORD) lParam2 ); + case ICM_DECOMPRESSEX: + return ICCVID_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, + (DWORD) lParam2 ); + + case ICM_DECOMPRESS_END: + return ICCVID_DecompressEnd( info ); + + case ICM_COMPRESS_QUERY: + FIXME("compression not implemented\n"); + return ICERR_BADFORMAT; + + case ICM_CONFIGURE: + return ICERR_UNSUPPORTED; + + default: + FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2); + } + return ICERR_UNSUPPORTED; +} + +BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) +{ + TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + ICCVID_hModule = hModule; + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} diff --git a/reactos/dll/win32/iccvid/iccvid.rbuild b/reactos/dll/win32/iccvid/iccvid.rbuild new file mode 100644 index 00000000000..8c73f6f6771 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid.rbuild @@ -0,0 +1,12 @@ + + + . + include/reactos/wine + + iccvid.c + rsrc.rc + wine + user32 + kernel32 + ntdll + \ No newline at end of file diff --git a/reactos/dll/win32/iccvid/iccvid.spec b/reactos/dll/win32/iccvid/iccvid.spec new file mode 100644 index 00000000000..e77601d46db --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid.spec @@ -0,0 +1 @@ +@ stdcall -private DriverProc(long long long long long) ICCVID_DriverProc diff --git a/reactos/dll/win32/iccvid/iccvid_Da.rc b/reactos/dll/win32/iccvid/iccvid_Da.rc new file mode 100644 index 00000000000..185b1bb92ab --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Da.rc @@ -0,0 +1,27 @@ +/* + * Danish resources for iccvid + * + * Copyright 2008 Jens Albretsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_DANISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak videokodeks" + IDS_DESCRIPTION "Cinepak videokodeks" +} diff --git a/reactos/dll/win32/iccvid/iccvid_De.rc b/reactos/dll/win32/iccvid/iccvid_De.rc new file mode 100644 index 00000000000..c101f3ad714 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_De.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2005 Henning Gerhardt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Video Codec" + IDS_DESCRIPTION "Cinepak Video Codec" +} diff --git a/reactos/dll/win32/iccvid/iccvid_En.rc b/reactos/dll/win32/iccvid/iccvid_En.rc new file mode 100644 index 00000000000..c71b0a449a0 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_En.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Video codec" + IDS_DESCRIPTION "Cinepak Video codec" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Fr.rc b/reactos/dll/win32/iccvid/iccvid_Fr.rc new file mode 100644 index 00000000000..4d276e68a15 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Fr.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2006 Jonathan Ernst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "codec vidéo Cinepak" + IDS_DESCRIPTION "codec vidéo Cinepak" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Hu.rc b/reactos/dll/win32/iccvid/iccvid_Hu.rc new file mode 100644 index 00000000000..b24cf8eaf25 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Hu.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2006 Andras Kovacs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Video kodek" + IDS_DESCRIPTION "Cinepak Video kodek" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Ko.rc b/reactos/dll/win32/iccvid/iccvid_Ko.rc new file mode 100644 index 00000000000..0cfbe3ea95d --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Ko.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2005 YunSomg Hwang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "½Ã³×ÆÑ ºñµð¿À ÄÚµ¦" + IDS_DESCRIPTION "½Ã³×ÆÑ ºñµð¿À ÄÚµ¦" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Nl.rc b/reactos/dll/win32/iccvid/iccvid_Nl.rc new file mode 100644 index 00000000000..0c58dd16d85 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Nl.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Frans Kool + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Video codec" + IDS_DESCRIPTION "Cinepak Video codec" +} diff --git a/reactos/dll/win32/iccvid/iccvid_No.rc b/reactos/dll/win32/iccvid/iccvid_No.rc new file mode 100644 index 00000000000..dd64108523b --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_No.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Alexander N. Sørnes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak-videokodek" + IDS_DESCRIPTION "Cinepak-videokodek" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Pl.rc b/reactos/dll/win32/iccvid/iccvid_Pl.rc new file mode 100644 index 00000000000..e276e8703a1 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Pl.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2006 Mikolaj Zalewski + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Kodek Cinepak Video" + IDS_DESCRIPTION "Kodek Cinepak Video" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Pt.rc b/reactos/dll/win32/iccvid/iccvid_Pt.rc new file mode 100644 index 00000000000..5e4ad5cabd3 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Pt.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Ricardo Filipe + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Codec Video Cinepak" + IDS_DESCRIPTION "Codec Video Cinepak" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Ro.rc b/reactos/dll/win32/iccvid/iccvid_Ro.rc new file mode 100644 index 00000000000..85cb1da2d38 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Ro.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2008 Michael Stefaniuc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Codecul Cinepak Video" + IDS_DESCRIPTION "Codecul Cinepak Video" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Ru.rc b/reactos/dll/win32/iccvid/iccvid_Ru.rc new file mode 100644 index 00000000000..c78ee72ff16 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Ru.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Âèäåî êîäåð-äåêîäåð Cinepak" + IDS_DESCRIPTION "Âèäåî êîäåð-äåêîäåð Cinepak" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Si.rc b/reactos/dll/win32/iccvid/iccvid_Si.rc new file mode 100644 index 00000000000..82bbd05fee4 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Si.rc @@ -0,0 +1,29 @@ +/* + * Copyright 2008 Rok Mandeljc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma code_page(65001) + +LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Video kodek" + IDS_DESCRIPTION "Cinepak Video kodek" +} + +#pragma code_page(default) diff --git a/reactos/dll/win32/iccvid/iccvid_Sv.rc b/reactos/dll/win32/iccvid/iccvid_Sv.rc new file mode 100644 index 00000000000..55eb468125b --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Sv.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2007 Daniel Nylander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak videokodek" + IDS_DESCRIPTION "Cinepak videokodek" +} diff --git a/reactos/dll/win32/iccvid/iccvid_Tr.rc b/reactos/dll/win32/iccvid/iccvid_Tr.rc new file mode 100644 index 00000000000..929f44fcbb2 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_Tr.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2006 Fatih Aþýcý + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "Cinepak Vidyo çözücü" + IDS_DESCRIPTION "Cinepak Vidyo çözücü" +} diff --git a/reactos/dll/win32/iccvid/iccvid_private.h b/reactos/dll/win32/iccvid/iccvid_private.h new file mode 100644 index 00000000000..8400e775207 --- /dev/null +++ b/reactos/dll/win32/iccvid/iccvid_private.h @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ICCVID_PRIVATE_H +#define __ICCVID_PRIVATE_H + +#define IDS_NAME 100 +#define IDS_DESCRIPTION 101 + +#endif /* __ICCVID_PRIVATE_H */ diff --git a/reactos/dll/win32/iccvid/rsrc.rc b/reactos/dll/win32/iccvid/rsrc.rc new file mode 100644 index 00000000000..e7512207c82 --- /dev/null +++ b/reactos/dll/win32/iccvid/rsrc.rc @@ -0,0 +1,36 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windef.h" +#include "iccvid_private.h" + +#include "iccvid_Da.rc" +#include "iccvid_De.rc" +#include "iccvid_En.rc" +#include "iccvid_Fr.rc" +#include "iccvid_Hu.rc" +#include "iccvid_Ko.rc" +#include "iccvid_Nl.rc" +#include "iccvid_No.rc" +#include "iccvid_Pl.rc" +#include "iccvid_Pt.rc" +#include "iccvid_Ro.rc" +#include "iccvid_Ru.rc" +#include "iccvid_Si.rc" +#include "iccvid_Sv.rc" +#include "iccvid_Tr.rc" diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild new file mode 100644 index 00000000000..8f24f00fda5 --- /dev/null +++ b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.rbuild @@ -0,0 +1,12 @@ + + + . + include/reactos/wine + + imaadp32.c + wine + winmm + user32 + kernel32 + ntdll + diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec new file mode 100644 index 00000000000..09473e9d6a6 --- /dev/null +++ b/reactos/dll/win32/imaadp32.acm/imaadp32.acm.spec @@ -0,0 +1 @@ +@ stdcall -private DriverProc (long long long long long) ADPCM_DriverProc diff --git a/reactos/dll/win32/imaadp32.acm/imaadp32.c b/reactos/dll/win32/imaadp32.acm/imaadp32.c new file mode 100644 index 00000000000..dd3cc5d108e --- /dev/null +++ b/reactos/dll/win32/imaadp32.acm/imaadp32.c @@ -0,0 +1,926 @@ +/* + * IMA ADPCM handling + * + * Copyright (C) 2001,2002 Eric Pouech + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "mmsystem.h" +#include "mmreg.h" +#include "msacm.h" +#include "msacmdrv.h" +#include "wine/debug.h" + +/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */ + +WINE_DEFAULT_DEBUG_CHANNEL(adpcm); + +/*********************************************************************** + * ADPCM_drvOpen + */ +static LRESULT ADPCM_drvOpen(LPCSTR str) +{ + return 1; +} + +/*********************************************************************** + * ADPCM_drvClose + */ +static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID) +{ + return 1; +} + +typedef struct tagAcmAdpcmData +{ + void (*convert)(PACMDRVSTREAMINSTANCE adsi, + const unsigned char*, LPDWORD, unsigned char*, LPDWORD); + /* IMA encoding only */ + BYTE stepIndexL; + BYTE stepIndexR; + /* short sample; */ +} AcmAdpcmData; + +/* table to list all supported formats... those are the basic ones. this + * also helps given a unique index to each of the supported formats + */ +typedef struct +{ + int nChannels; + int nBits; + int rate; +} Format; + +static const Format PCM_Formats[] = +{ + {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, + {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, + {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, + {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, +}; + +static const Format ADPCM_Formats[] = +{ + {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025}, + {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100}, +}; + +#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) +#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0])) + +/*********************************************************************** + * ADPCM_GetFormatIndex + */ +static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx) +{ + int i, hi; + const Format* fmts; + + switch (wfx->wFormatTag) + { + case WAVE_FORMAT_PCM: + hi = NUM_PCM_FORMATS; + fmts = PCM_Formats; + break; + case WAVE_FORMAT_IMA_ADPCM: + hi = NUM_ADPCM_FORMATS; + fmts = ADPCM_Formats; + break; + default: + return 0xFFFFFFFF; + } + + for (i = 0; i < hi; i++) + { + if (wfx->nChannels == fmts[i].nChannels && + wfx->nSamplesPerSec == fmts[i].rate && + wfx->wBitsPerSample == fmts[i].nBits) + return i; + } + + return 0xFFFFFFFF; +} + +/*********************************************************************** + * R16 + * + * Read a 16 bit sample (correctly handles endianess) + */ +static inline short R16(const unsigned char* src) +{ + return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); +} + +/*********************************************************************** + * W16 + * + * Write a 16 bit sample (correctly handles endianess) + */ +static inline void W16(unsigned char* dst, short s) +{ + dst[0] = LOBYTE(s); + dst[1] = HIBYTE(s); +} + +/* IMA (or DVI) APDCM codec routines */ + +static const unsigned IMA_StepTable[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 +}; + +static const int IMA_IndexTable[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +static inline void clamp_step_index(int* stepIndex) +{ + if (*stepIndex < 0 ) *stepIndex = 0; + if (*stepIndex > 88) *stepIndex = 88; +} + +static inline void clamp_sample(int* sample) +{ + if (*sample < -32768) *sample = -32768; + if (*sample > 32767) *sample = 32767; +} + +static inline void process_nibble(unsigned char code, int* stepIndex, int* sample) +{ + unsigned step; + int diff; + + code &= 0x0F; + + step = IMA_StepTable[*stepIndex]; + diff = step >> 3; + if (code & 1) diff += step >> 2; + if (code & 2) diff += step >> 1; + if (code & 4) diff += step; + if (code & 8) *sample -= diff; + else *sample += diff; + clamp_sample(sample); + *stepIndex += IMA_IndexTable[code]; + clamp_step_index(stepIndex); +} + +static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample) +{ + int effdiff, diff = in - *sample; + unsigned step; + unsigned char code; + + if (diff < 0) + { + diff = -diff; + code = 8; + } + else + { + code = 0; + } + + step = IMA_StepTable[*stepIndex]; + effdiff = (step >> 3); + if (diff >= step) + { + code |= 4; + diff -= step; + effdiff += step; + } + step >>= 1; + if (diff >= step) + { + code |= 2; + diff -= step; + effdiff += step; + } + step >>= 1; + if (diff >= step) + { + code |= 1; + effdiff += step; + } + if (code & 8) *sample -= effdiff; + else *sample += effdiff; + clamp_sample(sample); + *stepIndex += IMA_IndexTable[code]; + clamp_step_index(stepIndex); + return code; +} + +static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int i; + int sampleL, sampleR; + int stepIndexL, stepIndexR; + int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; + int nsamp; + /* compute the number of entire blocks we can decode... + * it's the min of the number of entire blocks in source buffer and the number + * of entire blocks in destination buffer + */ + DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, + *ndst / (nsamp_blk * 2 * 2)); + + *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; + *ndst = nblock * (nsamp_blk * 2 * 2); + + nsamp_blk--; /* remove the sample in block header */ + for (; nblock > 0; nblock--) + { + const unsigned char* in_src = src; + + /* handle headers first */ + sampleL = R16(src); + stepIndexL = (unsigned)*(src + 2); + clamp_step_index(&stepIndexL); + src += 4; + W16(dst, sampleL); dst += 2; + + sampleR = R16(src); + stepIndexR = (unsigned)*(src + 2); + clamp_step_index(&stepIndexR); + src += 4; + W16(dst, sampleR); dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8) + { + for (i = 0; i < 4; i++) + { + process_nibble(*src, &stepIndexL, &sampleL); + W16(dst + (2 * i + 0) * 4 + 0, sampleL); + process_nibble(*src++ >> 4, &stepIndexL, &sampleL); + W16(dst + (2 * i + 1) * 4 + 0, sampleL); + } + for (i = 0; i < 4; i++) + { + process_nibble(*src , &stepIndexR, &sampleR); + W16(dst + (2 * i + 0) * 4 + 2, sampleR); + process_nibble(*src++ >>4, &stepIndexR, &sampleR); + W16(dst + (2 * i + 1) * 4 + 2, sampleR); + } + dst += 32; + } + /* we have now to realign the source pointer on block */ + src = in_src + adsi->pwfxSrc->nBlockAlign; + } +} + +static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int sample; + int stepIndex; + int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; + int nsamp; + /* compute the number of entire blocks we can decode... + * it's the min of the number of entire blocks in source buffer and the number + * of entire blocks in destination buffer + */ + DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, + *ndst / (nsamp_blk * 2)); + + *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; + *ndst = nblock * nsamp_blk * 2; + + nsamp_blk--; /* remove the sample in block header */ + for (; nblock > 0; nblock--) + { + const unsigned char* in_src = src; + + /* handle header first */ + sample = R16(src); + stepIndex = (unsigned)*(src + 2); + clamp_step_index(&stepIndex); + src += 4; + W16(dst, sample); dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) + { + process_nibble(*src, &stepIndex, &sample); + W16(dst, sample); dst += 2; + process_nibble(*src++ >> 4, &stepIndex, &sample); + W16(dst, sample); dst += 2; + } + /* we have now to realign the source pointer on block */ + src = in_src + adsi->pwfxSrc->nBlockAlign; + } +} + +static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int stepIndexL, stepIndexR; + int sampleL, sampleR; + BYTE code1, code2; + int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; + int i, nsamp; + /* compute the number of entire blocks we can decode... + * it's the min of the number of entire blocks in source buffer and the number + * of entire blocks in destination buffer + */ + DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2), + *ndst / adsi->pwfxDst->nBlockAlign); + + *nsrc = nblock * (nsamp_blk * 2 * 2); + *ndst = nblock * adsi->pwfxDst->nBlockAlign; + + stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL; + stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR; + + nsamp_blk--; /* so that we won't count the sample in header while filling the block */ + + for (; nblock > 0; nblock--) + { + unsigned char* in_dst = dst; + + /* generate header */ + sampleL = R16(src); src += 2; + W16(dst, sampleL); dst += 2; + *dst = (unsigned char)(unsigned)stepIndexL; + dst += 2; + + sampleR = R16(src); src += 2; + W16(dst, sampleR); dst += 2; + *dst = (unsigned char)(unsigned)stepIndexR; + dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8) + { + for (i = 0; i < 4; i++) + { + code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0), + &stepIndexL, &sampleL); + code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0), + &stepIndexL, &sampleL); + *dst++ = (code1 << 4) | code2; + } + for (i = 0; i < 4; i++) + { + code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1), + &stepIndexR, &sampleR); + code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1), + &stepIndexR, &sampleR); + *dst++ = (code1 << 4) | code2; + } + src += 32; + } + dst = in_dst + adsi->pwfxDst->nBlockAlign; + } + ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL; + ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR; +} + +static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int stepIndex; + int sample; + BYTE code1, code2; + int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; + int nsamp; + /* compute the number of entire blocks we can decode... + * it's the min of the number of entire blocks in source buffer and the number + * of entire blocks in destination buffer + */ + DWORD nblock = min(*nsrc / (nsamp_blk * 2), + *ndst / adsi->pwfxDst->nBlockAlign); + + *nsrc = nblock * (nsamp_blk * 2); + *ndst = nblock * adsi->pwfxDst->nBlockAlign; + + stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL; + nsamp_blk--; /* so that we won't count the sample in header while filling the block */ + + for (; nblock > 0; nblock--) + { + unsigned char* in_dst = dst; + + /* generate header */ + /* FIXME: what about the last effective sample from previous block ??? */ + /* perhaps something like: + * sample += R16(src); + * clamp_sample(sample); + * and with : + * + saving the sample in adsi->dwDriver when all blocks are done + + + reset should set the field in adsi->dwDriver to 0 too + */ + sample = R16(src); src += 2; + W16(dst, sample); dst += 2; + *dst = (unsigned char)(unsigned)stepIndex; + dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) + { + code1 = generate_nibble(R16(src), &stepIndex, &sample); + src += 2; + code2 = generate_nibble(R16(src), &stepIndex, &sample); + src += 2; + *dst++ = (code1 << 4) | code2; + } + dst = in_dst + adsi->pwfxDst->nBlockAlign; + } + ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex; +} + +/*********************************************************************** + * ADPCM_DriverDetails + * + */ +static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add) +{ + add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; + add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; + add->wMid = 0x1; + add->wPid = 0x22; + add->vdwACM = 0x3320000; + add->vdwDriver = 0x04000000; + add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + add->cFormatTags = 2; /* PCM, IMA ADPCM */ + add->cFilterTags = 0; + add->hicon = NULL; + MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1, + add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1, + add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, + add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, + add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); + add->szFeatures[0] = 0; + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatTagDetails + * + */ +static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) +{ + static const WCHAR szPcm[]={'P','C','M',0}; + static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','D','P','C','M',0}; + + switch (dwQuery) + { + case ACM_FORMATTAGDETAILSF_INDEX: + if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATTAGDETAILSF_LARGESTSIZE: + if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) + { + aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */ + break; + } + /* fall thru */ + case ACM_FORMATTAGDETAILSF_FORMATTAG: + switch (aftd->dwFormatTag) + { + case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; + case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break; + default: return ACMERR_NOTPOSSIBLE; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + + aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + switch (aftd->dwFormatTagIndex) + { + case 0: + aftd->dwFormatTag = WAVE_FORMAT_PCM; + aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); + aftd->cStandardFormats = NUM_PCM_FORMATS; + lstrcpyW(aftd->szFormatTag, szPcm); + break; + case 1: + aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM; + aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT); + aftd->cStandardFormats = NUM_ADPCM_FORMATS; + lstrcpyW(aftd->szFormatTag, szImaAdPcm); + break; + } + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatDetails + * + */ +static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) +{ + switch (dwQuery) + { + case ACM_FORMATDETAILSF_FORMAT: + if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATDETAILSF_INDEX: + afd->pwfx->wFormatTag = afd->dwFormatTag; + switch (afd->dwFormatTag) + { + case WAVE_FORMAT_PCM: + if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; + /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible + * afd->pwfx->cbSize = 0; + */ + afd->pwfx->nBlockAlign = + (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; + afd->pwfx->nAvgBytesPerSec = + afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; + break; + case WAVE_FORMAT_IMA_ADPCM: + if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits; + afd->pwfx->nBlockAlign = 1024; + /* we got 4 bits per sample */ + afd->pwfx->nAvgBytesPerSec = + (afd->pwfx->nSamplesPerSec * 4) / 8; + if (afd->cbwfx >= sizeof(WAVEFORMATEX)) + afd->pwfx->cbSize = sizeof(WORD); + if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT)) + ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1; + break; + default: + WARN("Unsupported tag %08x\n", afd->dwFormatTag); + return MMSYSERR_INVALPARAM; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + afd->szFormat[0] = 0; /* let MSACM format this for us... */ + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatSuggest + * + */ +static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) +{ + /* some tests ... */ + if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || + adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || + ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + /* FIXME: should do those tests against the real size (according to format tag */ + + /* If no suggestion for destination, then copy source value */ + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) + adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) + adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; + + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) + { + if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) + adfs->pwfxDst->wBitsPerSample = 4; + else + adfs->pwfxDst->wBitsPerSample = 16; + } + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) + { + if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) + adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM; + else + adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; + } + + /* check if result is ok */ + if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + + /* recompute other values */ + switch (adfs->pwfxDst->wFormatTag) + { + case WAVE_FORMAT_PCM: + adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8; + adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; + break; + case WAVE_FORMAT_IMA_ADPCM: + adfs->pwfxDst->nBlockAlign = 1024; + /* FIXME: not handling header overhead */ + adfs->pwfxDst->nAvgBytesPerSec = ((adfs->pwfxDst->nSamplesPerSec * 4) / 8) * adfs->pwfxSrc->nChannels; + ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = (1024 - 4 * adfs->pwfxSrc->nChannels) * (2 / adfs->pwfxSrc->nChannels) + 1; + TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock); + break; + default: + FIXME("\n"); + break; + } + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_Reset + * + */ +static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad) +{ + aad->stepIndexL = aad->stepIndexR = 0; +} + +/*********************************************************************** + * ADPCM_StreamOpen + * + */ +static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) +{ + AcmAdpcmData* aad; + unsigned nspb; + + assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); + + if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || + ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) + return ACMERR_NOTPOSSIBLE; + + aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData)); + if (aad == 0) return MMSYSERR_NOMEM; + + adsi->dwDriver = (DWORD_PTR)aad; + + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + goto theEnd; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + /* resampling or mono <=> stereo not available + * ADPCM algo only define 16 bit per sample output + */ + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxDst->wBitsPerSample != 16) + goto theEnd; + + nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; + TRACE("spb=%u\n", nspb); + + /* we check that in a block, after the header, samples are present on + * 4-sample packet pattern + * we also check that the block alignment is bigger than the expected size + */ + if (((nspb - 1) & 3) != 0) goto theEnd; + if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign) + goto theEnd; + + /* adpcm decoding... */ + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2) + aad->convert = cvtSSima16K; + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1) + aad->convert = cvtMMima16K; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxSrc->wBitsPerSample != 16) + goto theEnd; + + nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; + TRACE("spb=%u\n", nspb); + + /* we check that in a block, after the header, samples are present on + * 4-sample packet pattern + * we also check that the block alignment is bigger than the expected size + */ + if (((nspb - 1) & 3) != 0) goto theEnd; + if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign) + goto theEnd; + + /* adpcm coding... */ + if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2) + aad->convert = cvtSS16imaK; + if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1) + aad->convert = cvtMM16imaK; + } + else goto theEnd; + ADPCM_Reset(adsi, aad); + + return MMSYSERR_NOERROR; + + theEnd: + HeapFree(GetProcessHeap(), 0, aad); + adsi->dwDriver = 0L; + return MMSYSERR_NOTSUPPORTED; +} + +/*********************************************************************** + * ADPCM_StreamClose + * + */ +static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) +{ + HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_StreamSize + * + */ +static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) +{ + switch (adss->fdwSize) + { + case ACM_STREAMSIZEF_DESTINATION: + /* cbDstLength => cbSrcLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) + { + /* don't take block overhead into account, doesn't matter too much */ + adss->cbSrcLength = adss->cbDstLength * 4; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + FIXME("misses the block header overhead\n"); + adss->cbSrcLength = 256 + adss->cbDstLength / 4; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + case ACM_STREAMSIZEF_SOURCE: + /* cbSrcLength => cbDstLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) + { + FIXME("misses the block header overhead\n"); + adss->cbDstLength = 256 + adss->cbSrcLength / 4; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + /* don't take block overhead into account, doesn't matter too much */ + adss->cbDstLength = adss->cbSrcLength * 4; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + default: + WARN("Unsupported query %08x\n", adss->fdwSize); + return MMSYSERR_NOTSUPPORTED; + } + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_StreamConvert + * + */ +static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) +{ + AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver; + DWORD nsrc = adsh->cbSrcLength; + DWORD ndst = adsh->cbDstLength; + + if (adsh->fdwConvert & + ~(ACM_STREAMCONVERTF_BLOCKALIGN| + ACM_STREAMCONVERTF_END| + ACM_STREAMCONVERTF_START)) + { + FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); + } + /* ACM_STREAMCONVERTF_BLOCKALIGN + * currently all conversions are block aligned, so do nothing for this flag + * ACM_STREAMCONVERTF_END + * no pending data, so do nothing for this flag + */ + if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) + { + ADPCM_Reset(adsi, aad); + } + + aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); + adsh->cbSrcLengthUsed = nsrc; + adsh->cbDstLengthUsed = ndst; + + return MMSYSERR_NOERROR; +} + +/************************************************************************** + * ADPCM_DriverProc [exported] + */ +LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, + LPARAM dwParam1, LPARAM dwParam2) +{ + TRACE("(%08lx %p %04x %08lx %08lx);\n", + dwDevID, hDriv, wMsg, dwParam1, dwParam2); + + switch (wMsg) + { + case DRV_LOAD: return 1; + case DRV_FREE: return 1; + case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1); + case DRV_CLOSE: return ADPCM_drvClose(dwDevID); + case DRV_ENABLE: return 1; + case DRV_DISABLE: return 1; + case DRV_QUERYCONFIGURE: return 1; + case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1; + case DRV_INSTALL: return DRVCNF_RESTART; + case DRV_REMOVE: return DRVCNF_RESTART; + + case ACMDM_DRIVER_NOTIFY: + /* no caching from other ACM drivers is done so far */ + return MMSYSERR_NOERROR; + + case ACMDM_DRIVER_DETAILS: + return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); + + case ACMDM_FORMATTAG_DETAILS: + return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_DETAILS: + return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_SUGGEST: + return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); + + case ACMDM_STREAM_OPEN: + return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_CLOSE: + return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_SIZE: + return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); + + case ACMDM_STREAM_CONVERT: + return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); + + case ACMDM_HARDWARE_WAVE_CAPS_INPUT: + case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: + /* this converter is not a hardware driver */ + case ACMDM_FILTERTAG_DETAILS: + case ACMDM_FILTER_DETAILS: + /* this converter is not a filter */ + case ACMDM_STREAM_RESET: + /* only needed for asynchronous driver... we aren't, so just say it */ + return MMSYSERR_NOTSUPPORTED; + case ACMDM_STREAM_PREPARE: + case ACMDM_STREAM_UNPREPARE: + /* nothing special to do here... so don't do anything */ + return MMSYSERR_NOERROR; + + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} diff --git a/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild b/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild new file mode 100644 index 00000000000..1be0196a9ee --- /dev/null +++ b/reactos/dll/win32/msadp32.acm/msadp32.acm.rbuild @@ -0,0 +1,12 @@ + + + . + include/reactos/wine + + msadp32.c + wine + winmm + user32 + kernel32 + ntdll + diff --git a/reactos/dll/win32/msadp32.acm/msadp32.acm.spec b/reactos/dll/win32/msadp32.acm/msadp32.acm.spec new file mode 100644 index 00000000000..09473e9d6a6 --- /dev/null +++ b/reactos/dll/win32/msadp32.acm/msadp32.acm.spec @@ -0,0 +1 @@ +@ stdcall -private DriverProc (long long long long long) ADPCM_DriverProc diff --git a/reactos/dll/win32/msadp32.acm/msadp32.c b/reactos/dll/win32/msadp32.acm/msadp32.c new file mode 100644 index 00000000000..1c0c840ae83 --- /dev/null +++ b/reactos/dll/win32/msadp32.acm/msadp32.c @@ -0,0 +1,811 @@ +/* + * MS ADPCM handling + * + * Copyright (C) 2002 Eric Pouech + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "mmsystem.h" +#include "mmreg.h" +#include "msacm.h" +#include "msacmdrv.h" +#include "wine/debug.h" + +/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */ + +WINE_DEFAULT_DEBUG_CHANNEL(adpcm); + +/*********************************************************************** + * ADPCM_drvOpen + */ +static LRESULT ADPCM_drvOpen(LPCSTR str) +{ + return 1; +} + +/*********************************************************************** + * ADPCM_drvClose + */ +static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID) +{ + return 1; +} + +typedef struct tagAcmAdpcmData +{ + void (*convert)(const ACMDRVSTREAMINSTANCE *adsi, + const unsigned char*, LPDWORD, unsigned char*, LPDWORD); +} AcmAdpcmData; + +/* table to list all supported formats... those are the basic ones. this + * also helps given a unique index to each of the supported formats + */ +typedef struct +{ + int nChannels; + int nBits; + int rate; +} Format; + +static const Format PCM_Formats[] = +{ + {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, + {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, + {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, + {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, +}; + +static const Format ADPCM_Formats[] = +{ + {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025}, + {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100}, +}; + +#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) +#define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0])) + +static int MS_Delta[] = +{ + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +}; + + +static ADPCMCOEFSET MSADPCM_CoeffSet[] = +{ + {256, 0}, {512, -256}, {0, 0}, {192, 64}, {240, 0}, {460, -208}, {392, -232} +}; + +/*********************************************************************** + * ADPCM_GetFormatIndex + */ +static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX* wfx) +{ + int i, hi; + const Format* fmts; + + switch (wfx->wFormatTag) + { + case WAVE_FORMAT_PCM: + hi = NUM_PCM_FORMATS; + fmts = PCM_Formats; + break; + case WAVE_FORMAT_ADPCM: + hi = NUM_ADPCM_FORMATS; + fmts = ADPCM_Formats; + break; + default: + return 0xFFFFFFFF; + } + + for (i = 0; i < hi; i++) + { + if (wfx->nChannels == fmts[i].nChannels && + wfx->nSamplesPerSec == fmts[i].rate && + wfx->wBitsPerSample == fmts[i].nBits) + return i; + } + + switch (wfx->wFormatTag) + { + case WAVE_FORMAT_PCM: + if(3 > wfx->nChannels && + wfx->nChannels > 0 && + wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels && + wfx->nBlockAlign == 2 * wfx->nChannels && + wfx->wBitsPerSample == 16) + return hi; + break; + case WAVE_FORMAT_ADPCM: + if(3 > wfx->nChannels && + wfx->nChannels > 0 && + wfx->wBitsPerSample == 4 && + wfx->cbSize == 32) + return hi; + break; + } + + return 0xFFFFFFFF; +} + +static void init_wfx_adpcm(ADPCMWAVEFORMAT* awfx) +{ + register WAVEFORMATEX* pwfx = &awfx->wfx; + + /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample + * have been initialized... */ + + if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM) {FIXME("wrong FT\n"); return;} + if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;} + + switch (pwfx->nSamplesPerSec) + { + case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; + case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; + case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break; + case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break; + default: break; + } + pwfx->cbSize = 2 * sizeof(WORD) + 7 * sizeof(ADPCMCOEFSET); + /* 7 is the size of the block head (which contains two samples) */ + + awfx->wSamplesPerBlock = pwfx->nBlockAlign * 2 / pwfx->nChannels - 12; + pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock; + awfx->wNumCoef = 7; + memcpy(awfx->aCoef, MSADPCM_CoeffSet, 7 * sizeof(ADPCMCOEFSET)); +} + +/*********************************************************************** + * R16 + * + * Read a 16 bit sample (correctly handles endianess) + */ +static inline short R16(const unsigned char* src) +{ + return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); +} + +/*********************************************************************** + * W16 + * + * Write a 16 bit sample (correctly handles endianess) + */ +static inline void W16(unsigned char* dst, short s) +{ + dst[0] = LOBYTE(s); + dst[1] = HIBYTE(s); +} + +static inline void clamp_sample(int* sample) +{ + if (*sample < -32768) *sample = -32768; + if (*sample > 32767) *sample = 32767; +} + +static inline void process_nibble(unsigned nibble, int* idelta, + int* sample1, int* sample2, + const ADPCMCOEFSET* coeff) +{ + int sample; + int snibble; + + /* nibble is in fact a signed 4 bit integer => propagate sign if needed */ + snibble = (nibble & 0x08) ? (nibble - 16) : nibble; + sample = ((*sample1 * coeff->iCoef1) + (*sample2 * coeff->iCoef2)) / 256 + + snibble * *idelta; + clamp_sample(&sample); + + *sample2 = *sample1; + *sample1 = sample; + *idelta = ((MS_Delta[nibble] * *idelta) / 256); + if (*idelta < 16) *idelta = 16; +} + +static void cvtSSms16K(const ACMDRVSTREAMINSTANCE *adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int ideltaL, ideltaR; + int sample1L, sample2L; + int sample1R, sample2R; + ADPCMCOEFSET coeffL, coeffR; + int nsamp; + int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; + DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, + *ndst / (nsamp_blk * 2 * 2)); + + *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; + *ndst = nblock * nsamp_blk * 2 * 2; + + nsamp_blk -= 2; /* see below for samples from block head */ + for (; nblock > 0; nblock--) + { + const unsigned char* in_src = src; + + assert(*src <= 6); + coeffL = MSADPCM_CoeffSet[*src++]; + assert(*src <= 6); + coeffR = MSADPCM_CoeffSet[*src++]; + + ideltaL = R16(src); src += 2; + ideltaR = R16(src); src += 2; + sample1L = R16(src); src += 2; + sample1R = R16(src); src += 2; + sample2L = R16(src); src += 2; + sample2R = R16(src); src += 2; + + /* store samples from block head */ + W16(dst, sample2L); dst += 2; + W16(dst, sample2R); dst += 2; + W16(dst, sample1L); dst += 2; + W16(dst, sample1R); dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp--) + { + process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL); + W16(dst, sample1L); dst += 2; + process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR); + W16(dst, sample1R); dst += 2; + } + src = in_src + adsi->pwfxSrc->nBlockAlign; + } +} + +static void cvtMMms16K(const ACMDRVSTREAMINSTANCE *adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int idelta; + int sample1, sample2; + ADPCMCOEFSET coeff; + int nsamp; + int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; + DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, + *ndst / (nsamp_blk * 2)); + + *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; + *ndst = nblock * nsamp_blk * 2; + + nsamp_blk -= 2; /* see below for samples from block head */ + for (; nblock > 0; nblock--) + { + const unsigned char* in_src = src; + + assert(*src <= 6); + coeff = MSADPCM_CoeffSet[*src++]; + + idelta = R16(src); src += 2; + sample1 = R16(src); src += 2; + sample2 = R16(src); src += 2; + + /* store samples from block head */ + W16(dst, sample2); dst += 2; + W16(dst, sample1); dst += 2; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) + { + process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff); + W16(dst, sample1); dst += 2; + process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff); + W16(dst, sample1); dst += 2; + } + src = in_src + adsi->pwfxSrc->nBlockAlign; + } +} + +#if 0 +static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ +} + +static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ +} +#endif + +/*********************************************************************** + * ADPCM_DriverDetails + * + */ +static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add) +{ + add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; + add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; + add->wMid = 0xFF; + add->wPid = 0x00; + add->vdwACM = 0x01000000; + add->vdwDriver = 0x01000000; + add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + add->cFormatTags = 2; /* PCM, MS ADPCM */ + add->cFilterTags = 0; + add->hicon = NULL; + MultiByteToWideChar( CP_ACP, 0, "MS-ADPCM", -1, + add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1, + add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, + add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, + add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); + add->szFeatures[0] = 0; + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatTagDetails + * + */ +static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) +{ + static const WCHAR szPcm[]={'P','C','M',0}; + static const WCHAR szMsAdPcm[]={'M','i','c','r','o','s','o','f','t',' ','A','D','P','C','M',0}; + + switch (dwQuery) + { + case ACM_FORMATTAGDETAILSF_INDEX: + if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATTAGDETAILSF_LARGESTSIZE: + if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) + { + aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */ + break; + } + /* fall thru */ + case ACM_FORMATTAGDETAILSF_FORMATTAG: + switch (aftd->dwFormatTag) + { + case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; + case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break; + default: return ACMERR_NOTPOSSIBLE; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + + aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + switch (aftd->dwFormatTagIndex) + { + case 0: + aftd->dwFormatTag = WAVE_FORMAT_PCM; + aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); + aftd->cStandardFormats = NUM_PCM_FORMATS; + lstrcpyW(aftd->szFormatTag, szPcm); + break; + case 1: + aftd->dwFormatTag = WAVE_FORMAT_ADPCM; + aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET); + aftd->cStandardFormats = NUM_ADPCM_FORMATS; + lstrcpyW(aftd->szFormatTag, szMsAdPcm); + break; + } + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatDetails + * + */ +static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) +{ + switch (dwQuery) + { + case ACM_FORMATDETAILSF_FORMAT: + if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATDETAILSF_INDEX: + afd->pwfx->wFormatTag = afd->dwFormatTag; + switch (afd->dwFormatTag) + { + case WAVE_FORMAT_PCM: + if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; + /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible + * afd->pwfx->cbSize = 0; + */ + afd->pwfx->nBlockAlign = + (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; + afd->pwfx->nAvgBytesPerSec = + afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; + break; + case WAVE_FORMAT_ADPCM: + if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE; + if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET)) + return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits; + init_wfx_adpcm((ADPCMWAVEFORMAT*)afd->pwfx); + break; + default: + WARN("Unsupported tag %08x\n", afd->dwFormatTag); + return MMSYSERR_INVALPARAM; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + afd->szFormat[0] = 0; /* let MSACM format this for us... */ + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_FormatSuggest + * + */ +static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) +{ + /* some tests ... */ + if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || + adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || + adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag || + ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + /* FIXME: should do those tests against the real size (according to format tag */ + + /* If no suggestion for destination, then copy source value */ + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) + adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) + adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; + + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) + { + if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) + adfs->pwfxDst->wBitsPerSample = 4; + else + adfs->pwfxDst->wBitsPerSample = 16; + } + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) + { + if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) + adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ADPCM; + else + adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; + } + + /* recompute other values */ + switch (adfs->pwfxDst->wFormatTag) + { + case WAVE_FORMAT_PCM: + adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8; + adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; + /* check if result is ok */ + if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + break; + case WAVE_FORMAT_ADPCM: + init_wfx_adpcm((ADPCMWAVEFORMAT*)adfs->pwfxDst); + /* check if result is ok */ + if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + break; + default: + FIXME("\n"); + break; + } + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_Reset + * + */ +static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad) +{ +} + +/*********************************************************************** + * ADPCM_StreamOpen + * + */ +static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) +{ + AcmAdpcmData* aad; + + assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); + + if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || + ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) + return ACMERR_NOTPOSSIBLE; + + aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData)); + if (aad == 0) return MMSYSERR_NOMEM; + + adsi->dwDriver = (DWORD_PTR)aad; + + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + goto theEnd; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + /* resampling or mono <=> stereo not available + * ADPCM algo only define 16 bit per sample output + */ + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxDst->wBitsPerSample != 16) + goto theEnd; + +#if 0 + { + unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; + FIXME("spb=%u\n", nspb); + + /* we check that in a block, after the header, samples are present on + * 4-sample packet pattern + * we also check that the block alignment is bigger than the expected size + */ + if (((nspb - 1) & 3) != 0) goto theEnd; + if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign) + goto theEnd; + } +#endif + + /* adpcm decoding... */ + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2) + aad->convert = cvtSSms16K; + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1) + aad->convert = cvtMMms16K; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxSrc->wBitsPerSample != 16) + goto theEnd; +#if 0 + nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock; + FIXME("spb=%u\n", nspb); + + /* we check that in a block, after the header, samples are present on + * 4-sample packet pattern + * we also check that the block alignment is bigger than the expected size + */ + if (((nspb - 1) & 3) != 0) goto theEnd; + if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign) + goto theEnd; +#endif +#if 0 + /* adpcm coding... */ + if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2) + aad->convert = cvtSS16msK; + if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1) + aad->convert = cvtMM16msK; +#endif + FIXME("We don't support encoding yet\n"); + goto theEnd; + } + else goto theEnd; + ADPCM_Reset(adsi, aad); + + return MMSYSERR_NOERROR; + + theEnd: + HeapFree(GetProcessHeap(), 0, aad); + adsi->dwDriver = 0L; + return MMSYSERR_NOTSUPPORTED; +} + +/*********************************************************************** + * ADPCM_StreamClose + * + */ +static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) +{ + HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_StreamSize + * + */ +static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) +{ + DWORD nblocks; + WORD wSamplesPerBlock; + /* wSamplesPerBlock formula comes from MSDN ADPCMWAVEFORMAT page.*/ + switch (adss->fdwSize) + { + case ACM_STREAMSIZEF_DESTINATION: + /* cbDstLength => cbSrcLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) + { + wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12; + nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign; + if (nblocks == 0) + return ACMERR_NOTPOSSIBLE; + adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12; + nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * wSamplesPerBlock); + if (nblocks == 0) + return ACMERR_NOTPOSSIBLE; + adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + case ACM_STREAMSIZEF_SOURCE: + /* cbSrcLength => cbDstLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) + { + wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12; + nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock); + if (nblocks == 0) + return ACMERR_NOTPOSSIBLE; + if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock)) + /* Round block count up. */ + nblocks++; + adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12; + nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign; + if (nblocks == 0) + return ACMERR_NOTPOSSIBLE; + if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign) + /* Round block count up. */ + nblocks++; + adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * wSamplesPerBlock; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + default: + WARN("Unsupported query %08x\n", adss->fdwSize); + return MMSYSERR_NOTSUPPORTED; + } + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * ADPCM_StreamConvert + * + */ +static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) +{ + AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver; + DWORD nsrc = adsh->cbSrcLength; + DWORD ndst = adsh->cbDstLength; + + if (adsh->fdwConvert & + ~(ACM_STREAMCONVERTF_BLOCKALIGN| + ACM_STREAMCONVERTF_END| + ACM_STREAMCONVERTF_START)) + { + FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); + } + /* ACM_STREAMCONVERTF_BLOCKALIGN + * currently all conversions are block aligned, so do nothing for this flag + * ACM_STREAMCONVERTF_END + * no pending data, so do nothing for this flag + */ + if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) + { + ADPCM_Reset(adsi, aad); + } + + aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); + adsh->cbSrcLengthUsed = nsrc; + adsh->cbDstLengthUsed = ndst; + + return MMSYSERR_NOERROR; +} + +/************************************************************************** + * ADPCM_DriverProc [exported] + */ +LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, + LPARAM dwParam1, LPARAM dwParam2) +{ + TRACE("(%08lx %p %04x %08lx %08lx);\n", + dwDevID, hDriv, wMsg, dwParam1, dwParam2); + + switch (wMsg) + { + case DRV_LOAD: return 1; + case DRV_FREE: return 1; + case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1); + case DRV_CLOSE: return ADPCM_drvClose(dwDevID); + case DRV_ENABLE: return 1; + case DRV_DISABLE: return 1; + case DRV_QUERYCONFIGURE: return 1; + case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1; + case DRV_INSTALL: return DRVCNF_RESTART; + case DRV_REMOVE: return DRVCNF_RESTART; + + case ACMDM_DRIVER_NOTIFY: + /* no caching from other ACM drivers is done so far */ + return MMSYSERR_NOERROR; + + case ACMDM_DRIVER_DETAILS: + return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); + + case ACMDM_FORMATTAG_DETAILS: + return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_DETAILS: + return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_SUGGEST: + return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); + + case ACMDM_STREAM_OPEN: + return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_CLOSE: + return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_SIZE: + return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); + + case ACMDM_STREAM_CONVERT: + return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); + + case ACMDM_HARDWARE_WAVE_CAPS_INPUT: + case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: + /* this converter is not a hardware driver */ + case ACMDM_FILTERTAG_DETAILS: + case ACMDM_FILTER_DETAILS: + /* this converter is not a filter */ + case ACMDM_STREAM_RESET: + /* only needed for asynchronous driver... we aren't, so just say it */ + return MMSYSERR_NOTSUPPORTED; + case ACMDM_STREAM_PREPARE: + case ACMDM_STREAM_UNPREPARE: + /* nothing special to do here... so don't do anything */ + return MMSYSERR_NOERROR; + + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} diff --git a/reactos/dll/win32/msg711.acm/msg711.acm.rbuild b/reactos/dll/win32/msg711.acm/msg711.acm.rbuild new file mode 100644 index 00000000000..a9297bd3812 --- /dev/null +++ b/reactos/dll/win32/msg711.acm/msg711.acm.rbuild @@ -0,0 +1,12 @@ + + + . + include/reactos/wine + + msg711.c + wine + winmm + user32 + kernel32 + ntdll + diff --git a/reactos/dll/win32/msg711.acm/msg711.acm.spec b/reactos/dll/win32/msg711.acm/msg711.acm.spec new file mode 100644 index 00000000000..e351c5879a5 --- /dev/null +++ b/reactos/dll/win32/msg711.acm/msg711.acm.spec @@ -0,0 +1 @@ +@ stdcall -private DriverProc(long long long long long) G711_DriverProc diff --git a/reactos/dll/win32/msg711.acm/msg711.c b/reactos/dll/win32/msg711.acm/msg711.c new file mode 100644 index 00000000000..203942ddcb1 --- /dev/null +++ b/reactos/dll/win32/msg711.acm/msg711.c @@ -0,0 +1,1151 @@ +/* + * G711 handling (includes A-Law & MU-Law) + * + * Copyright (C) 2002 Eric Pouech + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "mmsystem.h" +#include "mmreg.h" +#include "msacm.h" +#include "msacmdrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(g711); + +/*********************************************************************** + * G711_drvOpen + */ +static LRESULT G711_drvOpen(LPCSTR str) +{ + return 1; +} + +/*********************************************************************** + * G711_drvClose + */ +static LRESULT G711_drvClose(DWORD_PTR dwDevID) +{ + return 1; +} + +typedef struct tagAcmG711Data +{ + void (*convert)(PACMDRVSTREAMINSTANCE adsi, + const unsigned char*, LPDWORD, unsigned char*, LPDWORD); +} AcmG711Data; + +/* table to list all supported formats... those are the basic ones. this + * also helps given a unique index to each of the supported formats + */ +typedef struct +{ + int nChannels; + int nBits; + int rate; +} Format; + +static const Format PCM_Formats[] = +{ + /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000}, + /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025}, + /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050}, + /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100}, +}; + +static const Format ALaw_Formats[] = +{ + {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, + {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100}, +}; + +static const Format ULaw_Formats[] = +{ + {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, + {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100}, +}; + +#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) +#define NUM_ALAW_FORMATS (sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0])) +#define NUM_ULAW_FORMATS (sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0])) + +/*********************************************************************** + * G711_GetFormatIndex + */ +static DWORD G711_GetFormatIndex(const WAVEFORMATEX *wfx) +{ + int i, hi; + const Format* fmts; + + switch (wfx->wFormatTag) + { + case WAVE_FORMAT_PCM: + hi = NUM_PCM_FORMATS; + fmts = PCM_Formats; + break; + case WAVE_FORMAT_ALAW: + hi = NUM_ALAW_FORMATS; + fmts = ALaw_Formats; + break; + case WAVE_FORMAT_MULAW: + hi = NUM_ULAW_FORMATS; + fmts = ULaw_Formats; + break; + default: + return 0xFFFFFFFF; + } + + for (i = 0; i < hi; i++) + { + if (wfx->nChannels == fmts[i].nChannels && + wfx->nSamplesPerSec == fmts[i].rate && + wfx->wBitsPerSample == fmts[i].nBits) + return i; + } + + return 0xFFFFFFFF; +} + +/*********************************************************************** + * R16 + * + * Read a 16 bit sample (correctly handles endianess) + */ +static inline short R16(const unsigned char* src) +{ + return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); +} + +/*********************************************************************** + * W16 + * + * Write a 16 bit sample (correctly handles endianess) + */ +static inline void W16(unsigned char* dst, short s) +{ + dst[0] = LOBYTE(s); + dst[1] = HIBYTE(s); +} + +/* You can uncomment this if you don't want the statically generated conversion + * table, but rather recompute the Xlaw => PCM conversion for each sample +#define NO_FASTDECODE + * Since the conversion tables are rather small (2k), I don't think it's really + * interesting not to use them, but keeping the actual conversion code around + * is helpful to regenerate the tables when needed. + */ + +/* -------------------------------------------------------------------------------*/ + +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ + +/* + * December 30, 1994: + * Functions linear2alaw, linear2ulaw have been updated to correctly + * convert unquantized 16 bit values. + * Tables for direct u- to A-law and A- to u-law conversions have been + * corrected. + * Borge Lindberg, Center for PersonKommunikation, Aalborg University. + * bli@cpk.auc.dk + * + */ + +#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +static const short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF}; +static const short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; + +/* copy from CCITT G.711 specifications */ +static const unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, +/* corrected: + 81, 82, 83, 84, 85, 86, 87, 88, + should be: */ + 80, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +static const unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, +/* corrected: + 73, 74, 75, 76, 77, 78, 79, 79, + should be: */ + 73, 74, 75, 76, 77, 78, 79, 80, + + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +static short +search( + int val, /* changed from "short" *drago* */ + const short *table, + int size) /* changed from "short" *drago* */ +{ + int i; /* changed from "short" *drago* */ + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} + +/* + * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law + * + * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +static inline unsigned char +linear2alaw(int pcm_val) /* 2's complement (16-bit range) */ + /* changed from "short" *drago* */ +{ + int mask; /* changed from "short" *drago* */ + int seg; /* changed from "short" *drago* */ + unsigned char aval; + + pcm_val = pcm_val >> 3; + + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 1; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_aend, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + aval = (unsigned char) seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 1) & QUANT_MASK; + else + aval |= (pcm_val >> seg) & QUANT_MASK; + return (aval ^ mask); + } +} + +#ifdef NO_FASTDECODE +/* + * alaw2linear() - Convert an A-law value to 16-bit linear PCM + * + */ +static inline int +alaw2linear(unsigned char a_val) +{ + int t; /* changed from "short" *drago* */ + int seg; /* changed from "short" *drago* */ + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} +#else +/* EPP (for Wine): + * this array has been statically generated from the above routine + */ +static const unsigned short _a2l[] = { +0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, +0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, +0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, +0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, +0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, +0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, +0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, +0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00, +0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, +0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58, +0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, +0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58, +0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, +0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960, +0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, +0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0, +0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, +0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80, +0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, +0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40, +0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, +0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00, +0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, +0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500, +0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, +0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8, +0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, +0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8, +0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, +0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0, +0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, +0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350, +}; +static inline int +alaw2linear(unsigned char a_val) +{ + return (short)_a2l[a_val]; +} +#endif + +#define BIAS (0x84) /* Bias for linear code. */ +#define CLIP 8159 + +/* + * linear2ulaw() - Convert a linear PCM value to u-law + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +static inline unsigned char +linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */ +{ + short mask; + short seg; + unsigned char uval; + + /* Get the sign and the magnitude of the value. */ + pcm_val = pcm_val >> 2; + if (pcm_val < 0) { + pcm_val = -pcm_val; + mask = 0x7F; + } else { + mask = 0xFF; + } + if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ + pcm_val += (BIAS >> 2); + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_uend, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); + return (uval ^ mask); + } +} + +#ifdef NO_FASTDECODE +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +static inline short +ulaw2linear(unsigned char u_val) +{ + short t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} +#else +/* EPP (for Wine): + * this array has been statically generated from the above routine + */ +static const unsigned short _u2l[] = { +0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, +0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, +0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, +0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, +0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, +0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, +0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, +0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844, +0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, +0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64, +0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, +0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74, +0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, +0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C, +0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, +0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000, +0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, +0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C, +0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, +0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C, +0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, +0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC, +0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, +0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC, +0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, +0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C, +0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, +0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C, +0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, +0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084, +0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, +0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000, +}; +static inline short ulaw2linear(unsigned char u_val) +{ + return (short)_u2l[u_val]; +} +#endif + +/* A-law to u-law conversion */ +static inline unsigned char +alaw2ulaw(unsigned char aval) +{ + aval &= 0xff; + return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +static inline unsigned char +ulaw2alaw(unsigned char uval) +{ + uval &= 0xff; + return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} + +/* -------------------------------------------------------------------------------*/ + +static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize, *dstsize / 2); + DWORD i; + short w; + + *srcsize = len; + *dstsize = len * 2; + for (i = 0; i < len; i++) + { + w = alaw2linear(*src++); + W16(dst, w); dst += 2; + } +} + +static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize / 2, *dstsize); + DWORD i; + + *srcsize = len * 2; + *dstsize = len; + for (i = 0; i < len; i++) + { + *dst++ = linear2alaw(R16(src)); src += 2; + } +} + +static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize, *dstsize / 2); + DWORD i; + short w; + + *srcsize = len; + *dstsize = len * 2; + for (i = 0; i < len; i++) + { + w = ulaw2linear(*src++); + W16(dst, w); dst += 2; + } +} + +static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize / 2, *dstsize); + DWORD i; + + *srcsize = len * 2; + *dstsize = len; + for (i = 0; i < len; i++) + { + *dst++ = linear2ulaw(R16(src)); src += 2; + } +} + +static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize, *dstsize); + DWORD i; + + *srcsize = len; + *dstsize = len; + + for (i = 0; i < len; i++) + *dst++ = alaw2ulaw(*src++); +} + + +static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD srcsize, + unsigned char* dst, LPDWORD dstsize) +{ + DWORD len = min(*srcsize, *dstsize); + DWORD i; + + *srcsize = len; + *dstsize = len; + + for (i = 0; i < len; i++) + *dst++ = ulaw2alaw(*src++); +} + +/*********************************************************************** + * G711_DriverDetails + * + */ +static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add) +{ + add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; + add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; + add->wMid = 0xFF; + add->wPid = 0x00; + add->vdwACM = 0x01000000; + add->vdwDriver = 0x01000000; + add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */ + add->cFilterTags = 0; + add->hicon = NULL; + MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1, + add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1, + add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, + add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, + add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); + add->szFeatures[0] = 0; + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_FormatTagDetails + * + */ +static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) +{ + static const WCHAR szPcm[]={'P','C','M',0}; + static const WCHAR szALaw[]={'A','-','L','a','w',0}; + static const WCHAR szULaw[]={'U','-','L','a','w',0}; + + switch (dwQuery) + { + case ACM_FORMATTAGDETAILSF_INDEX: + if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATTAGDETAILSF_LARGESTSIZE: + if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) + { + aftd->dwFormatTagIndex = 1; + break; + } + /* fall thru */ + case ACM_FORMATTAGDETAILSF_FORMATTAG: + switch (aftd->dwFormatTag) + { + case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; + case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break; + case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break; + default: return ACMERR_NOTPOSSIBLE; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + + aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + switch (aftd->dwFormatTagIndex) + { + case 0: + aftd->dwFormatTag = WAVE_FORMAT_PCM; + aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); + aftd->cStandardFormats = NUM_PCM_FORMATS; + lstrcpyW(aftd->szFormatTag, szPcm); + break; + case 1: + aftd->dwFormatTag = WAVE_FORMAT_ALAW; + aftd->cbFormatSize = sizeof(WAVEFORMATEX); + aftd->cStandardFormats = NUM_ALAW_FORMATS; + lstrcpyW(aftd->szFormatTag, szALaw); + break; + case 2: + aftd->dwFormatTag = WAVE_FORMAT_MULAW; + aftd->cbFormatSize = sizeof(WAVEFORMATEX); + aftd->cStandardFormats = NUM_ULAW_FORMATS; + lstrcpyW(aftd->szFormatTag, szULaw); + break; + } + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_FormatDetails + * + */ +static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) +{ + switch (dwQuery) + { + case ACM_FORMATDETAILSF_FORMAT: + if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + break; + case ACM_FORMATDETAILSF_INDEX: + afd->pwfx->wFormatTag = afd->dwFormatTag; + switch (afd->dwFormatTag) + { + case WAVE_FORMAT_PCM: + if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; + afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2; + afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; + break; + case WAVE_FORMAT_ALAW: + if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits; + afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels; + afd->pwfx->cbSize = 0; + break; + case WAVE_FORMAT_MULAW: + if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE; + afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate; + afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits; + afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels; + afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels; + afd->pwfx->cbSize = 0; + break; + default: + WARN("Unsupported tag %08x\n", afd->dwFormatTag); + return MMSYSERR_INVALPARAM; + } + break; + default: + WARN("Unsupported query %08x\n", dwQuery); + return MMSYSERR_NOTSUPPORTED; + } + afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; + afd->szFormat[0] = 0; /* let MSACM format this for us... */ + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_FormatSuggest + * + */ +static LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs) +{ + /* some tests ... */ + if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || + adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || + G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + /* FIXME: should do those tests against the real size (according to format tag */ + + /* If no suggestion for destination, then copy source value */ + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) + adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) + adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; + + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) + { + if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) + adfs->pwfxDst->wBitsPerSample = 8; + else + adfs->pwfxDst->wBitsPerSample = 16; + } + if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) + { + switch (adfs->pwfxSrc->wFormatTag) + { + case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break; + case WAVE_FORMAT_ALAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break; + case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break; + } + } + /* check if result is ok */ + if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; + + /* recompute other values */ + switch (adfs->pwfxDst->wFormatTag) + { + case WAVE_FORMAT_PCM: + adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels; + adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; + break; + case WAVE_FORMAT_ALAW: + adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2; + adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2; + break; + case WAVE_FORMAT_MULAW: + adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2; + adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2; + break; + default: + FIXME("\n"); + break; + } + + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_Reset + * + */ +static void G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad) +{ +} + +/*********************************************************************** + * G711_StreamOpen + * + */ +static LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi) +{ + AcmG711Data* aad; + + assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); + + if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || + G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) + return ACMERR_NOTPOSSIBLE; + + aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data)); + if (aad == 0) return MMSYSERR_NOMEM; + + adsi->dwDriver = (DWORD_PTR)aad; + + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + goto theEnd; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + /* resampling or mono <=> stereo not available + * G711 algo only define 16 bit per sample output + */ + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxDst->wBitsPerSample != 16) + goto theEnd; + + /* g711 A-Law decoding... */ + if (adsi->pwfxDst->wBitsPerSample == 16) + aad->convert = cvtXXalaw16K; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxSrc->wBitsPerSample != 16) + goto theEnd; + + /* g711 coding... */ + if (adsi->pwfxSrc->wBitsPerSample == 16) + aad->convert = cvtXX16alawK; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + /* resampling or mono <=> stereo not available + * G711 algo only define 16 bit per sample output + */ + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxDst->wBitsPerSample != 16) + goto theEnd; + + /* g711 MU-Law decoding... */ + if (adsi->pwfxDst->wBitsPerSample == 16) + aad->convert = cvtXXulaw16K; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || + adsi->pwfxSrc->wBitsPerSample != 16) + goto theEnd; + + /* g711 coding... */ + if (adsi->pwfxSrc->wBitsPerSample == 16) + aad->convert = cvtXX16ulawK; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels) + goto theEnd; + + /* MU-Law => A-Law... */ + aad->convert = cvtXXulawalawK; + } + else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW) + { + if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || + adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels) + goto theEnd; + + /* A-Law => MU-Law... */ + aad->convert = cvtXXalawulawK; + } + else goto theEnd; + + G711_Reset(adsi, aad); + + return MMSYSERR_NOERROR; + + theEnd: + HeapFree(GetProcessHeap(), 0, aad); + adsi->dwDriver = 0L; + return MMSYSERR_NOTSUPPORTED; +} + +/*********************************************************************** + * G711_StreamClose + * + */ +static LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi) +{ + HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_StreamSize + * + */ +static LRESULT G711_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) +{ + switch (adss->fdwSize) + { + case ACM_STREAMSIZEF_DESTINATION: + /* cbDstLength => cbSrcLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) + { + adss->cbSrcLength = adss->cbDstLength / 2; + } + else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + adss->cbSrcLength = adss->cbDstLength * 2; + } + else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && + (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) + { + adss->cbSrcLength = adss->cbDstLength; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + case ACM_STREAMSIZEF_SOURCE: + /* cbSrcLength => cbDstLength */ + if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && + (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) + { + adss->cbDstLength = adss->cbSrcLength * 2; + } + else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) + { + adss->cbDstLength = adss->cbSrcLength / 2; + } + else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && + (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) + { + adss->cbDstLength = adss->cbSrcLength; + } + else + { + return MMSYSERR_NOTSUPPORTED; + } + break; + default: + WARN("Unsupported query %08x\n", adss->fdwSize); + return MMSYSERR_NOTSUPPORTED; + } + FIXME("\n"); + return MMSYSERR_NOERROR; +} + +/*********************************************************************** + * G711_StreamConvert + * + */ +static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) +{ + AcmG711Data* aad = (AcmG711Data*)adsi->dwDriver; + DWORD nsrc = adsh->cbSrcLength; + DWORD ndst = adsh->cbDstLength; + + if (adsh->fdwConvert & + ~(ACM_STREAMCONVERTF_BLOCKALIGN| + ACM_STREAMCONVERTF_END| + ACM_STREAMCONVERTF_START)) + { + FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); + } + /* ACM_STREAMCONVERTF_BLOCKALIGN + * currently all conversions are block aligned, so do nothing for this flag + * ACM_STREAMCONVERTF_END + * no pending data, so do nothing for this flag + */ + if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) + { + G711_Reset(adsi, aad); + } + + aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); + adsh->cbSrcLengthUsed = nsrc; + adsh->cbDstLengthUsed = ndst; + + return MMSYSERR_NOERROR; +} + +/************************************************************************** + * G711_DriverProc [exported] + */ +LRESULT CALLBACK G711_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, + LPARAM dwParam1, LPARAM dwParam2) +{ + TRACE("(%08lx %p %04x %08lx %08lx);\n", + dwDevID, hDriv, wMsg, dwParam1, dwParam2); + + switch (wMsg) + { + case DRV_LOAD: return 1; + case DRV_FREE: return 1; + case DRV_OPEN: return G711_drvOpen((LPSTR)dwParam1); + case DRV_CLOSE: return G711_drvClose(dwDevID); + case DRV_ENABLE: return 1; + case DRV_DISABLE: return 1; + case DRV_QUERYCONFIGURE: return 1; + case DRV_CONFIGURE: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1; + case DRV_INSTALL: return DRVCNF_RESTART; + case DRV_REMOVE: return DRVCNF_RESTART; + + case ACMDM_DRIVER_NOTIFY: + /* no caching from other ACM drivers is done so far */ + return MMSYSERR_NOERROR; + + case ACMDM_DRIVER_DETAILS: + return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1); + + case ACMDM_FORMATTAG_DETAILS: + return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_DETAILS: + return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); + + case ACMDM_FORMAT_SUGGEST: + return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); + + case ACMDM_STREAM_OPEN: + return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_CLOSE: + return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); + + case ACMDM_STREAM_SIZE: + return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); + + case ACMDM_STREAM_CONVERT: + return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); + + case ACMDM_HARDWARE_WAVE_CAPS_INPUT: + case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: + /* this converter is not a hardware driver */ + case ACMDM_FILTERTAG_DETAILS: + case ACMDM_FILTER_DETAILS: + /* this converter is not a filter */ + case ACMDM_STREAM_RESET: + /* only needed for asynchronous driver... we aren't, so just say it */ + return MMSYSERR_NOTSUPPORTED; + case ACMDM_STREAM_PREPARE: + case ACMDM_STREAM_UNPREPARE: + /* nothing special to do here... so don't do anything */ + return MMSYSERR_NOERROR; + + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} diff --git a/reactos/dll/win32/msvidc32/msvidc32.rbuild b/reactos/dll/win32/msvidc32/msvidc32.rbuild new file mode 100644 index 00000000000..7ebb98a3381 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32.rbuild @@ -0,0 +1,12 @@ + + + . + include/reactos/wine + + msvideo1.c + rsrc.rc + wine + user32 + kernel32 + ntdll + diff --git a/reactos/dll/win32/msvidc32/msvidc32.spec b/reactos/dll/win32/msvidc32/msvidc32.spec new file mode 100644 index 00000000000..e93470adea9 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32.spec @@ -0,0 +1 @@ +@ stdcall -private DriverProc(long long long long long) CRAM_DriverProc diff --git a/reactos/dll/win32/msvidc32/msvidc32_Da.rc b/reactos/dll/win32/msvidc32/msvidc32_Da.rc new file mode 100644 index 00000000000..50ae3f6f5a0 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Da.rc @@ -0,0 +1,27 @@ +/* + * Danish language support + * + * Copyright (C) 2008 Jens Albretsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_DANISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 videokodeks" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_De.rc b/reactos/dll/win32/msvidc32/msvidc32_De.rc new file mode 100644 index 00000000000..1d0de70d0db --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_De.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2005 Henning Gerhardt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 Video Codec" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_En.rc b/reactos/dll/win32/msvidc32/msvidc32_En.rc new file mode 100644 index 00000000000..93c8518ec9d --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_En.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 video codec" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Fr.rc b/reactos/dll/win32/msvidc32/msvidc32_Fr.rc new file mode 100644 index 00000000000..3592f31331c --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Fr.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2006 Jonathan Ernst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "codec vidéo Wine Video 1" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Hu.rc b/reactos/dll/win32/msvidc32/msvidc32_Hu.rc new file mode 100644 index 00000000000..c031963f495 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Hu.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2006 Andras Kovacs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 video kodek" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ko.rc b/reactos/dll/win32/msvidc32/msvidc32_Ko.rc new file mode 100644 index 00000000000..11c18c1134f --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Ko.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine ºñµð¿À 1 ºñµð¿À ÄÚµ¦" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Nl.rc b/reactos/dll/win32/msvidc32/msvidc32_Nl.rc new file mode 100644 index 00000000000..b68d3eff7a0 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Nl.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Frans Kool + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 video codec" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_No.rc b/reactos/dll/win32/msvidc32/msvidc32_No.rc new file mode 100644 index 00000000000..6d27778dfcc --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_No.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Alexander N. Sørnes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1-videokodek" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Pl.rc b/reactos/dll/win32/msvidc32/msvidc32_Pl.rc new file mode 100644 index 00000000000..af39271d3b1 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Pl.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Kodek Wine Video 1" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Pt.rc b/reactos/dll/win32/msvidc32/msvidc32_Pt.rc new file mode 100644 index 00000000000..8dcda922a39 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Pt.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Ricardo Filipe + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "codec video Wine Video 1" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ro.rc b/reactos/dll/win32/msvidc32/msvidc32_Ro.rc new file mode 100644 index 00000000000..fa7584a7dfd --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Ro.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * Copyright 2008 Michael Stefaniuc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Codecul video Wine Video 1" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Ru.rc b/reactos/dll/win32/msvidc32/msvidc32_Ru.rc new file mode 100644 index 00000000000..2c84bff4da4 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Ru.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2008 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Âèäåî êîäåð Wine Video 1" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Si.rc b/reactos/dll/win32/msvidc32/msvidc32_Si.rc new file mode 100644 index 00000000000..060ad082142 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Si.rc @@ -0,0 +1,29 @@ +/* + * Copyright 2008 Rok Mandeljc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma code_page(65001) + +LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 video kodek" +} + +#pragma code_page(default) diff --git a/reactos/dll/win32/msvidc32/msvidc32_Sv.rc b/reactos/dll/win32/msvidc32/msvidc32_Sv.rc new file mode 100644 index 00000000000..1f4770d7a80 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Sv.rc @@ -0,0 +1,25 @@ +/* + * Copyright 2007 Daniel Nylander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Video 1 videokodek" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_Tr.rc b/reactos/dll/win32/msvidc32/msvidc32_Tr.rc new file mode 100644 index 00000000000..2353b0c542e --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_Tr.rc @@ -0,0 +1,27 @@ +/* + * Turkish Resources + * + * Copyright 2006 Fatih Aþýcý + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_NAME "MS-CRAM" + IDS_DESCRIPTION "Wine Vidyo 1 vidyo çözücü" +} diff --git a/reactos/dll/win32/msvidc32/msvidc32_private.h b/reactos/dll/win32/msvidc32/msvidc32_private.h new file mode 100644 index 00000000000..b47c6e6f556 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvidc32_private.h @@ -0,0 +1,25 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __MSVIDC32_PRIVATE_H +#define __MSVIDC32_PRIVATE_H + +#define IDS_NAME 100 +#define IDS_DESCRIPTION 101 + +#endif /* __MSVIDC32_PRIVATE_H */ diff --git a/reactos/dll/win32/msvidc32/msvideo1.c b/reactos/dll/win32/msvidc32/msvideo1.c new file mode 100644 index 00000000000..9de2a2d35e9 --- /dev/null +++ b/reactos/dll/win32/msvidc32/msvideo1.c @@ -0,0 +1,598 @@ +/* + * Microsoft Video-1 Decoder + * Copyright (C) 2003 the ffmpeg project + * + * Portions Copyright (C) 2004 Mike McCormack for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +/** + * @file msvideo1.c + * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the MS Video-1 format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * This decoder outputs either PAL8 or RGB555 data, depending on the + * whether a RGB palette was passed through palctrl; + * if it's present, then the data is PAL8; RGB555 otherwise. + */ + +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "commdlg.h" +#include "vfw.h" +#include "mmsystem.h" +#include "msvidc32_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvidc32); + +static HINSTANCE MSVIDC32_hModule; + +#define CRAM_MAGIC mmioFOURCC('C', 'R', 'A', 'M') +#define MSVC_MAGIC mmioFOURCC('M', 'S', 'V', 'C') +#define WHAM_MAGIC mmioFOURCC('W', 'H', 'A', 'M') + +#define PALETTE_COUNT 256 +#define LE_16(x) ((((const uint8_t *)(x))[1] << 8) | ((const uint8_t *)(x))[0]) + +/* FIXME - check the stream size */ +#define CHECK_STREAM_PTR(n) \ + if ((stream_ptr + n) > buf_size ) { \ + WARN("stream_ptr out of bounds (%d >= %d)\n", \ + stream_ptr + n, buf_size); \ + return; \ + } + +typedef BYTE uint8_t; + +typedef struct Msvideo1Context { + DWORD dwMagic; + int mode_8bit; /* if it's not 8-bit, it's 16-bit */ +} Msvideo1Context; + +static void +msvideo1_decode_8bit( int width, int height, const unsigned char *buf, int buf_size, + unsigned char *pixels, int stride) +{ + int block_ptr, pixel_ptr; + int total_blocks; + int pixel_x, pixel_y; /* pixel width and height iterators */ + int block_x, block_y; /* block width and height iterators */ + int blocks_wide, blocks_high; /* width and height in 4x4 blocks */ + int block_inc; + int row_dec; + + /* decoding parameters */ + int stream_ptr; + unsigned char byte_a, byte_b; + unsigned short flags; + int skip_blocks; + unsigned char colors[8]; + + stream_ptr = 0; + skip_blocks = 0; + blocks_wide = width / 4; + blocks_high = height / 4; + total_blocks = blocks_wide * blocks_high; + block_inc = 4; + row_dec = stride + 4; + + for (block_y = blocks_high; block_y > 0; block_y--) { + block_ptr = ((block_y * 4) - 1) * stride; + for (block_x = blocks_wide; block_x > 0; block_x--) { + /* check if this block should be skipped */ + if (skip_blocks) { + block_ptr += block_inc; + skip_blocks--; + total_blocks--; + continue; + } + + pixel_ptr = block_ptr; + + /* get the next two bytes in the encoded data stream */ + CHECK_STREAM_PTR(2); + byte_a = buf[stream_ptr++]; + byte_b = buf[stream_ptr++]; + + /* check if the decode is finished */ + if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) + return; + else if ((byte_b & 0xFC) == 0x84) { + /* skip code, but don't count the current block */ + skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1; + } else if (byte_b < 0x80) { + /* 2-color encoding */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(2); + colors[0] = buf[stream_ptr++]; + colors[1] = buf[stream_ptr++]; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + { +#if ORIGINAL + pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1]; +#else + pixels[width*(height-(pixel_ptr/width)-1) + + pixel_ptr%width] = + colors[(flags & 0x1) ^ 1]; + pixel_ptr++; +#endif + } + pixel_ptr -= row_dec; + } + } else if (byte_b >= 0x90) { + /* 8-color encoding */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(8); + memcpy(colors, &buf[stream_ptr], 8); + stream_ptr += 8; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + { +#if ORIGINAL + pixels[pixel_ptr++] = + colors[((pixel_y & 0x2) << 1) + + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)]; +#else + pixels[width*(height-(pixel_ptr/width)-1) + + pixel_ptr%width] = + colors[((pixel_y & 0x2) << 1) + + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)]; + pixel_ptr++; +#endif + } + pixel_ptr -= row_dec; + } + } else { + /* 1-color encoding */ + colors[0] = byte_a; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) + { +#if ORIGINAL + pixels[pixel_ptr++] = colors[0]; +#else + pixels[width*(height-(pixel_ptr/width)-1) + + pixel_ptr%width] = colors[0]; + pixel_ptr++; +#endif + } + pixel_ptr -= row_dec; + } + } + + block_ptr += block_inc; + total_blocks--; + } + } +} + +static void +msvideo1_decode_16bit( int width, int height, const unsigned char *buf, int buf_size, + unsigned short *pixels, int stride) +{ + int block_ptr, pixel_ptr; + int total_blocks; + int pixel_x, pixel_y; /* pixel width and height iterators */ + int block_x, block_y; /* block width and height iterators */ + int blocks_wide, blocks_high; /* width and height in 4x4 blocks */ + int block_inc; + int row_dec; + + /* decoding parameters */ + int stream_ptr; + unsigned char byte_a, byte_b; + unsigned short flags; + int skip_blocks; + unsigned short colors[8]; + + stream_ptr = 0; + skip_blocks = 0; + blocks_wide = width / 4; + blocks_high = height / 4; + total_blocks = blocks_wide * blocks_high; + block_inc = 4; + row_dec = stride + 4; + + for (block_y = blocks_high; block_y > 0; block_y--) { + block_ptr = ((block_y * 4) - 1) * stride; + for (block_x = blocks_wide; block_x > 0; block_x--) { + /* check if this block should be skipped */ + if (skip_blocks) { + block_ptr += block_inc; + skip_blocks--; + total_blocks--; + continue; + } + + pixel_ptr = block_ptr; + + /* get the next two bytes in the encoded data stream */ + CHECK_STREAM_PTR(2); + byte_a = buf[stream_ptr++]; + byte_b = buf[stream_ptr++]; + + /* check if the decode is finished */ + if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) { + return; + } else if ((byte_b & 0xFC) == 0x84) { + /* skip code, but don't count the current block */ + skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1; + } else if (byte_b < 0x80) { + /* 2- or 8-color encoding modes */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(4); + colors[0] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[1] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + + if (colors[0] & 0x8000) { + /* 8-color encoding */ + CHECK_STREAM_PTR(12); + colors[2] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[3] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[4] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[5] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[6] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + colors[7] = LE_16(&buf[stream_ptr]); + stream_ptr += 2; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = + colors[((pixel_y & 0x2) << 1) + + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)]; + pixel_ptr -= row_dec; + } + } else { + /* 2-color encoding */ + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1]; + pixel_ptr -= row_dec; + } + } + } else { + /* otherwise, it's a 1-color block */ + colors[0] = (byte_b << 8) | byte_a; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) + pixels[pixel_ptr++] = colors[0]; + pixel_ptr -= row_dec; + } + } + + block_ptr += block_inc; + total_blocks--; + } + } +} + +static LRESULT +CRAM_DecompressQuery( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + TRACE("ICM_DECOMPRESS_QUERY %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + TRACE("planes = %d\n", in->bmiHeader.biPlanes ); + TRACE("bpp = %d\n", in->bmiHeader.biBitCount ); + TRACE("height = %d\n", in->bmiHeader.biHeight ); + TRACE("width = %d\n", in->bmiHeader.biWidth ); + TRACE("compr = %x\n", in->bmiHeader.biCompression ); + + if( ( in->bmiHeader.biCompression != CRAM_MAGIC ) && + ( in->bmiHeader.biCompression != MSVC_MAGIC ) && + ( in->bmiHeader.biCompression != WHAM_MAGIC ) ) + return ICERR_UNSUPPORTED; + + if( ( in->bmiHeader.biBitCount != 16 ) && + ( in->bmiHeader.biBitCount != 8 ) ) + { + TRACE("can't do %d bpp\n", in->bmiHeader.biBitCount ); + return ICERR_UNSUPPORTED; + } + + /* output must be same dimensions as input */ + if( out ) + { + if( in->bmiHeader.biBitCount != out->bmiHeader.biBitCount ) + return ICERR_UNSUPPORTED; + if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) + return ICERR_UNSUPPORTED; + if( in->bmiHeader.biHeight != out->bmiHeader.biHeight ) + return ICERR_UNSUPPORTED; + if( in->bmiHeader.biWidth != out->bmiHeader.biWidth ) + return ICERR_UNSUPPORTED; + } + + TRACE("OK!\n"); + + return ICERR_OK; +} + +static LRESULT +CRAM_DecompressGetFormat( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + DWORD size; + + TRACE("ICM_DECOMPRESS_GETFORMAT %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + size = in->bmiHeader.biSize; + if (in->bmiHeader.biBitCount <= 8) + size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD); + + if( out ) + { + memcpy( out, in, size ); + out->bmiHeader.biCompression = BI_RGB; + out->bmiHeader.biSizeImage = in->bmiHeader.biHeight + * in->bmiHeader.biWidth *4; + return ICERR_OK; + } + + return size; +} + +static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out ) +{ + TRACE("ICM_DECOMPRESS_BEGIN %p %p %p\n", info, in, out); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount); + if( in->bmiHeader.biBitCount == 8 ) + info->mode_8bit = 1; + else if( in->bmiHeader.biBitCount == 16 ) + info->mode_8bit = 0; + else + { + ERR("Bad output format\n"); + return ICERR_BADPARAM; + } + + return ICERR_OK; +} + +static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size ) +{ + LONG width, height, stride, sz; + WORD bit_per_pixel; + + TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + /* FIXME: flags are ignored */ + + width = icd->lpbiInput->biWidth; + height = icd->lpbiInput->biHeight; + bit_per_pixel = icd->lpbiInput->biBitCount; + stride = width*bit_per_pixel/8; + sz = icd->lpbiInput->biSizeImage; + + if (info->mode_8bit) + { + msvideo1_decode_8bit( width, height, icd->lpInput, sz, + icd->lpOutput, stride); + } + else + { + msvideo1_decode_16bit( width, height, icd->lpInput, sz, + icd->lpOutput, stride); + } + + return ICERR_OK; +} + +static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size ) +{ + LONG width, height, stride, sz; + WORD bit_per_pixel; + + TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size); + + if( (info==NULL) || (info->dwMagic!=CRAM_MAGIC) ) + return ICERR_BADPARAM; + + /* FIXME: flags are ignored */ + + width = icd->lpbiSrc->biWidth; + height = icd->lpbiSrc->biHeight; + bit_per_pixel = icd->lpbiSrc->biBitCount; + stride = width*bit_per_pixel/8; + sz = icd->lpbiSrc->biSizeImage; + + if (info->mode_8bit) + { + msvideo1_decode_8bit( width, height, icd->lpSrc, sz, + icd->lpDst, stride); + } + else + { + msvideo1_decode_16bit( width, height, icd->lpSrc, sz, + icd->lpDst, stride); + } + + return ICERR_OK; +} + +static LRESULT CRAM_GetInfo( const Msvideo1Context *info, ICINFO *icinfo, DWORD dwSize ) +{ + if (!icinfo) return sizeof(ICINFO); + if (dwSize < sizeof(ICINFO)) return 0; + + icinfo->dwSize = sizeof(ICINFO); + icinfo->fccType = ICTYPE_VIDEO; + icinfo->fccHandler = info ? info->dwMagic : CRAM_MAGIC; + icinfo->dwFlags = 0; + icinfo->dwVersion = ICVERSION; + icinfo->dwVersionICM = ICVERSION; + + LoadStringW(MSVIDC32_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR)); + LoadStringW(MSVIDC32_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR)); + /* msvfw32 will fill icinfo->szDriver for us */ + + return sizeof(ICINFO); +} + +/*********************************************************************** + * DriverProc (MSVIDC32.@) + */ +LRESULT WINAPI CRAM_DriverProc( DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg, + LPARAM lParam1, LPARAM lParam2 ) +{ + Msvideo1Context *info = (Msvideo1Context *) dwDriverId; + LRESULT r = ICERR_UNSUPPORTED; + + TRACE("%ld %p %04x %08lx %08lx\n", dwDriverId, hdrvr, msg, lParam1, lParam2); + + switch( msg ) + { + case DRV_LOAD: + TRACE("Loaded\n"); + r = 1; + break; + + case DRV_ENABLE: + break; + + case DRV_OPEN: + { + ICINFO *icinfo = (ICINFO *)lParam2; + + TRACE("Opened\n"); + + if (icinfo && icinfo->fccType != ICTYPE_VIDEO) return 0; + + info = HeapAlloc( GetProcessHeap(), 0, sizeof (Msvideo1Context) ); + if( info ) + { + memset( info, 0, sizeof info ); + info->dwMagic = CRAM_MAGIC; + } + r = (LRESULT) info; + break; + } + + case DRV_CLOSE: + HeapFree( GetProcessHeap(), 0, info ); + break; + + case DRV_DISABLE: + break; + + case DRV_FREE: + break; + + case ICM_GETINFO: + r = CRAM_GetInfo( info, (ICINFO *)lParam1, (DWORD)lParam2 ); + break; + + case ICM_DECOMPRESS_QUERY: + r = CRAM_DecompressQuery( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + break; + + case ICM_DECOMPRESS_GET_FORMAT: + r = CRAM_DecompressGetFormat( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + break; + + case ICM_DECOMPRESS_GET_PALETTE: + FIXME("ICM_DECOMPRESS_GET_PALETTE\n"); + break; + + case ICM_DECOMPRESSEX_QUERY: + FIXME("ICM_DECOMPRESSEX_QUERY\n"); + break; + + case ICM_DECOMPRESS: + r = CRAM_Decompress( info, (ICDECOMPRESS*) lParam1, + (DWORD) lParam2 ); + break; + + case ICM_DECOMPRESS_BEGIN: + r = CRAM_DecompressBegin( info, (LPBITMAPINFO) lParam1, + (LPBITMAPINFO) lParam2 ); + break; + + case ICM_DECOMPRESSEX: + r = CRAM_DecompressEx( info, (ICDECOMPRESSEX*) lParam1, + (DWORD) lParam2 ); + break; + + case ICM_COMPRESS_QUERY: + FIXME("compression not implemented\n"); + r = ICERR_BADFORMAT; + break; + + case ICM_CONFIGURE: + r = ICERR_UNSUPPORTED; + break; + + default: + FIXME("Unknown message: %04x %ld %ld\n", msg, lParam1, lParam2); + } + + return r; +} + +/*********************************************************************** + * DllMain + */ +BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) +{ + TRACE("(%p,%d,%p)\n", hModule, dwReason, lpReserved); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + MSVIDC32_hModule = hModule; + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} diff --git a/reactos/dll/win32/msvidc32/rsrc.rc b/reactos/dll/win32/msvidc32/rsrc.rc new file mode 100644 index 00000000000..f7f7630c9a9 --- /dev/null +++ b/reactos/dll/win32/msvidc32/rsrc.rc @@ -0,0 +1,36 @@ +/* + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windef.h" +#include "msvidc32_private.h" + +#include "msvidc32_Da.rc" +#include "msvidc32_De.rc" +#include "msvidc32_Fr.rc" +#include "msvidc32_En.rc" +#include "msvidc32_Hu.rc" +#include "msvidc32_Ko.rc" +#include "msvidc32_Nl.rc" +#include "msvidc32_No.rc" +#include "msvidc32_Pl.rc" +#include "msvidc32_Pt.rc" +#include "msvidc32_Ro.rc" +#include "msvidc32_Ru.rc" +#include "msvidc32_Si.rc" +#include "msvidc32_Sv.rc" +#include "msvidc32_Tr.rc" diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild index 57aa44a5a89..657de9b9563 100644 --- a/reactos/dll/win32/win32.rbuild +++ b/reactos/dll/win32/win32.rbuild @@ -124,9 +124,15 @@ + + + + + + @@ -208,6 +214,9 @@ + + + @@ -226,6 +235,9 @@ + + + @@ -262,6 +274,9 @@ + + + diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 128c43048a8..5cd8f4d92b2 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -50,7 +50,9 @@ reactos/dll/win32/dciman32 # Synced to Wine-1_0-rc2 reactos/dll/win32/gdiplus # Autosync reactos/dll/win32/hhctrl.ocx # Autosync reactos/dll/win32/hlink # Autosync +reactos/dll/win32/iccvid # Autosync reactos/dll/win32/icmp # Synced to Wine-0_9_10 +reactos/dll/win32/imaadp32.acm # Autosync reactos/dll/win32/imm32 # Autosync reactos/dll/win32/imagehlp # Patches for BindImage need review and submission to winehq. reactos/dll/win32/inetcomm # Autosync @@ -71,11 +73,13 @@ reactos/dll/win32/mciwave # Autosync reactos/dll/win32/mlang # Autosync reactos/dll/win32/mpr # Autosync reactos/dll/win32/msacm32 # Out of sync +reactos/dll/win32/msadp32.acm # Autosync reactos/dll/win32/mscat32 # Autosync reactos/dll/win32/mscms # Autosync reactos/dll/win32/mscoree # Autosync reactos/dll/win32/msctf # Autosync reactos/dll/win32/msftedit # Autosync +reactos/dll/win32/msg711.acm # Autosync reactos/dll/win32/mshtml # Autosync reactos/dll/win32/msimg32 # Autosync reactos/dll/win32/msi # Autosync @@ -84,6 +88,7 @@ reactos/dll/win32/msrle32 # Autosync reactos/dll/win32/mstask # Autosync reactos/dll/win32/msvcrt20 # Autosync reactos/dll/win32/msvfw32 # Autosync +reactos/dll/win32/msvidc32 # Autosync reactos/dll/win32/msxml3 # Synced to Wine-20071230 reactos/dll/win32/nddeapi # Autosync reactos/dll/win32/netapi32 # Autosync