include: Make sure __int64 is correctly defined on PPC64.
[wine.git] / dlls / l3codeca.acm / mpegl3.c
blob2e929371ae8b9d5ff6b931894aa9268f99b4f2dc
1 /*
2 * MPEG Layer 3 handling
4 * Copyright (C) 2002 Eric Pouech
5 * Copyright (C) 2009 CodeWeavers, Aric Stewart
6 * Copyright (C) 2010 Kristofer Henriksson
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <string.h>
31 #ifdef HAVE_MPG123_H
32 # include <mpg123.h>
33 #else
34 # ifdef HAVE_COREAUDIO_COREAUDIO_H
35 # include <CoreFoundation/CoreFoundation.h>
36 # include <CoreAudio/CoreAudio.h>
37 # endif
38 # ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
39 # include <AudioToolbox/AudioConverter.h>
40 # endif
41 #endif
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "winuser.h"
47 #include "winnls.h"
48 #include "mmsystem.h"
49 #include "mmreg.h"
50 #include "msacm.h"
51 #include "msacmdrv.h"
52 #include "wine/debug.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);
56 /* table to list all supported formats... those are the basic ones. this
57 * also helps given a unique index to each of the supported formats
59 typedef struct
61 int nChannels;
62 int nBits;
63 int rate;
64 } Format;
66 static const Format PCM_Formats[] =
68 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
69 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
70 {1, 8, 12000}, {2, 8, 12000}, {1, 16, 12000}, {2, 16, 12000},
71 {1, 8, 16000}, {2, 8, 16000}, {1, 16, 16000}, {2, 16, 16000},
72 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
73 {1, 8, 24000}, {2, 8, 24000}, {1, 16, 24000}, {2, 16, 24000},
74 {1, 8, 32000}, {2, 8, 32000}, {1, 16, 32000}, {2, 16, 32000},
75 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
76 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}
79 static const Format MPEG3_Formats[] =
81 {1, 0, 8000}, {2, 0, 8000},
82 {1, 0, 11025}, {2, 0, 11025},
83 {1, 0, 12000}, {2, 0, 12000},
84 {1, 0, 16000}, {2, 0, 16000},
85 {1, 0, 22050}, {2, 0, 22050},
86 {1, 0, 24000}, {2, 0, 24000},
87 {1, 0, 32000}, {2, 0, 32000},
88 {1, 0, 44100}, {2, 0, 44100},
89 {1, 0, 48000}, {2, 0, 48000}
92 /***********************************************************************
93 * MPEG3_GetFormatIndex
95 static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
97 int i, hi;
98 const Format *fmts;
100 switch (wfx->wFormatTag)
102 case WAVE_FORMAT_PCM:
103 hi = ARRAY_SIZE(PCM_Formats);
104 fmts = PCM_Formats;
105 break;
106 case WAVE_FORMAT_MPEG:
107 case WAVE_FORMAT_MPEGLAYER3:
108 hi = ARRAY_SIZE(MPEG3_Formats);
109 fmts = MPEG3_Formats;
110 break;
111 default:
112 return 0xFFFFFFFF;
115 for (i = 0; i < hi; i++)
117 if (wfx->nChannels == fmts[i].nChannels &&
118 wfx->nSamplesPerSec == fmts[i].rate &&
119 (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
120 return i;
123 return 0xFFFFFFFF;
126 #ifdef HAVE_MPG123_H
128 typedef struct tagAcmMpeg3Data
130 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
131 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
132 mpg123_handle *mh;
133 } AcmMpeg3Data;
135 /***********************************************************************
136 * MPEG3_drvOpen
138 static LRESULT MPEG3_drvOpen(LPCSTR str)
140 mpg123_init();
141 return 1;
144 /***********************************************************************
145 * MPEG3_drvClose
147 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
149 mpg123_exit();
150 return 1;
154 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
155 const unsigned char* src, LPDWORD nsrc,
156 unsigned char* dst, LPDWORD ndst)
158 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
159 int ret;
160 size_t size;
161 DWORD dpos = 0;
164 if (*nsrc > 0)
166 ret = mpg123_feed(amd->mh, src, *nsrc);
167 if (ret != MPG123_OK)
169 ERR("Error feeding data\n");
170 *ndst = *nsrc = 0;
171 return;
175 do {
176 size = 0;
177 ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
178 if (ret == MPG123_ERR)
180 FIXME("Error occurred during decoding!\n");
181 *ndst = *nsrc = 0;
182 return;
185 if (ret == MPG123_NEW_FORMAT)
187 long rate;
188 int channels, enc;
189 mpg123_getformat(amd->mh, &rate, &channels, &enc);
190 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
192 dpos += size;
193 if (dpos >= *ndst) break;
194 } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
195 *ndst = dpos;
198 /***********************************************************************
199 * MPEG3_Reset
202 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
204 mpg123_feedseek(aad->mh, 0, SEEK_SET, NULL);
205 mpg123_close(aad->mh);
206 mpg123_open_feed(aad->mh);
209 /***********************************************************************
210 * MPEG3_StreamOpen
213 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
215 LRESULT error = MMSYSERR_NOTSUPPORTED;
216 AcmMpeg3Data* aad;
217 int err;
219 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
221 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
222 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
223 return ACMERR_NOTPOSSIBLE;
225 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
226 if (aad == 0) return MMSYSERR_NOMEM;
228 adsi->dwDriver = (DWORD_PTR)aad;
230 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
231 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
233 goto theEnd;
235 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
236 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
237 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
239 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
241 MPEGLAYER3WAVEFORMAT *formatmp3 = (MPEGLAYER3WAVEFORMAT *)adsi->pwfxSrc;
243 if (adsi->pwfxSrc->cbSize < MPEGLAYER3_WFX_EXTRA_BYTES ||
244 formatmp3->wID != MPEGLAYER3_ID_MPEG)
246 error = ACMERR_NOTPOSSIBLE;
247 goto theEnd;
251 /* resampling or mono <=> stereo not available
252 * MPEG3 algo only define 16 bit per sample output
254 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
255 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
256 adsi->pwfxDst->wBitsPerSample != 16)
257 goto theEnd;
258 aad->convert = mp3_horse;
259 aad->mh = mpg123_new(NULL,&err);
260 mpg123_open_feed(aad->mh);
262 #if MPG123_API_VERSION >= 31 /* needed for MPG123_IGNORE_FRAMEINFO enum value */
263 /* mpg123 may find a XING header in the mp3 and use that information
264 * to ask for seeks in order to read specific frames in the file.
265 * We cannot allow that since the caller application is feeding us.
266 * This fixes problems for mp3 files encoded with LAME (bug 42361)
268 mpg123_param(aad->mh, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0);
269 #endif
271 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
272 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
273 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
275 WARN("Encoding to MPEG is not supported\n");
276 goto theEnd;
278 else goto theEnd;
279 MPEG3_Reset(adsi, aad);
281 return MMSYSERR_NOERROR;
283 theEnd:
284 HeapFree(GetProcessHeap(), 0, aad);
285 adsi->dwDriver = 0L;
286 return error;
289 /***********************************************************************
290 * MPEG3_StreamClose
293 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
295 mpg123_close(((AcmMpeg3Data*)adsi->dwDriver)->mh);
296 mpg123_delete(((AcmMpeg3Data*)adsi->dwDriver)->mh);
297 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
298 return MMSYSERR_NOERROR;
301 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
303 static const unsigned short Mp3BitRates[2][16] =
305 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
306 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
309 static const unsigned short Mp3SampleRates[2][4] =
311 {44100, 48000, 32000, 0},
312 {22050, 24000, 16000, 0}
315 typedef struct tagAcmMpeg3Data
317 LRESULT (*convert)(PACMDRVSTREAMINSTANCE adsi, unsigned char*,
318 LPDWORD, unsigned char*, LPDWORD);
319 AudioConverterRef acr;
320 AudioStreamBasicDescription in,out;
322 AudioBufferList outBuffer;
323 AudioBuffer inBuffer;
325 SInt32 tagBytesLeft;
327 UInt32 NumberPackets;
328 AudioStreamPacketDescription *PacketDescriptions;
329 } AcmMpeg3Data;
331 /***********************************************************************
332 * MPEG3_drvOpen
334 static LRESULT MPEG3_drvOpen(LPCSTR str)
336 return 1;
339 /***********************************************************************
340 * MPEG3_drvClose
342 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
344 return 1;
348 When it asks for data, give it all we have. If we have no data, we assume
349 we will in the future, so give it no packets and return an error, which
350 signals that we will have more later.
352 static OSStatus Mp3AudioConverterComplexInputDataProc(
353 AudioConverterRef inAudioConverter,
354 UInt32 *ioNumberDataPackets,
355 AudioBufferList *ioData,
356 AudioStreamPacketDescription **outDataPacketDescription,
357 void *inUserData
360 AcmMpeg3Data *amd = (AcmMpeg3Data*)inUserData;
362 if (amd->inBuffer.mDataByteSize > 0)
364 *ioNumberDataPackets = amd->NumberPackets;
365 ioData->mNumberBuffers = 1;
366 ioData->mBuffers[0] = amd->inBuffer;
367 amd->inBuffer.mDataByteSize = 0;
368 if (outDataPacketDescription)
369 *outDataPacketDescription = amd->PacketDescriptions;
370 return noErr;
372 else
374 *ioNumberDataPackets = 0;
375 return -74;
380 Get the length of the current frame. We need to be at the start of a
381 frame now. The buffer must have at least the four bytes for the header.
383 static SInt32 Mp3GetPacketLength(const unsigned char* src)
385 unsigned char mpegv;
386 unsigned short brate, srate;
387 unsigned int size;
390 Check that our position looks like an MP3 header and see which type
391 of MP3 file we have.
393 if (src[0] == 0xff && src[1] >> 1 == 0x7d) mpegv = 0; /* MPEG-1 File */
394 else if (src[0] == 0xff && src[1] >> 1 == 0x79) mpegv = 1; /* MPEG-2 File */
395 else return -1;
397 /* Fill in bit rate and sample rate. */
398 brate = Mp3BitRates[mpegv][(src[2] & 0xf0) >> 4];
399 srate = Mp3SampleRates[mpegv][(src[2] & 0xc) >> 2];
401 /* Certain values for bit rate and sample rate are invalid. */
402 if (brate == 0 || srate == 0) return -1;
404 /* Compute frame size, round down */
405 size = 72 * (2 - mpegv) * brate * 1000 / srate;
407 /* If there is padding, add one byte */
408 if (src[2] & 0x2) return size + 1;
409 else return size;
413 Apple's AudioFileStream does weird things so we deal with parsing the
414 file ourselves. It was also designed for a different use case, so this
415 is not unexpected. We expect to have MP3 data as input (i.e. we can only
416 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
417 understand the ID3v2 header and skip over it. Whenever we have data we
418 want to skip at the beginning of the input, we do this by setting *ndst=0
419 and *nsrc to the length of the unwanted data and return no error.
421 static LRESULT mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi,
422 unsigned char* src, LPDWORD nsrc,
423 unsigned char* dst, LPDWORD ndst)
425 OSStatus err;
426 UInt32 size, aspdi, synci, syncSkip;
427 short framelen[4];
428 const unsigned char* psrc;
429 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
431 TRACE("ndst %u %p <- %u %p\n", *ndst, dst, *nsrc, src);
433 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an((const char *)src, 16));
435 /* Parse ID3 tag */
436 if (!memcmp(src, "ID3", 3) && amd->tagBytesLeft == -1)
438 amd->tagBytesLeft = (src[6] << 21) + (src[7] << 14) + (src[8] << 7) + src[9];
439 if (src[5] & 0x10) amd->tagBytesLeft += 20; /* There is a footer */
440 else amd->tagBytesLeft += 10;
443 /* Consume the tag */
444 if (amd->tagBytesLeft >= (SInt32)*nsrc)
446 *ndst = 0;
447 amd->tagBytesLeft -= *nsrc;
449 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc);
450 return MMSYSERR_NOERROR;
452 else if (amd->tagBytesLeft > 0)
454 src += amd->tagBytesLeft;
455 *nsrc -= amd->tagBytesLeft;
456 TRACE("Skipping %ld for ID3 tag\n", amd->tagBytesLeft);
460 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
461 Thus, in the first 1440 bytes we must find the beginning of 3 valid
462 frames in a row unless we reach the end of the file first.
464 syncSkip = 0;
465 for (psrc = src; psrc <= src + *nsrc - 4 && psrc < src + 1440; psrc++)
467 framelen[0] = 0;
468 for (synci = 1;
469 synci < 4 && psrc + framelen[synci-1] < src + *nsrc - 4;
470 synci++)
472 framelen[synci] = Mp3GetPacketLength(psrc + framelen[synci-1]);
473 if (framelen[synci] == -1)
475 synci = 0;
476 break;
478 framelen[synci] += framelen[synci-1];
480 if (synci > 0) /* We synced successfully */
482 if (psrc - src > 0)
484 syncSkip = psrc - src;
485 src += syncSkip;
486 *nsrc -= syncSkip;
487 TRACE("Skipping %ld for frame sync\n", syncSkip);
489 break;
493 if (Mp3GetPacketLength(src) == -1)
495 *ndst = *nsrc = 0;
496 ERR("Frame sync failed. Cannot play file.\n");
497 return MMSYSERR_ERROR;
501 Fill in frame descriptions for all frames. We use an extra pointer
502 to keep track of our position in the input.
505 amd->NumberPackets = 25; /* This is the initial array capacity */
506 amd->PacketDescriptions = HeapAlloc(GetProcessHeap(), 0, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
507 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
509 for (aspdi = 0, psrc = src;
510 psrc <= src + *nsrc - 4;
511 psrc += amd->PacketDescriptions[aspdi].mDataByteSize, aspdi++)
513 /* Return an error if we can't read the frame header */
514 if (Mp3GetPacketLength(psrc) == -1)
516 *ndst = *nsrc = 0;
517 ERR("Invalid header at %p.\n", psrc);
518 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
519 return MMSYSERR_ERROR;
522 /* If we run out of space, double size and reallocate */
523 if (aspdi >= amd->NumberPackets)
525 amd->NumberPackets *= 2;
526 amd->PacketDescriptions = HeapReAlloc(GetProcessHeap(), 0, amd->PacketDescriptions, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
527 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
530 /* Fill in packet data */
531 amd->PacketDescriptions[aspdi].mStartOffset = psrc - src;
532 amd->PacketDescriptions[aspdi].mVariableFramesInPacket = 0;
533 amd->PacketDescriptions[aspdi].mDataByteSize = Mp3GetPacketLength(psrc);
535 /* If this brings us past the end, the last one doesn't count */
536 if (psrc + amd->PacketDescriptions[aspdi].mDataByteSize > src + *nsrc) break;
539 /* Fill in correct number of frames */
540 amd->NumberPackets = aspdi;
542 /* Adjust nsrc to only include full frames */
543 *nsrc = psrc - src;
545 amd->inBuffer.mDataByteSize = *nsrc;
546 amd->inBuffer.mData = src;
547 amd->inBuffer.mNumberChannels = amd->in.mChannelsPerFrame;
549 amd->outBuffer.mNumberBuffers = 1;
550 amd->outBuffer.mBuffers[0].mDataByteSize = *ndst;
551 amd->outBuffer.mBuffers[0].mData = dst;
552 amd->outBuffer.mBuffers[0].mNumberChannels = amd->out.mChannelsPerFrame;
554 /* Convert the data */
555 size = amd->outBuffer.mBuffers[0].mDataByteSize / amd->out.mBytesPerPacket;
556 err = AudioConverterFillComplexBuffer(amd->acr, Mp3AudioConverterComplexInputDataProc, amd, &size, &amd->outBuffer, 0);
558 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
560 /* Add skipped bytes back into *nsrc */
561 if (amd->tagBytesLeft > 0)
563 *nsrc += amd->tagBytesLeft;
564 amd->tagBytesLeft = 0;
566 *nsrc += syncSkip;
568 if (err != noErr && err != -74)
570 *ndst = *nsrc = 0;
571 ERR("Feed Error: %ld\n", err);
572 return MMSYSERR_ERROR;
575 *ndst = amd->outBuffer.mBuffers[0].mDataByteSize;
577 TRACE("convert %d -> %d\n", *nsrc, *ndst);
579 return MMSYSERR_NOERROR;
582 /***********************************************************************
583 * MPEG3_Reset
586 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
588 AudioConverterReset(aad->acr);
591 /***********************************************************************
592 * MPEG3_StreamOpen
595 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
597 AcmMpeg3Data* aad;
599 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
601 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
602 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
603 return ACMERR_NOTPOSSIBLE;
605 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
606 if (aad == 0) return MMSYSERR_NOMEM;
608 adsi->dwDriver = (DWORD_PTR)aad;
610 if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
611 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
612 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
614 OSStatus err;
616 aad->in.mSampleRate = adsi->pwfxSrc->nSamplesPerSec;
617 aad->out.mSampleRate = adsi->pwfxDst->nSamplesPerSec;
618 aad->in.mBitsPerChannel = adsi->pwfxSrc->wBitsPerSample;
619 aad->out.mBitsPerChannel = adsi->pwfxDst->wBitsPerSample;
620 aad->in.mFormatID = kAudioFormatMPEGLayer3;
621 aad->out.mFormatID = kAudioFormatLinearPCM;
622 aad->in.mChannelsPerFrame = adsi->pwfxSrc->nChannels;
623 aad->out.mChannelsPerFrame = adsi->pwfxDst->nChannels;
624 aad->in.mFormatFlags = 0;
625 aad->out.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
626 aad->in.mBytesPerFrame = 0;
627 aad->out.mBytesPerFrame = (aad->out.mBitsPerChannel * aad->out.mChannelsPerFrame) / 8;
628 aad->in.mBytesPerPacket = 0;
629 aad->out.mBytesPerPacket = aad->out.mBytesPerFrame;
630 aad->in.mFramesPerPacket = 0;
631 aad->out.mFramesPerPacket = 1;
632 aad->in.mReserved = aad->out.mReserved = 0;
634 aad->tagBytesLeft = -1;
636 aad->convert = mp3_leopard_horse;
638 err = AudioConverterNew(&aad->in, &aad->out, &aad->acr);
639 if (err != noErr)
641 ERR("Create failed: %ld\n", err);
643 else
645 MPEG3_Reset(adsi, aad);
647 return MMSYSERR_NOERROR;
651 HeapFree(GetProcessHeap(), 0, aad);
652 adsi->dwDriver = 0;
654 return MMSYSERR_NOTSUPPORTED;
657 /***********************************************************************
658 * MPEG3_StreamClose
661 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
663 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
665 AudioConverterDispose(amd->acr);
667 HeapFree(GetProcessHeap(), 0, amd);
668 adsi->dwDriver = 0;
670 return MMSYSERR_NOERROR;
673 #endif
675 /***********************************************************************
676 * MPEG3_DriverDetails
679 static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
681 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
682 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
683 add->wMid = MM_FRAUNHOFER_IIS;
684 add->wPid = MM_FHGIIS_MPEGLAYER3_DECODE;
685 add->vdwACM = 0x01000000;
686 add->vdwDriver = 0x01000000;
687 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
688 add->cFormatTags = 3; /* PCM, MPEG3 */
689 add->cFilterTags = 0;
690 add->hicon = NULL;
691 MultiByteToWideChar( CP_ACP, 0, "MPEG Layer-3 Codec", -1,
692 add->szShortName, ARRAY_SIZE( add->szShortName ));
693 MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
694 add->szLongName, ARRAY_SIZE( add->szLongName ));
695 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
696 add->szCopyright, ARRAY_SIZE( add->szCopyright ));
697 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
698 add->szLicensing, ARRAY_SIZE( add->szLicensing ));
699 add->szFeatures[0] = 0;
701 return MMSYSERR_NOERROR;
704 /***********************************************************************
705 * MPEG3_FormatTagDetails
708 static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
710 static const WCHAR szPcm[]={'P','C','M',0};
711 static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
712 static const WCHAR szMpeg[]={'M','P','e','g',0};
714 switch (dwQuery)
716 case ACM_FORMATTAGDETAILSF_INDEX:
717 if (aftd->dwFormatTagIndex > 2) return ACMERR_NOTPOSSIBLE;
718 break;
719 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
720 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
722 aftd->dwFormatTagIndex = 2; /* WAVE_FORMAT_MPEG is biggest */
723 break;
725 /* fall through */
726 case ACM_FORMATTAGDETAILSF_FORMATTAG:
727 switch (aftd->dwFormatTag)
729 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
730 case WAVE_FORMAT_MPEGLAYER3: aftd->dwFormatTagIndex = 1; break;
731 case WAVE_FORMAT_MPEG: aftd->dwFormatTagIndex = 2; break;
732 default: return ACMERR_NOTPOSSIBLE;
734 break;
735 default:
736 WARN("Unsupported query %08x\n", dwQuery);
737 return MMSYSERR_NOTSUPPORTED;
740 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
741 switch (aftd->dwFormatTagIndex)
743 case 0:
744 aftd->dwFormatTag = WAVE_FORMAT_PCM;
745 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
746 aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
747 lstrcpyW(aftd->szFormatTag, szPcm);
748 break;
749 case 1:
750 aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
751 aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
752 aftd->cStandardFormats = 0;
753 lstrcpyW(aftd->szFormatTag, szMpeg3);
754 break;
755 case 2:
756 aftd->dwFormatTag = WAVE_FORMAT_MPEG;
757 aftd->cbFormatSize = sizeof(MPEG1WAVEFORMAT);
758 aftd->cStandardFormats = 0;
759 lstrcpyW(aftd->szFormatTag, szMpeg);
760 break;
762 return MMSYSERR_NOERROR;
765 /***********************************************************************
766 * MPEG3_FormatDetails
769 static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
771 switch (dwQuery)
773 case ACM_FORMATDETAILSF_FORMAT:
774 if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
775 break;
776 case ACM_FORMATDETAILSF_INDEX:
777 afd->pwfx->wFormatTag = afd->dwFormatTag;
778 switch (afd->dwFormatTag)
780 case WAVE_FORMAT_PCM:
781 if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE;
782 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
783 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
784 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
785 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
786 * afd->pwfx->cbSize = 0;
788 afd->pwfx->nBlockAlign =
789 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
790 afd->pwfx->nAvgBytesPerSec =
791 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
792 break;
793 case WAVE_FORMAT_MPEGLAYER3:
794 case WAVE_FORMAT_MPEG:
795 WARN("Encoding to MPEG is not supported\n");
796 return ACMERR_NOTPOSSIBLE;
797 default:
798 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
799 return MMSYSERR_INVALPARAM;
801 break;
802 default:
803 WARN("Unsupported query %08x\n", dwQuery);
804 return MMSYSERR_NOTSUPPORTED;
806 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
807 afd->szFormat[0] = 0; /* let MSACM format this for us... */
809 return MMSYSERR_NOERROR;
812 /***********************************************************************
813 * MPEG3_FormatSuggest
816 static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
818 /* some tests ... */
819 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
820 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
821 MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
822 /* FIXME: should do those tests against the real size (according to format tag */
824 /* If no suggestion for destination, then copy source value */
825 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
826 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
827 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
828 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
829 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
830 adfs->pwfxDst->wBitsPerSample = 16;
831 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
833 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
835 WARN("Encoding to MPEG is not supported\n");
836 return ACMERR_NOTPOSSIBLE;
838 else
839 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
842 /* check if result is ok */
843 if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
845 /* recompute other values */
846 switch (adfs->pwfxDst->wFormatTag)
848 case WAVE_FORMAT_PCM:
849 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
850 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
851 break;
852 case WAVE_FORMAT_MPEG:
853 case WAVE_FORMAT_MPEGLAYER3:
854 WARN("Encoding to MPEG is not supported\n");
855 return ACMERR_NOTPOSSIBLE;
856 break;
857 default:
858 FIXME("\n");
859 break;
862 return MMSYSERR_NOERROR;
865 /***********************************************************************
866 * MPEG3_StreamSize
869 static LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
871 DWORD nblocks;
873 switch (adss->fdwSize)
875 case ACM_STREAMSIZEF_DESTINATION:
876 /* cbDstLength => cbSrcLength */
877 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
878 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
879 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
881 nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
882 if (nblocks == 0)
883 return ACMERR_NOTPOSSIBLE;
884 adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
886 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
887 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
888 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
890 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
891 if (nblocks == 0)
892 return ACMERR_NOTPOSSIBLE;
893 adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
895 else
897 return MMSYSERR_NOTSUPPORTED;
899 break;
900 case ACM_STREAMSIZEF_SOURCE:
901 /* cbSrcLength => cbDstLength */
902 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
903 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
904 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
906 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
907 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
908 /* Round block count up. */
909 nblocks++;
910 if (nblocks == 0)
911 return ACMERR_NOTPOSSIBLE;
912 adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
914 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
915 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
916 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
918 nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
919 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
920 /* Round block count up. */
921 nblocks++;
922 if (nblocks == 0)
923 return ACMERR_NOTPOSSIBLE;
924 adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
926 else
928 return MMSYSERR_NOTSUPPORTED;
930 break;
931 default:
932 WARN("Unsupported query %08x\n", adss->fdwSize);
933 return MMSYSERR_NOTSUPPORTED;
935 return MMSYSERR_NOERROR;
938 /***********************************************************************
939 * MPEG3_StreamConvert
942 static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
944 AcmMpeg3Data* aad = (AcmMpeg3Data*)adsi->dwDriver;
945 DWORD nsrc = adsh->cbSrcLength;
946 DWORD ndst = adsh->cbDstLength;
948 if (adsh->fdwConvert &
949 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
950 ACM_STREAMCONVERTF_END|
951 ACM_STREAMCONVERTF_START))
953 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
955 /* ACM_STREAMCONVERTF_BLOCKALIGN
956 * currently all conversions are block aligned, so do nothing for this flag
957 * ACM_STREAMCONVERTF_END
958 * no pending data, so do nothing for this flag
960 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
962 MPEG3_Reset(adsi, aad);
965 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
966 adsh->cbSrcLengthUsed = nsrc;
967 adsh->cbDstLengthUsed = ndst;
969 return MMSYSERR_NOERROR;
972 /**************************************************************************
973 * MPEG3_DriverProc [exported]
975 LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
976 LPARAM dwParam1, LPARAM dwParam2)
978 TRACE("(%08lx %p %04x %08lx %08lx);\n",
979 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
981 switch (wMsg)
983 case DRV_LOAD: return 1;
984 case DRV_FREE: return 1;
985 case DRV_OPEN: return MPEG3_drvOpen((LPSTR)dwParam1);
986 case DRV_CLOSE: return MPEG3_drvClose(dwDevID);
987 case DRV_ENABLE: return 1;
988 case DRV_DISABLE: return 1;
989 case DRV_QUERYCONFIGURE: return 1;
990 case DRV_CONFIGURE: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
991 case DRV_INSTALL: return DRVCNF_RESTART;
992 case DRV_REMOVE: return DRVCNF_RESTART;
994 case ACMDM_DRIVER_NOTIFY:
995 /* no caching from other ACM drivers is done so far */
996 return MMSYSERR_NOERROR;
998 case ACMDM_DRIVER_DETAILS:
999 return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1001 case ACMDM_FORMATTAG_DETAILS:
1002 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1004 case ACMDM_FORMAT_DETAILS:
1005 return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1007 case ACMDM_FORMAT_SUGGEST:
1008 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1010 case ACMDM_STREAM_OPEN:
1011 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1013 case ACMDM_STREAM_CLOSE:
1014 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1016 case ACMDM_STREAM_SIZE:
1017 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1019 case ACMDM_STREAM_CONVERT:
1020 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1022 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1023 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1024 /* this converter is not a hardware driver */
1025 case ACMDM_FILTERTAG_DETAILS:
1026 case ACMDM_FILTER_DETAILS:
1027 /* this converter is not a filter */
1028 case ACMDM_STREAM_RESET:
1029 /* only needed for asynchronous driver... we aren't, so just say it */
1030 return MMSYSERR_NOTSUPPORTED;
1031 case ACMDM_STREAM_PREPARE:
1032 case ACMDM_STREAM_UNPREPARE:
1033 /* nothing special to do here... so don't do anything */
1034 return MMSYSERR_NOERROR;
1036 default:
1037 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);