home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include "..\filters.h"
- #include "common.h"
- #include "decoder.h"
-
- typedef short PCM[2][3][SBLIMIT];
- PCM FAR *pcm_sample;
- typedef unsigned int SAM[2][3][SBLIMIT];
- SAM FAR *sample;
- typedef double FRA[2][3][SBLIMIT];
- FRA FAR *fraction;
- typedef double VE[2][HAN_SIZE];
- VE FAR *w;
-
- Bit_stream_struc bs;
- frame_params fr_ps;
- layer info;
- unsigned long sample_frames;
- int themode=0;
-
- int i, j, k, stereo, done=FALSE, clip, sync;
- int error_protection, crc_error_count, total_error_count;
- unsigned int old_crc, new_crc;
- unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT],
- scale_index[2][3][SBLIMIT];
- unsigned long bitsPerSlot, samplesPerFrame, frameNum = 0;
- unsigned long frameBits, gotBits = 0;
- char encoded_file_name[MAX_NAME_SIZE];
- char decoded_file_name[MAX_NAME_SIZE];
- char t[50];
- int need_aiff;
- int topSb = 0;
-
- DWORD bbufat=0;
-
- #define MPEG_LAYER1 1
- #define MPEG_LAYER2 2
- #define MPEG_MODEL1 4
- #define MPEG_MODEL2 8
- #define MPEG_EMPHANO 16
- #define MPEG_EMPHA1 32
- #define MPEG_EMPHA2 64
- #define MPEG_JOINTSTEREO 128
- #define MPEG_ERRORPROTECTION 0x010000
- #define MPEG_COPYRIGHT 0x020000
- #define MPEG_ORIGINAL 0x040000
-
- typedef struct output_tag // any special vars associated with output file
- {short nFile;
- long lSize;
- } MYOUTPUT;
-
- typedef struct input_tag // any special vars associated with input file
- {short nFile;
- long lSize;
- long lSamprate;
- DWORD options;
- } MYINPUT;
-
- HANDLE myInstance=NULL;
-
- BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
- {
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- /* Code from LibMain inserted here. Return TRUE to keep the
- DLL loaded or return FALSE to fail loading the DLL.
-
- You may have to modify the code in your original LibMain to
- account for the fact that it may be called more than once.
- You will get one DLL_PROCESS_ATTACH for each process that
- loads the DLL. This is different from LibMain which gets
- called only once when the DLL is loaded. The only time this
- is critical is when you are using shared data sections.
- If you are using shared data sections for statically
- allocated data, you will need to be careful to initialize it
- only once. Check your code carefully.
-
- Certain one-time initializations may now need to be done for
- each process that attaches. You may also not need code from
- your original LibMain because the operating system may now
- be doing it for you.
- */
-
- myInstance=hModule;
-
- break;
-
- case DLL_THREAD_ATTACH:
- /* Called each time a thread is created in a process that has
- already loaded (attached to) this DLL. Does not get called
- for each thread that exists in the process before it loaded
- the DLL.
-
- Do thread-specific initialization here.
- */
- break;
-
- case DLL_THREAD_DETACH:
- /* Same as above, but called when a thread in the process
- exits.
-
- Do thread-specific cleanup here.
- */
- break;
-
- case DLL_PROCESS_DETACH:
- /* Code from _WEP inserted here. This code may (like the
- LibMain) not be necessary. Check to make certain that the
- operating system is not doing it for you.
- */
- myInstance=NULL;
- break;
- }
-
- /* The return value is only used for DLL_PROCESS_ATTACH; all other
- conditions are ignored. */
- return TRUE; // successful DLL_PROCESS_ATTACH
- }
-
- // Fill COOLQUERY structure with information regarding this file filter
-
- __declspec(dllexport) short FAR PASCAL QueryCoolFilter(COOLQUERY far * cq)
- { lstrcpy(cq->szName,"MPEG");
- lstrcpy(cq->szCopyright,"MPEG II Decoder (GNU General Public License)");
- lstrcpy(cq->szExt,"MP2");
- lstrcpy(cq->szExt2,"MP1");
- lstrcpy(cq->szExt3,"MPG");
- cq->lChunkSize=16384;
- cq->dwFlags=QF_RATEADJUSTABLE|QF_CANLOAD;
- cq->Stereo8=0;
- cq->Stereo16=R_32075|R_44100|R_48000;
- cq->Stereo24=0;
- cq->Stereo32=0;
- cq->Mono8=0;
- cq->Mono16=R_32075|R_44100|R_48000;
- cq->Mono24=0;
- cq->Mono32=0;
- cq->Quad32=0;
- cq->Quad16=0;
- cq->Quad8=0;
- return C_VALIDLIBRARY;
- }
-
- __declspec(dllexport) long FAR PASCAL FilterGetFileSize(HANDLE hInput)
- { long lSize=0L;
- //char m[50];
- //wsprintf(m,"FilterGetSize: Handle=%04X\n",hInput);
- //OutputDebugString(m);
- if (hInput)
- { MYINPUT far *mi;
- mi=(MYINPUT far *)GlobalLock(hInput);
- lSize=mi->lSize;
- //wsprintf(m,"FilterGetSize: Size = %ld\n",lSize);
- //OutputDebugString(m);
- GlobalUnlock(hInput);
- }
- return lSize;
- }
-
- __declspec(dllexport) BOOL FAR PASCAL FilterUnderstandsFormat(LPSTR filename)
- { //char m[100];
- //wsprintf(m,"Checking VOC support for %s\n",filename);
- //OutputDebugString(m);
- if ((lstrlen(filename)>4) &&
- ((strcmpi(filename+lstrlen(filename)-4,".mpg")==0) ||
- (strcmpi(filename+lstrlen(filename)-4,".mp2")==0) ||
- (strcmpi(filename+lstrlen(filename)-4,".mp1")==0)
- ))
- { //OutputDebugString("Supported VOC!\n");
- return TRUE;
- }
- return FALSE;
- }
-
- __declspec(dllexport) DWORD FAR PASCAL FilterOptions(HANDLE hInput)
- { MYINPUT far *mi;
- DWORD options;
- if (!hInput) return 0;
- mi=(MYINPUT far *)GlobalLock(hInput);
- options=(DWORD)mi->options;
- GlobalUnlock(hInput);
- return options;
- }
-
- /*
- #define MPEG_LAYER1 1
- #define MPEG_LAYER2 2
- #define MPEG_MODEL1 4
- #define MPEG_MODEL2 8
- #define MPEG_EMPHANO 16
- #define MPEG_EMPHA1 32
- #define MPEG_EMPHA2 64
- #define MPEG_JOINTSTEREO 128
- #define MPEG_ERRORPROTECTION 0x010000
- #define MPEG_COPYRIGHT 0x020000
- #define MPEG_ORIGINAL 0x040000
- */
-
- __declspec(dllexport) DWORD FAR PASCAL FilterOptionsString(HANDLE hInput, LPSTR szString)
- { MYINPUT far *mi;
- DWORD options;
- short compression;
- short sf;
- double bps;
- short x,y;
- short r;
-
- short bitrate[3][15] = {
- {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
- {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
- {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
- };
-
-
- if (!hInput) return 0;
- mi=(MYINPUT far *)GlobalLock(hInput);
- options=(DWORD)mi->options;
-
- lstrcpy(szString,"MPEG Encoded ");
- if (options&MPEG_LAYER1)
- { lstrcpy(szString+lstrlen(szString),"Layer I ");
- r=0;
- }
- else
- { lstrcpy(szString+lstrlen(szString),"Layer II ");
- r=1;
- }
- if (options&MPEG_MODEL1)
- lstrcpy(szString+lstrlen(szString),"Model 1 ");
- else
- lstrcpy(szString+lstrlen(szString),"Model 2 ");
- compression=(short)((options>>8)&0x0F);
-
-
- if (mi->lSamprate<=32075) sf = 2;
- else if (mi->lSamprate<=44100) sf = 0;
- else if (mi->lSamprate<=48000) sf = 1;
- else sf = 1;
-
- bps=(double)bitrate[r][compression]*1024.0/(double)mi->lSamprate;
- x=(short)bps;
- bps=bps-(double)x;
- y=(short)(bps*100);
- wsprintf(szString+lstrlen(szString),"%01d.%02d bits/sample (%d bps)",x,y,bitrate[r][compression]);
- GlobalUnlock(hInput);
- return options;
- }
-
-
- __declspec(dllexport) DWORD FAR PASCAL FilterCanWriteSpecial(HANDLE hOutput, DWORD idType)
- {
- return 0L;
- }
-
- __declspec(dllexport) DWORD FAR PASCAL FilterCanReadSpecial(HANDLE hInput, DWORD idType)
- {
- return 0L;
- }
-
- __declspec(dllexport) DWORD FAR PASCAL FilterWriteSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
- {
- return 0L;
- }
-
- __declspec(dllexport) DWORD FAR PASCAL FilterReadSpecial(HANDLE hOutput, DWORD idType, unsigned char far *buf, DWORD dwSize)
- {
- return 0L;
- }
-
-
-
- __declspec(dllexport) HANDLE FAR PASCAL OpenFilterOutput(LPSTR lpstrFilename,long lSamprate,WORD wBitsPerSample,WORD wChannels,long lSize,long far *lpChunkSize,DWORD dwOptions)
- { HANDLE hOutput;
- short nFile;
- nFile=_lcreat(lpstrFilename,0);
- if (nFile==-1) return NULL;
- hOutput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(MYOUTPUT));
- if (hOutput)
- { MYOUTPUT far *mo;
- mo=(MYOUTPUT far *)GlobalLock(hOutput);
- mo->nFile=nFile;
- mo->lSize=lSize;
- GlobalUnlock(hOutput);
- }
- *lpChunkSize=16384;
- return hOutput;
- }
-
- __declspec(dllexport) void FAR PASCAL CloseFilterOutput(HANDLE hOutput)
- { if (hOutput)
- { MYOUTPUT far *mo;
- mo=(MYOUTPUT far *)GlobalLock(hOutput);
- if (mo->nFile!=-1)
- { _lclose(mo->nFile);
- mo->nFile=-1;
- }
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- }
- }
-
- __declspec(dllexport) DWORD FAR PASCAL WriteFilterOutput(HANDLE hOutput, unsigned char far *buf, long lBytes)
- { DWORD written=0L;
- if (hOutput)
- { MYOUTPUT far *mo;
- mo=(MYOUTPUT far *)GlobalLock(hOutput);
- written=(DWORD)_lwrite(mo->nFile,buf,(UINT)lBytes);
- GlobalUnlock(hOutput);
- }
- return written;
- }
-
-
- HANDLE hMemory=NULL;
- unsigned char far *memory=NULL;
- long bbuflen=0;
-
- short CycleToFillMemory(void);
-
- // return handle that will be passed in to close, and write routines
- __declspec(dllexport) HANDLE FAR PASCAL OpenFilterInput( LPSTR lpstrFilename,
- long far *lSamprate,
- WORD far *wBitsPerSample,
- WORD far *wChannels,
- HWND hWnd,
- long far *lChunkSize)
- { HANDLE hInput;
- //char m[100];
- char lpszFilename[128];
- long lBitRate;
- short source;
- long fullsize;
- DWORD dwOptions;
-
- dwOptions=0;
-
- source=_lopen(lpstrFilename,OF_READ);
- if (source==-1) return NULL;
-
- fullsize=_llseek(source,0L,2);
- _lclose(source);
-
- hInput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(MYINPUT));
- if (hInput)
- { MYINPUT far *mi;
- mi=(MYINPUT far *)GlobalLock(hInput);
- //wsprintf(m,"OpenFilterInput: Size = %ld\n",mi->lSize);
- //OutputDebugString(m);
- //_llseek(nFile,0L,0);
- // return 0 for cool to inquire user for sample rates
- *lSamprate=44100;
- *wBitsPerSample=16;
- *wChannels=2;
- *lChunkSize=16384;
-
- /* Most large variables are declared dynamically to ensure
- compatibility with smaller machines */
-
- {//char m[100];
- //wsprintf(m,"My instance = %04X\n",myInstance);
- //OutputDebugString(m);
- GetModuleFileName(myInstance,(LPSTR)lpszFilename,128);
- //OutputDebugString(lpszFilename);
- //OutputDebugString("\n");
- lstrcpy(strrchr((LPSTR)lpszFilename,'\\'),"\\MPEG.DAT");
- };
-
- if (table_ready(lpszFilename)==1) // davej@microsoft.com compiled data files into one
- { //char m[100];
- //wsprintf(m,"Could not open %s!\n",(LPSTR)lpszFilename);
- //OutputDebugString(m);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return NULL;
- }
-
- pcm_sample = (PCM FAR *) mem_alloc((long) sizeof(PCM), "PCM Samp");
- sample = (SAM FAR *) mem_alloc((long) sizeof(SAM), "Sample");
- fraction = (FRA FAR *) mem_alloc((long) sizeof(FRA), "fraction");
- w = (VE FAR *) mem_alloc((long) sizeof(VE), "w");
-
- fr_ps.header = &info;
- fr_ps.tab_num = -1; /* no table loaded */
- fr_ps.alloc = NULL;
- for (i=0;i<HAN_SIZE;i++) for (j=0;j<2;j++) (*w)[j][i] = 0.0;
-
- lstrcpy(encoded_file_name,lpstrFilename);
-
- open_bit_stream_r(&bs, encoded_file_name, BUFFER_SIZE);
-
- *lChunkSize=BUFFER_SIZE;
-
- sample_frames = 0;
- //{char m[128];
- // wsprintf(m,"OpenFilterInput: Returning handle %04X, lchunksize=%ld\n",hInput,(*lChunkSize));
- // OutputDebugString(m);
- //}
- hMemory=GlobalAlloc(GMEM_MOVEABLE,16384);
- memory=(unsigned char far *)GlobalLock(hMemory);
- bbufat=0;
- bbuflen=0;
-
-
- CycleToFillMemory();
-
- *wChannels=stereo;
- *lSamprate=(long)(s_freq[info.sampling_frequency]*1000.0);
-
- lBitRate=(long)(bitrate[info.lay-1][info.bitrate_index])*1024/8;
-
- if (themode==MPG_MD_JOINT_STEREO)
- dwOptions|=MPEG_JOINTSTEREO;
- dwOptions|=(info.bitrate_index<<8);
- if (info.error_protection)
- dwOptions|=MPEG_ERRORPROTECTION;
- if (info.copyright)
- dwOptions|=MPEG_COPYRIGHT;
- if (info.original)
- dwOptions|=MPEG_ORIGINAL;
- if (info.lay==1)
- dwOptions|=MPEG_LAYER1;
- else
- dwOptions|=MPEG_LAYER2;
-
- dwOptions|=MPEG_MODEL2;
-
- if (info.emphasis==1)
- dwOptions|=MPEG_EMPHA1;
- else if (info.emphasis==3)
- dwOptions|=MPEG_EMPHA2;
- else
- dwOptions|=MPEG_EMPHANO;
-
- mi->options=dwOptions;
-
-
- mi->lSize=(long)(2.0*(double)(*wChannels)*(double)(*lSamprate)*((double)fullsize/(double)lBitRate*1.03));
-
- //{char m[140];
- // wsprintf(m,"bytes/sec = %ld, total size = %ld, samprate=%ld, channels=%d, ucsize = %ld\n",
- // lBitRate,fullsize,(*lSamprate),(*wChannels),mi->lSize);
- // OutputDebugString(m);
- //};
-
- //mi->lSize+=8192; // breathing room?
- mi->lSamprate=*lSamprate;
-
- GlobalUnlock(hInput);
- }
-
- return hInput;
- }
-
- __declspec(dllexport) void FAR PASCAL CloseFilterInput(HANDLE hInput)
- { if (hInput)
- { MYINPUT far *mi;
- mi=(MYINPUT far *)GlobalLock(hInput);
-
- close_bit_stream_r(&bs);
-
- GlobalUnlock(hInput);
- GlobalFree(hInput);
-
- mem_free((void **)&pcm_sample);
- mem_free((void **)&sample);
- mem_free((void **)&fraction);
- mem_free((void **)&w);
-
- if (memory)
- { GlobalUnlock(hMemory);
- memory=NULL;
- }
- if (hMemory)
- { GlobalFree(hMemory);
- hMemory=NULL;
- }
-
- }
- }
-
- short CycleToFillMemory(void)
- { unsigned char far *buf;
- //char m[128];
- //ProfStart();
-
- buf=memory+bbuflen;
- bbufat=0;
- //OutputDebugString("Setting bbufat to 0\n");
- //wsprintf(m,"buf = memory + %ld\n",bbuflen);
- //OutputDebugString(m);
-
-
-
- if (end_bs(&bs))
- { //ProfStop();
- return 1;
- }
-
-
- sync = seek_sync(&bs, SYNC_WORD, SYNC_WORD_LNGTH);
- frameBits = sstell(&bs) - gotBits;
- if(frameNum > 0) /* don't want to prshort on 1st loop; no lay */
- if(frameBits%bitsPerSlot)
- {//char m[128];
- //wsprintf(m,"Got %ld bits = %ld slots plus %ld\n",
- // frameBits, frameBits/bitsPerSlot, frameBits%bitsPerSlot);
- //OutputDebugString(m);
- }
- gotBits += frameBits;
-
- if (!sync) {
- //OutputDebugString("Frame cannot be located\n");
- //OutputDebugString("Input stream may be empty\n");
- done = TRUE;
- /* finally write out the buffer */
- if (info.lay == 2) out_fifo(*pcm_sample, 3, &fr_ps, done,
- buf, &sample_frames);
- else out_fifo(*pcm_sample, 1, &fr_ps, done,
- buf, &sample_frames);
- //ProfStop();
-
- return -1;
- }
-
- decode_info(&bs, &fr_ps);
- hdr_to_frps(&fr_ps);
- themode = fr_ps.header->mode;
- stereo = fr_ps.stereo;
- error_protection = info.error_protection;
- crc_error_count = 0;
- total_error_count = 0;
- //if(frameNum == 0) WriteHdr(&fr_ps); /* printout layer/mode */
- //{char m[100];
- // wsprintf(m, "{%4lu}", frameNum++);
- // OutputDebugString(m);
- //}
- if (error_protection) buffer_CRC(&bs, &old_crc);
- switch (info.lay) {
-
- case 1: {
- bitsPerSlot = 32; samplesPerFrame = 384;
- I_decode_bitalloc(&bs,bit_alloc,&fr_ps);
- I_decode_scale(&bs, bit_alloc, scale_index, &fr_ps);
-
- if (error_protection) {
- I_CRC_calc(&fr_ps, bit_alloc, &new_crc);
- if (new_crc != old_crc) {
- crc_error_count++;
- total_error_count++;
- recover_CRC_error(*pcm_sample, crc_error_count,
- &fr_ps, buf, &sample_frames);
- break;
- }
- else crc_error_count = 0;
- }
-
- clip = 0;
- for (i=0;i<SCALE_BLOCK;i++) {
- I_buffer_sample(&bs,(*sample),bit_alloc,&fr_ps);
- I_dequantize_sample(*sample,*fraction,bit_alloc,&fr_ps);
- I_denormalize_sample((*fraction),scale_index,&fr_ps);
- if(topSb>0) /* clear channels to 0 */
- for(j=topSb; j<fr_ps.sblimit; ++j)
- for(k=0; k<stereo; ++k)
- (*fraction)[k][0][j] = 0;
-
- for (j=0;j<stereo;j++) {
- clip += SubBandSynthesis (&((*fraction)[j][0][0]), j,
- &((*pcm_sample)[j][0][0]));
- }
- out_fifo(*pcm_sample, 1, &fr_ps, done,
- buf, &sample_frames);
- }
- if(clip > 0)
- {//char m[100];
- //wsprintf(m,"%d output samples clipped\n", clip);
- //OutputDebugString(m);
- }
- break;
- }
-
- case 2: {
- bitsPerSlot = 8; samplesPerFrame = 1152;
- II_decode_bitalloc(&bs, bit_alloc, &fr_ps);
-
- II_decode_scale(&bs, scfsi, bit_alloc, scale_index, &fr_ps);
-
- if (error_protection) {
- II_CRC_calc(&fr_ps, bit_alloc, scfsi, &new_crc);
- if (new_crc != old_crc) {
- crc_error_count++;
- total_error_count++;
- recover_CRC_error(*pcm_sample, crc_error_count,
- &fr_ps, buf, &sample_frames);
- break;
- }
- else crc_error_count = 0;
- }
-
-
- clip = 0;
- for (i=0;i<SCALE_BLOCK;i++) {
-
- II_buffer_sample(&bs,(*sample),bit_alloc,&fr_ps);
-
- II_dequantize_sample((*sample),bit_alloc,(*fraction),&fr_ps);
-
- II_denormalize_sample((*fraction),scale_index,&fr_ps,i>>2);
-
-
- if(topSb>0) /* debug : clear channels to 0 */
- for(j=topSb; j<fr_ps.sblimit; ++j)
- for(k=0; k<stereo; ++k)
- (*fraction)[k][0][j] =
- (*fraction)[k][1][j] =
- (*fraction)[k][2][j] = 0;
-
-
- for (j=0;j<3;j++) for (k=0;k<stereo;k++) {
- clip += SubBandSynthesis (&((*fraction)[k][j][0]), k,
- &((*pcm_sample)[k][j][0]));
-
-
- }
-
- out_fifo(*pcm_sample, 3, &fr_ps, done, buf,
- &sample_frames);
-
- }
- if(clip > 0)
- {//char m[100];
- //wsprintf(m,"%d samples clipped\n", clip);
- //OutputDebugString(m);
- }
- break;
- }
-
- }
-
- //{char m[100];
- // wsprintf(m,"bbufat = %ld, bbuflen = %ld, adding, bbuflen now = %ld\n",bbufat,bbuflen,bbuflen+bbufat);
- // OutputDebugString(m);
- //};
-
- bbuflen+=bbufat;
- //ProfStop();
- return 0;
-
- }
-
-
- __declspec(dllexport) DWORD FAR PASCAL ReadFilterInput(HANDLE hInput, unsigned char far *bufout, long lBytes)
- { DWORD read=0L;
- if (hInput)
- { MYINPUT far *mi;
- //char m[100];
- mi=(MYINPUT far *)GlobalLock(hInput);
-
-
- while (bbuflen<lBytes)
- {short er;
- if ((er=CycleToFillMemory())==1)
- { //wsprintf(m,"End of File, copying %ld bytes of memory to bufout\n",bbuflen);
- //OutputDebugString(m);
- CopyMemory(bufout,memory,(short)bbuflen);
- return bbufat;
- }
- if (er==-1) break;
- }
-
- // have bbuflen bytes at memory,
- // want lBytes bytes at bufout
-
- {short amount;
- //char m[100];
- amount=(short)lBytes;
- if (amount>(short)bbuflen)
- amount=(short)bbuflen;
- //wsprintf(m,"lBytes = %ld, amount = %d (bbuflen=%ld)\n",lBytes,amount,bbuflen);
- //OutputDebugString(m);
- CopyMemory(bufout,memory,amount);
- //wsprintf(m,"Copied %d bytes from start of memory to bufout\n",amount);
- //OutputDebugString(m);
- MoveMemory(memory,memory+amount,(short)bbuflen-amount);
- //wsprintf(m,"Moved %ld bytes from memory + %d to memory\n",bbuflen-(long)amount,amount);
- //OutputDebugString(m);
- bbuflen-=amount;
- bbufat=amount;
- //wsprintf(m,"Now bbuflen = %ld, and bbufat = %ld\n",bbuflen,bbufat);
- //OutputDebugString(m);
- };
-
-
- //wsprintf(m,"ReadFilterInput: Read %ld bytes to bufout\n",bbufat);
- //OutputDebugString(m);
- GlobalUnlock(hInput);
- }
- return bbufat;
- }
-