windowscodecs: Implement Commit for BMP encoder.
[wine] / dlls / winemp3.acm / mpegl3.c
1 /*
2  * MPEG Layer 3 handling
3  *
4  *      Copyright (C) 2002              Eric Pouech
5  *
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #include "mmreg.h"
32 #include "msacm.h"
33 #include "msacmdrv.h"
34 #include "mpg123.h"
35 #include "mpglib.h"
36
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);
40
41 /***********************************************************************
42  *           MPEG3_drvOpen
43  */
44 static LRESULT MPEG3_drvOpen(LPCSTR str)
45 {
46     return 1;
47 }
48
49 /***********************************************************************
50  *           MPEG3_drvClose
51  */
52 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
53 {
54     return 1;
55 }
56
57 typedef struct tagAcmMpeg3Data
58 {
59     void (*convert)(PACMDRVSTREAMINSTANCE adsi,
60                     const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
61     struct mpstr mp;
62 } AcmMpeg3Data;
63
64 /* table to list all supported formats... those are the basic ones. this
65  * also helps given a unique index to each of the supported formats
66  */
67 typedef struct
68 {
69     int         nChannels;
70     int         nBits;
71     int         rate;
72 } Format;
73
74 static const Format PCM_Formats[] =
75 {
76     {1,  8,  8000}, {2,  8,  8000}, {1, 16,  8000}, {2, 16,  8000},
77     {1,  8, 11025}, {2,  8, 11025}, {1, 16, 11025}, {2, 16, 11025},
78     {1,  8, 12000}, {2,  8, 12000}, {1, 16, 12000}, {2, 16, 12000},
79     {1,  8, 16000}, {2,  8, 16000}, {1, 16, 16000}, {2, 16, 16000},
80     {1,  8, 22050}, {2,  8, 22050}, {1, 16, 22050}, {2, 16, 22050},
81     {1,  8, 24000}, {2,  8, 24000}, {1, 16, 24000}, {2, 16, 24000},
82     {1,  8, 32000}, {2,  8, 32000}, {1, 16, 32000}, {2, 16, 32000},
83     {1,  8, 44100}, {2,  8, 44100}, {1, 16, 44100}, {2, 16, 44100},
84     {1,  8, 48000}, {2,  8, 48000}, {1, 16, 48000}, {2, 16, 48000}
85 };
86
87 static const Format MPEG3_Formats[] =
88 {
89     {1,  0,  8000}, {2,  0,  8000},
90     {1,  0, 11025}, {2,  0, 11025},
91     {1,  0, 12000}, {2,  0, 12000},
92     {1,  0, 16000}, {2,  0, 16000},
93     {1,  0, 22050}, {2,  0, 22050},
94     {1,  0, 24000}, {2,  0, 24000},
95     {1,  0, 32000}, {2,  0, 32000},
96     {1,  0, 44100}, {2,  0, 44100},
97     {1,  0, 48000}, {2,  0, 48000}
98 };
99
100 #define NUM_PCM_FORMATS         (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
101 #define NUM_MPEG3_FORMATS       (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))
102
103 /***********************************************************************
104  *           MPEG3_GetFormatIndex
105  */
106 static  DWORD   MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
107 {
108     int         i, hi;
109     const Format *fmts;
110
111     switch (wfx->wFormatTag)
112     {
113     case WAVE_FORMAT_PCM:
114         hi = NUM_PCM_FORMATS;
115         fmts = PCM_Formats;
116         break;
117     case WAVE_FORMAT_MPEGLAYER3:
118         hi = NUM_MPEG3_FORMATS;
119         fmts = MPEG3_Formats;
120         break;
121     default:
122         return 0xFFFFFFFF;
123     }
124
125     for (i = 0; i < hi; i++)
126     {
127         if (wfx->nChannels == fmts[i].nChannels &&
128             wfx->nSamplesPerSec == fmts[i].rate &&
129             (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
130             return i;
131     }
132
133     return 0xFFFFFFFF;
134 }
135
136 static DWORD get_num_buffered_bytes(struct mpstr *mp)
137 {
138     DWORD numBuff = 0;
139     struct buf * p = mp->tail;
140     while (p) {
141         numBuff += p->size - p->pos;
142         p = p->next;
143     }
144     return numBuff;
145 }
146
147 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
148                       const unsigned char* src, LPDWORD nsrc,
149                       unsigned char* dst, LPDWORD ndst)
150 {
151     AcmMpeg3Data*       amd = (AcmMpeg3Data*)adsi->dwDriver;
152     int                 size, ret;
153     DWORD               dpos = 0;
154     DWORD               buffered_before;
155     DWORD               buffered_during;
156     DWORD               buffered_after;
157
158     /* Skip leading ID v3 header */
159     if (amd->mp.fsizeold == -1 && !strncmp("ID3", (char*)src, 3))
160     {
161         UINT length = 10;
162         const char *header = (char *)src;
163
164         TRACE("Found ID3 v2.%d.%d\n", header[3], header[4]);
165         length += (header[6] & 0x7F) << 21;
166         length += (header[7] & 0x7F) << 14;
167         length += (header[8] & 0x7F) << 7;
168         length += (header[9] & 0x7F);
169         TRACE("Length: %u\n", length);
170         *nsrc = length;
171         *ndst = 0;
172         return;
173     }
174
175     buffered_before = get_num_buffered_bytes(&amd->mp);
176     ret = decodeMP3(&amd->mp, src, *nsrc, dst, *ndst, &size);
177     buffered_during = get_num_buffered_bytes(&amd->mp);
178     if (ret != MP3_OK)
179     {
180         if (ret == MP3_ERR)
181             FIXME("Error occurred during decoding!\n");
182         *ndst = *nsrc = 0;
183         return;
184     }
185     do {
186         dpos += size;
187         if (*ndst - dpos < 4608) break;
188         ret = decodeMP3(&amd->mp, NULL, 0,
189                         dst + dpos, *ndst - dpos, &size);
190     } while (ret == MP3_OK);
191     *ndst = dpos;
192
193     buffered_after = get_num_buffered_bytes(&amd->mp);
194     TRACE("before %d put %d during %d after %d\n", buffered_before, *nsrc, buffered_during, buffered_after);
195
196     *nsrc -= buffered_after;
197     ClearMP3Buffer(&amd->mp);
198 }
199
200 /***********************************************************************
201  *           MPEG3_DriverDetails
202  *
203  */
204 static  LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
205 {
206     add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
207     add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
208     add->wMid = 0xFF;
209     add->wPid = 0x00;
210     add->vdwACM = 0x01000000;
211     add->vdwDriver = 0x01000000;
212     add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
213     add->cFormatTags = 2; /* PCM, MPEG3 */
214     add->cFilterTags = 0;
215     add->hicon = NULL;
216     MultiByteToWideChar( CP_ACP, 0, "WINE-MPEG3", -1,
217                          add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
218     MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
219                          add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
220     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team (based on mpglib by Michael Hipp)...", -1,
221                          add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
222     MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
223                          add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
224     add->szFeatures[0] = 0;
225
226     return MMSYSERR_NOERROR;
227 }
228
229 /***********************************************************************
230  *           MPEG3_FormatTagDetails
231  *
232  */
233 static  LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
234 {
235     static const WCHAR szPcm[]={'P','C','M',0};
236     static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
237
238     switch (dwQuery)
239     {
240     case ACM_FORMATTAGDETAILSF_INDEX:
241         if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
242         break;
243     case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
244         if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
245         {
246             aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_MPEGLAYER3 is bigger than PCM */
247             break;
248         }
249         /* fall thru */
250     case ACM_FORMATTAGDETAILSF_FORMATTAG:
251         switch (aftd->dwFormatTag)
252         {
253         case WAVE_FORMAT_PCM:           aftd->dwFormatTagIndex = 0; break;
254         case WAVE_FORMAT_MPEGLAYER3:    aftd->dwFormatTagIndex = 1; break;
255         default:                        return ACMERR_NOTPOSSIBLE;
256         }
257         break;
258     default:
259         WARN("Unsupported query %08x\n", dwQuery);
260         return MMSYSERR_NOTSUPPORTED;
261     }
262
263     aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
264     switch (aftd->dwFormatTagIndex)
265     {
266     case 0:
267         aftd->dwFormatTag = WAVE_FORMAT_PCM;
268         aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
269         aftd->cStandardFormats = NUM_PCM_FORMATS;
270         lstrcpyW(aftd->szFormatTag, szPcm);
271         break;
272     case 1:
273         aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
274         aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
275         aftd->cStandardFormats = NUM_MPEG3_FORMATS;
276         lstrcpyW(aftd->szFormatTag, szMpeg3);
277         break;
278     }
279     return MMSYSERR_NOERROR;
280 }
281
282 static void fill_in_wfx(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
283 {
284     MPEGLAYER3WAVEFORMAT*   mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx;
285
286     wfx->nAvgBytesPerSec = bit_rate / 8;
287     if (cbwfx >= sizeof(WAVEFORMATEX))
288         wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
289     if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT))
290     {
291         mp3wfx->wID = MPEGLAYER3_ID_MPEG;
292         mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
293         mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec;
294         mp3wfx->nFramesPerBlock = 1;
295         mp3wfx->nCodecDelay = 0x0571;
296     }
297 }
298
299 /***********************************************************************
300  *           MPEG3_FormatDetails
301  *
302  */
303 static  LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
304 {
305     switch (dwQuery)
306     {
307     case ACM_FORMATDETAILSF_FORMAT:
308         if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
309         break;
310     case ACM_FORMATDETAILSF_INDEX:
311         afd->pwfx->wFormatTag = afd->dwFormatTag;
312         switch (afd->dwFormatTag)
313         {
314         case WAVE_FORMAT_PCM:
315             if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
316             afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
317             afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
318             afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
319             /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
320              * afd->pwfx->cbSize = 0;
321              */
322             afd->pwfx->nBlockAlign =
323                 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
324             afd->pwfx->nAvgBytesPerSec =
325                 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
326             break;
327         case WAVE_FORMAT_MPEGLAYER3:
328             if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE;
329             afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels;
330             afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate;
331             afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits;
332             afd->pwfx->nBlockAlign = 1;
333             fill_in_wfx(afd->cbwfx, afd->pwfx, 192000);
334             break;
335         default:
336             WARN("Unsupported tag %08x\n", afd->dwFormatTag);
337             return MMSYSERR_INVALPARAM;
338         }
339         break;
340     default:
341         WARN("Unsupported query %08x\n", dwQuery);
342         return MMSYSERR_NOTSUPPORTED;
343     }
344     afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
345     afd->szFormat[0] = 0; /* let MSACM format this for us... */
346
347     return MMSYSERR_NOERROR;
348 }
349
350 /***********************************************************************
351  *           MPEG3_FormatSuggest
352  *
353  */
354 static  LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
355 {
356     /* some tests ... */
357     if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
358         adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
359         MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
360     /* FIXME: should do those tests against the real size (according to format tag */
361
362     /* If no suggestion for destination, then copy source value */
363     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
364         adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
365     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
366         adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
367
368     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
369     {
370         if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
371             adfs->pwfxDst->wBitsPerSample = 4;
372         else
373             adfs->pwfxDst->wBitsPerSample = 16;
374     }
375     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
376     {
377         if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
378             adfs->pwfxDst->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
379         else
380             adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
381     }
382
383     /* check if result is ok */
384     if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
385
386     /* recompute other values */
387     switch (adfs->pwfxDst->wFormatTag)
388     {
389     case WAVE_FORMAT_PCM:
390         adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
391         adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
392         break;
393     case WAVE_FORMAT_MPEGLAYER3:
394         adfs->pwfxDst->nBlockAlign = 1;
395         fill_in_wfx(adfs->cbwfxDst, adfs->pwfxDst, 192000);
396         break;
397     default:
398         FIXME("\n");
399         break;
400     }
401
402     return MMSYSERR_NOERROR;
403 }
404
405 /***********************************************************************
406  *           MPEG3_Reset
407  *
408  */
409 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
410 {
411     ClearMP3Buffer(&aad->mp);
412     InitMP3(&aad->mp);
413 }
414
415 /***********************************************************************
416  *           MPEG3_StreamOpen
417  *
418  */
419 static  LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
420 {
421     AcmMpeg3Data*       aad;
422
423     assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
424
425     if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
426         MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
427         return ACMERR_NOTPOSSIBLE;
428
429     aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
430     if (aad == 0) return MMSYSERR_NOMEM;
431
432     adsi->dwDriver = (DWORD_PTR)aad;
433
434     if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
435         adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
436     {
437         goto theEnd;
438     }
439     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
440              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
441     {
442         /* resampling or mono <=> stereo not available
443          * MPEG3 algo only define 16 bit per sample output
444          */
445         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
446             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
447             adsi->pwfxDst->wBitsPerSample != 16)
448             goto theEnd;
449         aad->convert = mp3_horse;
450         InitMP3(&aad->mp);
451     }
452     /* no encoding yet
453     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
454              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
455     */
456     else goto theEnd;
457     MPEG3_Reset(adsi, aad);
458
459     return MMSYSERR_NOERROR;
460
461  theEnd:
462     HeapFree(GetProcessHeap(), 0, aad);
463     adsi->dwDriver = 0L;
464     return MMSYSERR_NOTSUPPORTED;
465 }
466
467 /***********************************************************************
468  *           MPEG3_StreamClose
469  *
470  */
471 static  LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
472 {
473     ClearMP3Buffer(&((AcmMpeg3Data*)adsi->dwDriver)->mp);
474     HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
475     return MMSYSERR_NOERROR;
476 }
477
478 /***********************************************************************
479  *           MPEG3_StreamSize
480  *
481  */
482 static  LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
483 {
484     DWORD nblocks;
485
486     switch (adss->fdwSize)
487     {
488     case ACM_STREAMSIZEF_DESTINATION:
489         /* cbDstLength => cbSrcLength */
490         if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
491             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
492         {
493             nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
494             if (nblocks == 0)
495                 return ACMERR_NOTPOSSIBLE;
496             adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
497         }
498         else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
499                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
500         {
501             nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
502             if (nblocks == 0)
503                 return ACMERR_NOTPOSSIBLE;
504             adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
505         }
506         else
507         {
508             return MMSYSERR_NOTSUPPORTED;
509         }
510         break;
511     case ACM_STREAMSIZEF_SOURCE:
512         /* cbSrcLength => cbDstLength */
513         if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
514             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
515         {
516             nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
517             if (nblocks == 0)
518                 return ACMERR_NOTPOSSIBLE;
519             if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
520                 /* Round block count up. */
521                 nblocks++;
522             adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
523         }
524         else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
525                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
526         {
527             nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
528             if (nblocks == 0)
529                 return ACMERR_NOTPOSSIBLE;
530             if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
531                 /* Round block count up. */
532                 nblocks++;
533             adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
534         }
535         else
536         {
537             return MMSYSERR_NOTSUPPORTED;
538         }
539         break;
540     default:
541         WARN("Unsupported query %08x\n", adss->fdwSize);
542         return MMSYSERR_NOTSUPPORTED;
543     }
544     return MMSYSERR_NOERROR;
545 }
546
547 /***********************************************************************
548  *           MPEG3_StreamConvert
549  *
550  */
551 static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
552 {
553     AcmMpeg3Data*       aad = (AcmMpeg3Data*)adsi->dwDriver;
554     DWORD               nsrc = adsh->cbSrcLength;
555     DWORD               ndst = adsh->cbDstLength;
556
557     if (adsh->fdwConvert &
558         ~(ACM_STREAMCONVERTF_BLOCKALIGN|
559           ACM_STREAMCONVERTF_END|
560           ACM_STREAMCONVERTF_START))
561     {
562         FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
563     }
564     /* ACM_STREAMCONVERTF_BLOCKALIGN
565      *  currently all conversions are block aligned, so do nothing for this flag
566      * ACM_STREAMCONVERTF_END
567      *  no pending data, so do nothing for this flag
568      */
569     if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
570     {
571         MPEG3_Reset(adsi, aad);
572     }
573
574     aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
575     adsh->cbSrcLengthUsed = nsrc;
576     adsh->cbDstLengthUsed = ndst;
577
578     return MMSYSERR_NOERROR;
579 }
580
581 /**************************************************************************
582  *                      MPEG3_DriverProc                        [exported]
583  */
584 LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
585                                          LPARAM dwParam1, LPARAM dwParam2)
586 {
587     TRACE("(%08lx %p %04x %08lx %08lx);\n",
588           dwDevID, hDriv, wMsg, dwParam1, dwParam2);
589
590     switch (wMsg)
591     {
592     case DRV_LOAD:              return 1;
593     case DRV_FREE:              return 1;
594     case DRV_OPEN:              return MPEG3_drvOpen((LPSTR)dwParam1);
595     case DRV_CLOSE:             return MPEG3_drvClose(dwDevID);
596     case DRV_ENABLE:            return 1;
597     case DRV_DISABLE:           return 1;
598     case DRV_QUERYCONFIGURE:    return 1;
599     case DRV_CONFIGURE:         MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
600     case DRV_INSTALL:           return DRVCNF_RESTART;
601     case DRV_REMOVE:            return DRVCNF_RESTART;
602
603     case ACMDM_DRIVER_NOTIFY:
604         /* no caching from other ACM drivers is done so far */
605         return MMSYSERR_NOERROR;
606
607     case ACMDM_DRIVER_DETAILS:
608         return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
609
610     case ACMDM_FORMATTAG_DETAILS:
611         return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
612
613     case ACMDM_FORMAT_DETAILS:
614         return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
615
616     case ACMDM_FORMAT_SUGGEST:
617         return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
618
619     case ACMDM_STREAM_OPEN:
620         return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
621
622     case ACMDM_STREAM_CLOSE:
623         return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
624
625     case ACMDM_STREAM_SIZE:
626         return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
627
628     case ACMDM_STREAM_CONVERT:
629         return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
630
631     case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
632     case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
633         /* this converter is not a hardware driver */
634     case ACMDM_FILTERTAG_DETAILS:
635     case ACMDM_FILTER_DETAILS:
636         /* this converter is not a filter */
637     case ACMDM_STREAM_RESET:
638         /* only needed for asynchronous driver... we aren't, so just say it */
639         return MMSYSERR_NOTSUPPORTED;
640     case ACMDM_STREAM_PREPARE:
641     case ACMDM_STREAM_UNPREPARE:
642         /* nothing special to do here... so don't do anything */
643         return MMSYSERR_NOERROR;
644
645     default:
646         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
647     }
648 }