mshtml: Use get_elem_attr_value helper in npplugin.c.
[wine.git] / dlls / winemp3.acm / mpegl3.c
blob57193b3d6f7f01ee4fbb74e58703f3def7005789
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 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
93 #define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))
95 /***********************************************************************
96 * MPEG3_GetFormatIndex
98 static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
100 int i, hi;
101 const Format *fmts;
103 switch (wfx->wFormatTag)
105 case WAVE_FORMAT_PCM:
106 hi = NUM_PCM_FORMATS;
107 fmts = PCM_Formats;
108 break;
109 case WAVE_FORMAT_MPEG:
110 case WAVE_FORMAT_MPEGLAYER3:
111 hi = NUM_MPEG3_FORMATS;
112 fmts = MPEG3_Formats;
113 break;
114 default:
115 return 0xFFFFFFFF;
118 for (i = 0; i < hi; i++)
120 if (wfx->nChannels == fmts[i].nChannels &&
121 wfx->nSamplesPerSec == fmts[i].rate &&
122 (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
123 return i;
126 return 0xFFFFFFFF;
129 #ifdef HAVE_MPG123_H
131 typedef struct tagAcmMpeg3Data
133 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
134 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
135 mpg123_handle *mh;
136 } AcmMpeg3Data;
138 /***********************************************************************
139 * MPEG3_drvOpen
141 static LRESULT MPEG3_drvOpen(LPCSTR str)
143 mpg123_init();
144 return 1;
147 /***********************************************************************
148 * MPEG3_drvClose
150 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
152 mpg123_exit();
153 return 1;
157 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
158 const unsigned char* src, LPDWORD nsrc,
159 unsigned char* dst, LPDWORD ndst)
161 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
162 int ret;
163 size_t size;
164 DWORD dpos = 0;
167 if (*nsrc > 0)
169 ret = mpg123_feed(amd->mh, src, *nsrc);
170 if (ret != MPG123_OK)
172 ERR("Error feeding data\n");
173 *ndst = *nsrc = 0;
174 return;
178 do {
179 size = 0;
180 ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
181 if (ret == MPG123_ERR)
183 FIXME("Error occurred during decoding!\n");
184 *ndst = *nsrc = 0;
185 return;
188 if (ret == MPG123_NEW_FORMAT)
190 long rate;
191 int channels, enc;
192 mpg123_getformat(amd->mh, &rate, &channels, &enc);
193 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
195 dpos += size;
196 if (dpos >= *ndst) break;
197 } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
198 *ndst = dpos;
201 /***********************************************************************
202 * MPEG3_Reset
205 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
207 mpg123_feedseek(aad->mh, 0, SEEK_SET, NULL);
208 mpg123_close(aad->mh);
209 mpg123_open_feed(aad->mh);
212 /***********************************************************************
213 * MPEG3_StreamOpen
216 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
218 AcmMpeg3Data* aad;
219 int err;
221 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
223 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
224 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
225 return ACMERR_NOTPOSSIBLE;
227 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
228 if (aad == 0) return MMSYSERR_NOMEM;
230 adsi->dwDriver = (DWORD_PTR)aad;
232 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
233 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
235 goto theEnd;
237 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
238 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
239 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
241 /* resampling or mono <=> stereo not available
242 * MPEG3 algo only define 16 bit per sample output
244 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
245 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
246 adsi->pwfxDst->wBitsPerSample != 16)
247 goto theEnd;
248 aad->convert = mp3_horse;
249 aad->mh = mpg123_new(NULL,&err);
250 mpg123_open_feed(aad->mh);
252 /* no encoding yet
253 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
254 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
256 else goto theEnd;
257 MPEG3_Reset(adsi, aad);
259 return MMSYSERR_NOERROR;
261 theEnd:
262 HeapFree(GetProcessHeap(), 0, aad);
263 adsi->dwDriver = 0L;
264 return MMSYSERR_NOTSUPPORTED;
267 /***********************************************************************
268 * MPEG3_StreamClose
271 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
273 mpg123_close(((AcmMpeg3Data*)adsi->dwDriver)->mh);
274 mpg123_delete(((AcmMpeg3Data*)adsi->dwDriver)->mh);
275 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
276 return MMSYSERR_NOERROR;
279 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
281 static const unsigned short Mp3BitRates[2][16] =
283 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
284 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
287 static const unsigned short Mp3SampleRates[2][4] =
289 {44100, 48000, 32000, 0},
290 {22050, 24000, 16000, 0}
293 typedef struct tagAcmMpeg3Data
295 LRESULT (*convert)(PACMDRVSTREAMINSTANCE adsi, unsigned char*,
296 LPDWORD, unsigned char*, LPDWORD);
297 AudioConverterRef acr;
298 AudioStreamBasicDescription in,out;
300 AudioBufferList outBuffer;
301 AudioBuffer inBuffer;
303 SInt32 tagBytesLeft;
305 UInt32 NumberPackets;
306 AudioStreamPacketDescription *PacketDescriptions;
307 } AcmMpeg3Data;
309 /***********************************************************************
310 * MPEG3_drvOpen
312 static LRESULT MPEG3_drvOpen(LPCSTR str)
314 return 1;
317 /***********************************************************************
318 * MPEG3_drvClose
320 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
322 return 1;
326 When it asks for data, give it all we have. If we have no data, we assume
327 we will in the future, so give it no packets and return an error, which
328 signals that we will have more later.
330 static OSStatus Mp3AudioConverterComplexInputDataProc(
331 AudioConverterRef inAudioConverter,
332 UInt32 *ioNumberDataPackets,
333 AudioBufferList *ioData,
334 AudioStreamPacketDescription **outDataPacketDescription,
335 void *inUserData
338 AcmMpeg3Data *amd = (AcmMpeg3Data*)inUserData;
340 if (amd->inBuffer.mDataByteSize > 0)
342 *ioNumberDataPackets = amd->NumberPackets;
343 ioData->mNumberBuffers = 1;
344 ioData->mBuffers[0] = amd->inBuffer;
345 amd->inBuffer.mDataByteSize = 0;
346 if (outDataPacketDescription)
347 *outDataPacketDescription = amd->PacketDescriptions;
348 return noErr;
350 else
352 *ioNumberDataPackets = 0;
353 return -74;
358 Get the length of the current frame. We need to be at the start of a
359 frame now. The buffer must have at least the four bytes for the header.
361 static SInt32 Mp3GetPacketLength(const unsigned char* src)
363 unsigned char mpegv;
364 unsigned short brate, srate;
365 unsigned int size;
368 Check that our position looks like an MP3 header and see which type
369 of MP3 file we have.
371 if (src[0] == 0xff && src[1] >> 1 == 0x7d) mpegv = 0; /* MPEG-1 File */
372 else if (src[0] == 0xff && src[1] >> 1 == 0x79) mpegv = 1; /* MPEG-2 File */
373 else return -1;
375 /* Fill in bit rate and sample rate. */
376 brate = Mp3BitRates[mpegv][(src[2] & 0xf0) >> 4];
377 srate = Mp3SampleRates[mpegv][(src[2] & 0xc) >> 2];
379 /* Certain values for bit rate and sample rate are invalid. */
380 if (brate == 0 || srate == 0) return -1;
382 /* Compute frame size, round down */
383 size = 72 * (2 - mpegv) * brate * 1000 / srate;
385 /* If there is padding, add one byte */
386 if (src[2] & 0x2) return size + 1;
387 else return size;
391 Apple's AudioFileStream does weird things so we deal with parsing the
392 file ourselves. It was also designed for a different use case, so this
393 is not unexpected. We expect to have MP3 data as input (i.e. we can only
394 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
395 understand the ID3v2 header and skip over it. Whenever we have data we
396 want to skip at the beginning of the input, we do this by setting *ndst=0
397 and *nsrc to the length of the unwanted data and return no error.
399 static LRESULT mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi,
400 unsigned char* src, LPDWORD nsrc,
401 unsigned char* dst, LPDWORD ndst)
403 OSStatus err;
404 UInt32 size, aspdi, synci, syncSkip;
405 short framelen[4];
406 const unsigned char* psrc;
407 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
409 TRACE("ndst %u %p <- %u %p\n", *ndst, dst, *nsrc, src);
411 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an((const char *)src, 16));
413 /* Parse ID3 tag */
414 if (!memcmp(src, "ID3", 3) && amd->tagBytesLeft == -1)
416 amd->tagBytesLeft = (src[6] << 21) + (src[7] << 14) + (src[8] << 7) + src[9];
417 if (src[5] & 0x10) amd->tagBytesLeft += 20; /* There is a footer */
418 else amd->tagBytesLeft += 10;
421 /* Consume the tag */
422 if (amd->tagBytesLeft >= (SInt32)*nsrc)
424 *ndst = 0;
425 amd->tagBytesLeft -= *nsrc;
427 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc);
428 return MMSYSERR_NOERROR;
430 else if (amd->tagBytesLeft > 0)
432 src += amd->tagBytesLeft;
433 *nsrc -= amd->tagBytesLeft;
434 TRACE("Skipping %ld for ID3 tag\n", amd->tagBytesLeft);
438 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
439 Thus, in the first 1440 bytes we must find the beginning of 3 valid
440 frames in a row unless we reach the end of the file first.
442 syncSkip = 0;
443 for (psrc = src; psrc <= src + *nsrc - 4 && psrc < src + 1440; psrc++)
445 framelen[0] = 0;
446 for (synci = 1;
447 synci < 4 && psrc + framelen[synci-1] < src + *nsrc - 4;
448 synci++)
450 framelen[synci] = Mp3GetPacketLength(psrc + framelen[synci-1]);
451 if (framelen[synci] == -1)
453 synci = 0;
454 break;
456 framelen[synci] += framelen[synci-1];
458 if (synci > 0) /* We synced successfully */
460 if (psrc - src > 0)
462 syncSkip = psrc - src;
463 src += syncSkip;
464 *nsrc -= syncSkip;
465 TRACE("Skipping %ld for frame sync\n", syncSkip);
467 break;
471 if (Mp3GetPacketLength(src) == -1)
473 *ndst = *nsrc = 0;
474 ERR("Frame sync failed. Cannot play file.\n");
475 return MMSYSERR_ERROR;
479 Fill in frame descriptions for all frames. We use an extra pointer
480 to keep track of our position in the input.
483 amd->NumberPackets = 25; /* This is the initial array capacity */
484 amd->PacketDescriptions = HeapAlloc(GetProcessHeap(), 0, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
485 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
487 for (aspdi = 0, psrc = src;
488 psrc <= src + *nsrc - 4;
489 psrc += amd->PacketDescriptions[aspdi].mDataByteSize, aspdi++)
491 /* Return an error if we can't read the frame header */
492 if (Mp3GetPacketLength(psrc) == -1)
494 *ndst = *nsrc = 0;
495 ERR("Invalid header at %p.\n", psrc);
496 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
497 return MMSYSERR_ERROR;
500 /* If we run out of space, double size and reallocate */
501 if (aspdi >= amd->NumberPackets)
503 amd->NumberPackets *= 2;
504 amd->PacketDescriptions = HeapReAlloc(GetProcessHeap(), 0, amd->PacketDescriptions, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
505 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
508 /* Fill in packet data */
509 amd->PacketDescriptions[aspdi].mStartOffset = psrc - src;
510 amd->PacketDescriptions[aspdi].mVariableFramesInPacket = 0;
511 amd->PacketDescriptions[aspdi].mDataByteSize = Mp3GetPacketLength(psrc);
513 /* If this brings us past the end, the last one doesn't count */
514 if (psrc + amd->PacketDescriptions[aspdi].mDataByteSize > src + *nsrc) break;
517 /* Fill in correct number of frames */
518 amd->NumberPackets = aspdi;
520 /* Adjust nsrc to only include full frames */
521 *nsrc = psrc - src;
523 amd->inBuffer.mDataByteSize = *nsrc;
524 amd->inBuffer.mData = src;
525 amd->inBuffer.mNumberChannels = amd->in.mChannelsPerFrame;
527 amd->outBuffer.mNumberBuffers = 1;
528 amd->outBuffer.mBuffers[0].mDataByteSize = *ndst;
529 amd->outBuffer.mBuffers[0].mData = dst;
530 amd->outBuffer.mBuffers[0].mNumberChannels = amd->out.mChannelsPerFrame;
532 /* Convert the data */
533 size = amd->outBuffer.mBuffers[0].mDataByteSize / amd->out.mBytesPerPacket;
534 err = AudioConverterFillComplexBuffer(amd->acr, Mp3AudioConverterComplexInputDataProc, amd, &size, &amd->outBuffer, 0);
536 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
538 /* Add skipped bytes back into *nsrc */
539 if (amd->tagBytesLeft > 0)
541 *nsrc += amd->tagBytesLeft;
542 amd->tagBytesLeft = 0;
544 *nsrc += syncSkip;
546 if (err != noErr && err != -74)
548 *ndst = *nsrc = 0;
549 ERR("Feed Error: %ld\n", err);
550 return MMSYSERR_ERROR;
553 *ndst = amd->outBuffer.mBuffers[0].mDataByteSize;
555 TRACE("convert %d -> %d\n", *nsrc, *ndst);
557 return MMSYSERR_NOERROR;
560 /***********************************************************************
561 * MPEG3_Reset
564 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
566 AudioConverterReset(aad->acr);
569 /***********************************************************************
570 * MPEG3_StreamOpen
573 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
575 AcmMpeg3Data* aad;
577 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
579 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
580 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
581 return ACMERR_NOTPOSSIBLE;
583 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
584 if (aad == 0) return MMSYSERR_NOMEM;
586 adsi->dwDriver = (DWORD_PTR)aad;
588 if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
589 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
590 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
592 OSStatus err;
594 aad->in.mSampleRate = adsi->pwfxSrc->nSamplesPerSec;
595 aad->out.mSampleRate = adsi->pwfxDst->nSamplesPerSec;
596 aad->in.mBitsPerChannel = adsi->pwfxSrc->wBitsPerSample;
597 aad->out.mBitsPerChannel = adsi->pwfxDst->wBitsPerSample;
598 aad->in.mFormatID = kAudioFormatMPEGLayer3;
599 aad->out.mFormatID = kAudioFormatLinearPCM;
600 aad->in.mChannelsPerFrame = adsi->pwfxSrc->nChannels;
601 aad->out.mChannelsPerFrame = adsi->pwfxDst->nChannels;
602 aad->in.mFormatFlags = 0;
603 aad->out.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
604 aad->in.mBytesPerFrame = 0;
605 aad->out.mBytesPerFrame = (aad->out.mBitsPerChannel * aad->out.mChannelsPerFrame) / 8;
606 aad->in.mBytesPerPacket = 0;
607 aad->out.mBytesPerPacket = aad->out.mBytesPerFrame;
608 aad->in.mFramesPerPacket = 0;
609 aad->out.mFramesPerPacket = 1;
610 aad->in.mReserved = aad->out.mReserved = 0;
612 aad->tagBytesLeft = -1;
614 aad->convert = mp3_leopard_horse;
616 err = AudioConverterNew(&aad->in, &aad->out, &aad->acr);
617 if (err != noErr)
619 ERR("Create failed: %ld\n", err);
621 else
623 MPEG3_Reset(adsi, aad);
625 return MMSYSERR_NOERROR;
629 HeapFree(GetProcessHeap(), 0, aad);
630 adsi->dwDriver = 0;
632 return MMSYSERR_NOTSUPPORTED;
635 /***********************************************************************
636 * MPEG3_StreamClose
639 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
641 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
643 AudioConverterDispose(amd->acr);
645 HeapFree(GetProcessHeap(), 0, amd);
646 adsi->dwDriver = 0;
648 return MMSYSERR_NOERROR;
651 #endif
653 /***********************************************************************
654 * MPEG3_DriverDetails
657 static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
659 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
660 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
661 add->wMid = 0xFF;
662 add->wPid = 0x00;
663 add->vdwACM = 0x01000000;
664 add->vdwDriver = 0x01000000;
665 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
666 add->cFormatTags = 3; /* PCM, MPEG3 */
667 add->cFilterTags = 0;
668 add->hicon = NULL;
669 MultiByteToWideChar( CP_ACP, 0, "WINE-MPEG3", -1,
670 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
671 MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
672 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
673 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
674 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
675 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
676 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
677 add->szFeatures[0] = 0;
679 return MMSYSERR_NOERROR;
682 /***********************************************************************
683 * MPEG3_FormatTagDetails
686 static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
688 static const WCHAR szPcm[]={'P','C','M',0};
689 static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
690 static const WCHAR szMpeg[]={'M','P','e','g',0};
692 switch (dwQuery)
694 case ACM_FORMATTAGDETAILSF_INDEX:
695 if (aftd->dwFormatTagIndex > 2) return ACMERR_NOTPOSSIBLE;
696 break;
697 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
698 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
700 aftd->dwFormatTagIndex = 2; /* WAVE_FORMAT_MPEG is biggest */
701 break;
703 /* fall through */
704 case ACM_FORMATTAGDETAILSF_FORMATTAG:
705 switch (aftd->dwFormatTag)
707 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
708 case WAVE_FORMAT_MPEGLAYER3: aftd->dwFormatTagIndex = 1; break;
709 case WAVE_FORMAT_MPEG: aftd->dwFormatTagIndex = 2; break;
710 default: return ACMERR_NOTPOSSIBLE;
712 break;
713 default:
714 WARN("Unsupported query %08x\n", dwQuery);
715 return MMSYSERR_NOTSUPPORTED;
718 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
719 switch (aftd->dwFormatTagIndex)
721 case 0:
722 aftd->dwFormatTag = WAVE_FORMAT_PCM;
723 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
724 aftd->cStandardFormats = NUM_PCM_FORMATS;
725 lstrcpyW(aftd->szFormatTag, szPcm);
726 break;
727 case 1:
728 aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
729 aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
730 aftd->cStandardFormats = NUM_MPEG3_FORMATS;
731 lstrcpyW(aftd->szFormatTag, szMpeg3);
732 break;
733 case 2:
734 aftd->dwFormatTag = WAVE_FORMAT_MPEG;
735 aftd->cbFormatSize = sizeof(MPEG1WAVEFORMAT);
736 aftd->cStandardFormats = NUM_MPEG3_FORMATS;
737 lstrcpyW(aftd->szFormatTag, szMpeg);
738 break;
740 return MMSYSERR_NOERROR;
743 static void fill_in_mp3(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
745 MPEGLAYER3WAVEFORMAT* mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx;
747 wfx->nAvgBytesPerSec = bit_rate / 8;
748 if (cbwfx >= sizeof(WAVEFORMATEX))
749 wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
750 if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT))
752 mp3wfx->wID = MPEGLAYER3_ID_MPEG;
753 mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
754 mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec;
755 mp3wfx->nFramesPerBlock = 1;
756 mp3wfx->nCodecDelay = 0x0571;
760 static void fill_in_mpeg(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
762 MPEG1WAVEFORMAT* mp3wfx = (MPEG1WAVEFORMAT*)wfx;
764 wfx->nAvgBytesPerSec = bit_rate / 8;
765 if (cbwfx >= sizeof(WAVEFORMATEX))
766 wfx->cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);
767 if (cbwfx >= sizeof(MPEG1WAVEFORMAT))
769 mp3wfx->fwHeadLayer = ACM_MPEG_LAYER3;
770 mp3wfx->dwHeadBitrate = wfx->nAvgBytesPerSec * 8;
771 mp3wfx->fwHeadMode = ACM_MPEG_JOINTSTEREO;
772 mp3wfx->fwHeadModeExt = 0xf;
773 mp3wfx->wHeadEmphasis = 1;
774 mp3wfx->fwHeadFlags = ACM_MPEG_ID_MPEG1;
778 /***********************************************************************
779 * MPEG3_FormatDetails
782 static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
784 switch (dwQuery)
786 case ACM_FORMATDETAILSF_FORMAT:
787 if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
788 break;
789 case ACM_FORMATDETAILSF_INDEX:
790 afd->pwfx->wFormatTag = afd->dwFormatTag;
791 switch (afd->dwFormatTag)
793 case WAVE_FORMAT_PCM:
794 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
795 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
796 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
797 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
798 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
799 * afd->pwfx->cbSize = 0;
801 afd->pwfx->nBlockAlign =
802 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
803 afd->pwfx->nAvgBytesPerSec =
804 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
805 break;
806 case WAVE_FORMAT_MPEGLAYER3:
807 case WAVE_FORMAT_MPEG:
808 if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE;
809 afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels;
810 afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate;
811 afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits;
812 afd->pwfx->nBlockAlign = 1;
813 if (afd->dwFormatTag == WAVE_FORMAT_MPEGLAYER3)
814 fill_in_mp3(afd->cbwfx, afd->pwfx, 192000);
815 else
816 fill_in_mpeg(afd->cbwfx, afd->pwfx, 192000);
817 break;
818 default:
819 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
820 return MMSYSERR_INVALPARAM;
822 break;
823 default:
824 WARN("Unsupported query %08x\n", dwQuery);
825 return MMSYSERR_NOTSUPPORTED;
827 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
828 afd->szFormat[0] = 0; /* let MSACM format this for us... */
830 return MMSYSERR_NOERROR;
833 /***********************************************************************
834 * MPEG3_FormatSuggest
837 static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
839 /* some tests ... */
840 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
841 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
842 MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
843 /* FIXME: should do those tests against the real size (according to format tag */
845 /* If no suggestion for destination, then copy source value */
846 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
847 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
848 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
849 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
851 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
853 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
854 adfs->pwfxDst->wBitsPerSample = 4;
855 else
856 adfs->pwfxDst->wBitsPerSample = 16;
858 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
860 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
861 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
862 else
863 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
866 /* check if result is ok */
867 if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
869 /* recompute other values */
870 switch (adfs->pwfxDst->wFormatTag)
872 case WAVE_FORMAT_PCM:
873 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
874 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
875 break;
876 case WAVE_FORMAT_MPEG:
877 adfs->pwfxDst->nBlockAlign = 1;
878 fill_in_mpeg(adfs->cbwfxDst, adfs->pwfxDst, 192000);
879 break;
880 case WAVE_FORMAT_MPEGLAYER3:
881 adfs->pwfxDst->nBlockAlign = 1;
882 fill_in_mp3(adfs->cbwfxDst, adfs->pwfxDst, 192000);
883 break;
884 default:
885 FIXME("\n");
886 break;
889 return MMSYSERR_NOERROR;
892 /***********************************************************************
893 * MPEG3_StreamSize
896 static LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
898 DWORD nblocks;
900 switch (adss->fdwSize)
902 case ACM_STREAMSIZEF_DESTINATION:
903 /* cbDstLength => cbSrcLength */
904 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
905 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
906 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
908 nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
909 if (nblocks == 0)
910 return ACMERR_NOTPOSSIBLE;
911 adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
913 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
914 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
915 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
917 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
918 if (nblocks == 0)
919 return ACMERR_NOTPOSSIBLE;
920 adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
922 else
924 return MMSYSERR_NOTSUPPORTED;
926 break;
927 case ACM_STREAMSIZEF_SOURCE:
928 /* cbSrcLength => cbDstLength */
929 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
930 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
931 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
933 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
934 if (nblocks == 0)
935 return ACMERR_NOTPOSSIBLE;
936 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
937 /* Round block count up. */
938 nblocks++;
939 adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
941 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
942 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
943 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
945 nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
946 if (nblocks == 0)
947 return ACMERR_NOTPOSSIBLE;
948 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
949 /* Round block count up. */
950 nblocks++;
951 adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
953 else
955 return MMSYSERR_NOTSUPPORTED;
957 break;
958 default:
959 WARN("Unsupported query %08x\n", adss->fdwSize);
960 return MMSYSERR_NOTSUPPORTED;
962 return MMSYSERR_NOERROR;
965 /***********************************************************************
966 * MPEG3_StreamConvert
969 static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
971 AcmMpeg3Data* aad = (AcmMpeg3Data*)adsi->dwDriver;
972 DWORD nsrc = adsh->cbSrcLength;
973 DWORD ndst = adsh->cbDstLength;
975 if (adsh->fdwConvert &
976 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
977 ACM_STREAMCONVERTF_END|
978 ACM_STREAMCONVERTF_START))
980 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
982 /* ACM_STREAMCONVERTF_BLOCKALIGN
983 * currently all conversions are block aligned, so do nothing for this flag
984 * ACM_STREAMCONVERTF_END
985 * no pending data, so do nothing for this flag
987 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
989 MPEG3_Reset(adsi, aad);
992 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
993 adsh->cbSrcLengthUsed = nsrc;
994 adsh->cbDstLengthUsed = ndst;
996 return MMSYSERR_NOERROR;
999 /**************************************************************************
1000 * MPEG3_DriverProc [exported]
1002 LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1003 LPARAM dwParam1, LPARAM dwParam2)
1005 TRACE("(%08lx %p %04x %08lx %08lx);\n",
1006 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1008 switch (wMsg)
1010 case DRV_LOAD: return 1;
1011 case DRV_FREE: return 1;
1012 case DRV_OPEN: return MPEG3_drvOpen((LPSTR)dwParam1);
1013 case DRV_CLOSE: return MPEG3_drvClose(dwDevID);
1014 case DRV_ENABLE: return 1;
1015 case DRV_DISABLE: return 1;
1016 case DRV_QUERYCONFIGURE: return 1;
1017 case DRV_CONFIGURE: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
1018 case DRV_INSTALL: return DRVCNF_RESTART;
1019 case DRV_REMOVE: return DRVCNF_RESTART;
1021 case ACMDM_DRIVER_NOTIFY:
1022 /* no caching from other ACM drivers is done so far */
1023 return MMSYSERR_NOERROR;
1025 case ACMDM_DRIVER_DETAILS:
1026 return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1028 case ACMDM_FORMATTAG_DETAILS:
1029 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1031 case ACMDM_FORMAT_DETAILS:
1032 return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1034 case ACMDM_FORMAT_SUGGEST:
1035 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1037 case ACMDM_STREAM_OPEN:
1038 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1040 case ACMDM_STREAM_CLOSE:
1041 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1043 case ACMDM_STREAM_SIZE:
1044 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1046 case ACMDM_STREAM_CONVERT:
1047 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1049 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1050 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1051 /* this converter is not a hardware driver */
1052 case ACMDM_FILTERTAG_DETAILS:
1053 case ACMDM_FILTER_DETAILS:
1054 /* this converter is not a filter */
1055 case ACMDM_STREAM_RESET:
1056 /* only needed for asynchronous driver... we aren't, so just say it */
1057 return MMSYSERR_NOTSUPPORTED;
1058 case ACMDM_STREAM_PREPARE:
1059 case ACMDM_STREAM_UNPREPARE:
1060 /* nothing special to do here... so don't do anything */
1061 return MMSYSERR_NOERROR;
1063 default:
1064 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);