2 * MPEG Layer 3 handling
4 * Copyright (C) 2002 Eric Pouech
5 * Copyright (C) 2009 CodeWeavers, Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
33 # ifdef HAVE_COREAUDIO_COREAUDIO_H
34 # include <CoreFoundation/CoreFoundation.h>
35 # include <CoreAudio/CoreAudio.h>
37 # ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
38 # include <AudioToolbox/AudioConverter.h>
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3
);
55 /* table to list all supported formats... those are the basic ones. this
56 * also helps given a unique index to each of the supported formats
65 static const Format PCM_Formats
[] =
67 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
68 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
69 {1, 8, 12000}, {2, 8, 12000}, {1, 16, 12000}, {2, 16, 12000},
70 {1, 8, 16000}, {2, 8, 16000}, {1, 16, 16000}, {2, 16, 16000},
71 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
72 {1, 8, 24000}, {2, 8, 24000}, {1, 16, 24000}, {2, 16, 24000},
73 {1, 8, 32000}, {2, 8, 32000}, {1, 16, 32000}, {2, 16, 32000},
74 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
75 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}
78 static const Format MPEG3_Formats
[] =
80 {1, 0, 8000}, {2, 0, 8000},
81 {1, 0, 11025}, {2, 0, 11025},
82 {1, 0, 12000}, {2, 0, 12000},
83 {1, 0, 16000}, {2, 0, 16000},
84 {1, 0, 22050}, {2, 0, 22050},
85 {1, 0, 24000}, {2, 0, 24000},
86 {1, 0, 32000}, {2, 0, 32000},
87 {1, 0, 44100}, {2, 0, 44100},
88 {1, 0, 48000}, {2, 0, 48000}
91 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
92 #define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))
94 /***********************************************************************
95 * MPEG3_GetFormatIndex
97 static DWORD
MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx
)
102 switch (wfx
->wFormatTag
)
104 case WAVE_FORMAT_PCM
:
105 hi
= NUM_PCM_FORMATS
;
108 case WAVE_FORMAT_MPEGLAYER3
:
109 hi
= NUM_MPEG3_FORMATS
;
110 fmts
= MPEG3_Formats
;
116 for (i
= 0; i
< hi
; i
++)
118 if (wfx
->nChannels
== fmts
[i
].nChannels
&&
119 wfx
->nSamplesPerSec
== fmts
[i
].rate
&&
120 (wfx
->wBitsPerSample
== fmts
[i
].nBits
|| !fmts
[i
].nBits
))
129 typedef struct tagAcmMpeg3Data
131 void (*convert
)(PACMDRVSTREAMINSTANCE adsi
,
132 const unsigned char*, LPDWORD
, unsigned char*, LPDWORD
);
136 /***********************************************************************
139 static LRESULT
MPEG3_drvOpen(LPCSTR str
)
145 /***********************************************************************
148 static LRESULT
MPEG3_drvClose(DWORD_PTR dwDevID
)
155 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi
,
156 const unsigned char* src
, LPDWORD nsrc
,
157 unsigned char* dst
, LPDWORD ndst
)
159 AcmMpeg3Data
* amd
= (AcmMpeg3Data
*)adsi
->dwDriver
;
167 ret
= mpg123_feed(amd
->mh
, src
, *nsrc
);
168 if (ret
!= MPG123_OK
)
170 ERR("Error feeding data\n");
178 ret
= mpg123_read(amd
->mh
, dst
+ dpos
, *ndst
- dpos
, &size
);
179 if (ret
== MPG123_ERR
)
181 FIXME("Error occurred during decoding!\n");
186 if (ret
== MPG123_NEW_FORMAT
)
190 mpg123_getformat(amd
->mh
, &rate
, &channels
, &enc
);
191 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate
, channels
, enc
);
194 if (dpos
> *ndst
) break;
195 } while (ret
!= MPG123_ERR
&& ret
!= MPG123_NEED_MORE
);
199 /***********************************************************************
203 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi
, AcmMpeg3Data
* aad
)
205 mpg123_feedseek(aad
->mh
, 0, SEEK_SET
, NULL
);
206 mpg123_close(aad
->mh
);
207 mpg123_open_feed(aad
->mh
);
210 /***********************************************************************
214 static LRESULT
MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
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
)
235 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
&&
236 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
238 /* resampling or mono <=> stereo not available
239 * MPEG3 algo only define 16 bit per sample output
241 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
242 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
243 adsi
->pwfxDst
->wBitsPerSample
!= 16)
245 aad
->convert
= mp3_horse
;
246 aad
->mh
= mpg123_new(NULL
,&err
);
247 mpg123_open_feed(aad
->mh
);
250 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
251 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
254 MPEG3_Reset(adsi
, aad
);
256 return MMSYSERR_NOERROR
;
259 HeapFree(GetProcessHeap(), 0, aad
);
261 return MMSYSERR_NOTSUPPORTED
;
264 /***********************************************************************
268 static LRESULT
MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
270 mpg123_close(((AcmMpeg3Data
*)adsi
->dwDriver
)->mh
);
271 mpg123_delete(((AcmMpeg3Data
*)adsi
->dwDriver
)->mh
);
272 HeapFree(GetProcessHeap(), 0, (void*)adsi
->dwDriver
);
273 return MMSYSERR_NOERROR
;
276 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
278 static const unsigned short Mp3BitRates
[2][16] =
280 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
281 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
284 static const unsigned short Mp3SampleRates
[2][4] =
286 {44100, 48000, 32000, 0},
287 {22050, 24000, 16000, 0}
290 typedef struct tagAcmMpeg3Data
292 LRESULT (*convert
)(PACMDRVSTREAMINSTANCE adsi
, const unsigned char*,
293 LPDWORD
, unsigned char*, LPDWORD
);
294 AudioConverterRef acr
;
295 AudioStreamBasicDescription in
,out
;
297 AudioBufferList outBuffer
;
298 AudioBuffer inBuffer
;
302 UInt32 NumberPackets
;
303 AudioStreamPacketDescription
*PacketDescriptions
;
306 /***********************************************************************
309 static LRESULT
MPEG3_drvOpen(LPCSTR str
)
314 /***********************************************************************
317 static LRESULT
MPEG3_drvClose(DWORD_PTR dwDevID
)
323 When it asks for data, give it all we have. If we have no data, we assume
324 we will in the future, so give it no packets and return an error, which
325 signals that we will have more later.
327 static OSStatus
Mp3AudioConverterComplexInputDataProc(
328 AudioConverterRef inAudioConverter
,
329 UInt32
*ioNumberDataPackets
,
330 AudioBufferList
*ioData
,
331 AudioStreamPacketDescription
**outDataPacketDescription
,
335 AcmMpeg3Data
*amd
= (AcmMpeg3Data
*)inUserData
;
337 if (amd
->inBuffer
.mDataByteSize
> 0)
339 *ioNumberDataPackets
= amd
->NumberPackets
;
340 ioData
->mNumberBuffers
= 1;
341 ioData
->mBuffers
[0] = amd
->inBuffer
;
342 amd
->inBuffer
.mDataByteSize
= 0;
343 if (outDataPacketDescription
)
344 *outDataPacketDescription
= amd
->PacketDescriptions
;
349 *ioNumberDataPackets
= 0;
355 Get the length of the current frame. We need to be at the start of a
356 frame now. The buffer must have at least the four bytes for the header.
358 static SInt32
Mp3GetPacketLength(const unsigned char* src
)
361 unsigned short brate
, srate
;
365 Check that our position looks like an MP3 header and see which type
368 if (src
[0] == 0xff && src
[1] >> 1 == 0x7d) mpegv
= 0; /* MPEG-1 File */
369 else if (src
[0] == 0xff && src
[1] >> 1 == 0x79) mpegv
= 1; /* MPEG-2 File */
372 /* Fill in bit rate and sample rate. */
373 brate
= Mp3BitRates
[mpegv
][(src
[2] & 0xf0) >> 4];
374 srate
= Mp3SampleRates
[mpegv
][(src
[2] & 0xc) >> 2];
376 /* Certain values for bit rate and sample rate are invalid. */
377 if (brate
== 0 || srate
== 0) return -1;
379 /* Compute frame size, round down */
380 size
= 72 * (2 - mpegv
) * brate
* 1000 / srate
;
382 /* If there is padding, add one byte */
383 if (src
[2] & 0x2) return size
+ 1;
388 Apple's AudioFileStream does weird things so we deal with parsing the
389 file ourselves. It was also designed for a different use case, so this
390 is not unexpected. We expect to have MP3 data as input (i.e. we can only
391 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
392 understand the ID3v2 header and skip over it. Whenever we have data we
393 want to skip at the beginning of the input, we do this by setting *ndst=0
394 and *nsrc to the length of the unwanted data and return no error.
396 static LRESULT
mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi
,
397 const unsigned char* src
, LPDWORD nsrc
,
398 unsigned char* dst
, LPDWORD ndst
)
401 UInt32 size
, aspdi
, synci
, syncSkip
;
403 const unsigned char* psrc
;
404 AcmMpeg3Data
* amd
= (AcmMpeg3Data
*)adsi
->dwDriver
;
406 TRACE("ndst %u %p <- %u %p\n", *ndst
, dst
, *nsrc
, src
);
408 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an(src
, 16));
411 if (!memcmp(src
, "ID3", 3) && amd
->tagBytesLeft
== -1)
413 amd
->tagBytesLeft
= (src
[6] << 21) + (src
[7] << 14) + (src
[8] << 7) + src
[9];
414 if (src
[5] & 0x10) amd
->tagBytesLeft
+= 20; /* There is a footer */
415 else amd
->tagBytesLeft
+= 10;
418 /* Consume the tag */
419 if (amd
->tagBytesLeft
>= (SInt32
)*nsrc
)
422 amd
->tagBytesLeft
-= *nsrc
;
424 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc
);
425 return MMSYSERR_NOERROR
;
427 else if (amd
->tagBytesLeft
> 0)
429 src
+= amd
->tagBytesLeft
;
430 *nsrc
-= amd
->tagBytesLeft
;
431 TRACE("Skipping %d for ID3 tag\n", amd
->tagBytesLeft
);
435 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
436 Thus, in the first 1440 bytes we must find the beginning of 3 valid
437 frames in a row unless we reach the end of the file first.
440 for (psrc
= src
; psrc
<= src
+ *nsrc
- 4 && psrc
< src
+ 1440; psrc
++)
444 synci
< 4 && psrc
+ framelen
[synci
-1] < src
+ *nsrc
- 4;
447 framelen
[synci
] = Mp3GetPacketLength(psrc
+ framelen
[synci
-1]);
448 if (framelen
[synci
] == -1)
453 framelen
[synci
] += framelen
[synci
-1];
455 if (synci
> 0) /* We synced successfully */
459 syncSkip
= psrc
- src
;
462 TRACE("Skipping %d for frame sync\n", syncSkip
);
468 if (Mp3GetPacketLength(src
) == -1)
471 ERR("Frame sync failed. Cannot play file.\n");
472 return MMSYSERR_ERROR
;
476 Fill in frame descriptions for all frames. We use an extra pointer
477 to keep track of our position in the input.
480 amd
->NumberPackets
= 25; /* This is the initial array capacity */
481 amd
->PacketDescriptions
= HeapAlloc(GetProcessHeap(), 0, amd
->NumberPackets
* sizeof(AudioStreamPacketDescription
));
482 if (amd
->PacketDescriptions
== 0) return MMSYSERR_NOMEM
;
484 for (aspdi
= 0, psrc
= src
;
485 psrc
<= src
+ *nsrc
- 4;
486 psrc
+= amd
->PacketDescriptions
[aspdi
].mDataByteSize
, aspdi
++)
488 /* Return an error if we can't read the frame header */
489 if (Mp3GetPacketLength(psrc
) == -1)
492 ERR("Invalid header at %p.\n", psrc
);
493 HeapFree(GetProcessHeap(), 0, amd
->PacketDescriptions
);
494 return MMSYSERR_ERROR
;
497 /* If we run out of space, double size and reallocate */
498 if (aspdi
>= amd
->NumberPackets
)
500 amd
->NumberPackets
*= 2;
501 amd
->PacketDescriptions
= HeapReAlloc(GetProcessHeap(), 0, amd
->PacketDescriptions
, amd
->NumberPackets
* sizeof(AudioStreamPacketDescription
));
502 if (amd
->PacketDescriptions
== 0) return MMSYSERR_NOMEM
;
505 /* Fill in packet data */
506 amd
->PacketDescriptions
[aspdi
].mStartOffset
= psrc
- src
;
507 amd
->PacketDescriptions
[aspdi
].mVariableFramesInPacket
= 0;
508 amd
->PacketDescriptions
[aspdi
].mDataByteSize
= Mp3GetPacketLength(psrc
);
510 /* If this brings us past the end, the last one doesn't count */
511 if (psrc
+ amd
->PacketDescriptions
[aspdi
].mDataByteSize
> src
+ *nsrc
) break;
514 /* Fill in correct number of frames */
515 amd
->NumberPackets
= aspdi
;
517 /* Adjust nsrc to only include full frames */
520 amd
->inBuffer
.mDataByteSize
= *nsrc
;
521 amd
->inBuffer
.mData
= src
;
522 amd
->inBuffer
.mNumberChannels
= amd
->in
.mChannelsPerFrame
;
524 amd
->outBuffer
.mNumberBuffers
= 1;
525 amd
->outBuffer
.mBuffers
[0].mDataByteSize
= *ndst
;
526 amd
->outBuffer
.mBuffers
[0].mData
= dst
;
527 amd
->outBuffer
.mBuffers
[0].mNumberChannels
= amd
->out
.mChannelsPerFrame
;
529 /* Convert the data */
530 size
= amd
->outBuffer
.mBuffers
[0].mDataByteSize
/ amd
->out
.mBytesPerPacket
;
531 err
= AudioConverterFillComplexBuffer(amd
->acr
, Mp3AudioConverterComplexInputDataProc
, amd
, &size
, &amd
->outBuffer
, 0);
533 HeapFree(GetProcessHeap(), 0, amd
->PacketDescriptions
);
535 /* Add skipped bytes back into *nsrc */
536 if (amd
->tagBytesLeft
> 0)
538 *nsrc
+= amd
->tagBytesLeft
;
539 amd
->tagBytesLeft
= 0;
543 if (err
!= noErr
&& err
!= -74)
546 ERR("Feed Error: %ld\n", err
);
547 return MMSYSERR_ERROR
;
550 *ndst
= amd
->outBuffer
.mBuffers
[0].mDataByteSize
;
552 TRACE("convert %d -> %d\n", *nsrc
, *ndst
);
554 return MMSYSERR_NOERROR
;
557 /***********************************************************************
561 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi
, AcmMpeg3Data
* aad
)
563 AudioConverterReset(aad
->acr
);
566 /***********************************************************************
570 static LRESULT
MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
574 assert(!(adsi
->fdwOpen
& ACM_STREAMOPENF_ASYNC
));
576 if (MPEG3_GetFormatIndex(adsi
->pwfxSrc
) == 0xFFFFFFFF ||
577 MPEG3_GetFormatIndex(adsi
->pwfxDst
) == 0xFFFFFFFF)
578 return ACMERR_NOTPOSSIBLE
;
580 aad
= HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data
));
581 if (aad
== 0) return MMSYSERR_NOMEM
;
583 adsi
->dwDriver
= (DWORD_PTR
)aad
;
585 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
&&
586 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
590 aad
->in
.mSampleRate
= adsi
->pwfxSrc
->nSamplesPerSec
;
591 aad
->out
.mSampleRate
= adsi
->pwfxDst
->nSamplesPerSec
;
592 aad
->in
.mBitsPerChannel
= adsi
->pwfxSrc
->wBitsPerSample
;
593 aad
->out
.mBitsPerChannel
= adsi
->pwfxDst
->wBitsPerSample
;
594 aad
->in
.mFormatID
= kAudioFormatMPEGLayer3
;
595 aad
->out
.mFormatID
= kAudioFormatLinearPCM
;
596 aad
->in
.mChannelsPerFrame
= adsi
->pwfxSrc
->nChannels
;
597 aad
->out
.mChannelsPerFrame
= adsi
->pwfxDst
->nChannels
;
598 aad
->in
.mFormatFlags
= 0;
599 aad
->out
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
600 aad
->in
.mBytesPerFrame
= 0;
601 aad
->out
.mBytesPerFrame
= (aad
->out
.mBitsPerChannel
* aad
->out
.mChannelsPerFrame
) / 8;
602 aad
->in
.mBytesPerPacket
= 0;
603 aad
->out
.mBytesPerPacket
= aad
->out
.mBytesPerFrame
;
604 aad
->in
.mFramesPerPacket
= 0;
605 aad
->out
.mFramesPerPacket
= 1;
606 aad
->in
.mReserved
= aad
->out
.mReserved
= 0;
608 aad
->tagBytesLeft
= -1;
610 aad
->convert
= mp3_leopard_horse
;
612 err
= AudioConverterNew(&aad
->in
, &aad
->out
, &aad
->acr
);
615 ERR("Create failed: %ld\n", err
);
619 MPEG3_Reset(adsi
, aad
);
621 return MMSYSERR_NOERROR
;
625 HeapFree(GetProcessHeap(), 0, aad
);
628 return MMSYSERR_NOTSUPPORTED
;
631 /***********************************************************************
635 static LRESULT
MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
637 AcmMpeg3Data
* amd
= (AcmMpeg3Data
*)adsi
->dwDriver
;
639 AudioConverterDispose(amd
->acr
);
641 HeapFree(GetProcessHeap(), 0, amd
);
644 return MMSYSERR_NOERROR
;
649 /***********************************************************************
650 * MPEG3_DriverDetails
653 static LRESULT
MPEG3_DriverDetails(PACMDRIVERDETAILSW add
)
655 add
->fccType
= ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
656 add
->fccComp
= ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
;
659 add
->vdwACM
= 0x01000000;
660 add
->vdwDriver
= 0x01000000;
661 add
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
662 add
->cFormatTags
= 2; /* PCM, MPEG3 */
663 add
->cFilterTags
= 0;
665 MultiByteToWideChar( CP_ACP
, 0, "WINE-MPEG3", -1,
666 add
->szShortName
, sizeof(add
->szShortName
)/sizeof(WCHAR
) );
667 MultiByteToWideChar( CP_ACP
, 0, "Wine MPEG3 decoder", -1,
668 add
->szLongName
, sizeof(add
->szLongName
)/sizeof(WCHAR
) );
669 MultiByteToWideChar( CP_ACP
, 0, "Brought to you by the Wine team...", -1,
670 add
->szCopyright
, sizeof(add
->szCopyright
)/sizeof(WCHAR
) );
671 MultiByteToWideChar( CP_ACP
, 0, "Refer to LICENSE file", -1,
672 add
->szLicensing
, sizeof(add
->szLicensing
)/sizeof(WCHAR
) );
673 add
->szFeatures
[0] = 0;
675 return MMSYSERR_NOERROR
;
678 /***********************************************************************
679 * MPEG3_FormatTagDetails
682 static LRESULT
MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd
, DWORD dwQuery
)
684 static const WCHAR szPcm
[]={'P','C','M',0};
685 static const WCHAR szMpeg3
[]={'M','P','e','g','3',0};
689 case ACM_FORMATTAGDETAILSF_INDEX
:
690 if (aftd
->dwFormatTagIndex
>= 2) return ACMERR_NOTPOSSIBLE
;
692 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
693 if (aftd
->dwFormatTag
== WAVE_FORMAT_UNKNOWN
)
695 aftd
->dwFormatTagIndex
= 1; /* WAVE_FORMAT_MPEGLAYER3 is bigger than PCM */
699 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
700 switch (aftd
->dwFormatTag
)
702 case WAVE_FORMAT_PCM
: aftd
->dwFormatTagIndex
= 0; break;
703 case WAVE_FORMAT_MPEGLAYER3
: aftd
->dwFormatTagIndex
= 1; break;
704 default: return ACMERR_NOTPOSSIBLE
;
708 WARN("Unsupported query %08x\n", dwQuery
);
709 return MMSYSERR_NOTSUPPORTED
;
712 aftd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
713 switch (aftd
->dwFormatTagIndex
)
716 aftd
->dwFormatTag
= WAVE_FORMAT_PCM
;
717 aftd
->cbFormatSize
= sizeof(PCMWAVEFORMAT
);
718 aftd
->cStandardFormats
= NUM_PCM_FORMATS
;
719 lstrcpyW(aftd
->szFormatTag
, szPcm
);
722 aftd
->dwFormatTag
= WAVE_FORMAT_MPEGLAYER3
;
723 aftd
->cbFormatSize
= sizeof(MPEGLAYER3WAVEFORMAT
);
724 aftd
->cStandardFormats
= NUM_MPEG3_FORMATS
;
725 lstrcpyW(aftd
->szFormatTag
, szMpeg3
);
728 return MMSYSERR_NOERROR
;
731 static void fill_in_wfx(unsigned cbwfx
, WAVEFORMATEX
* wfx
, unsigned bit_rate
)
733 MPEGLAYER3WAVEFORMAT
* mp3wfx
= (MPEGLAYER3WAVEFORMAT
*)wfx
;
735 wfx
->nAvgBytesPerSec
= bit_rate
/ 8;
736 if (cbwfx
>= sizeof(WAVEFORMATEX
))
737 wfx
->cbSize
= sizeof(MPEGLAYER3WAVEFORMAT
) - sizeof(WAVEFORMATEX
);
738 if (cbwfx
>= sizeof(MPEGLAYER3WAVEFORMAT
))
740 mp3wfx
->wID
= MPEGLAYER3_ID_MPEG
;
741 mp3wfx
->fdwFlags
= MPEGLAYER3_FLAG_PADDING_OFF
;
742 mp3wfx
->nBlockSize
= (bit_rate
* 144) / wfx
->nSamplesPerSec
;
743 mp3wfx
->nFramesPerBlock
= 1;
744 mp3wfx
->nCodecDelay
= 0x0571;
748 /***********************************************************************
749 * MPEG3_FormatDetails
752 static LRESULT
MPEG3_FormatDetails(PACMFORMATDETAILSW afd
, DWORD dwQuery
)
756 case ACM_FORMATDETAILSF_FORMAT
:
757 if (MPEG3_GetFormatIndex(afd
->pwfx
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
759 case ACM_FORMATDETAILSF_INDEX
:
760 afd
->pwfx
->wFormatTag
= afd
->dwFormatTag
;
761 switch (afd
->dwFormatTag
)
763 case WAVE_FORMAT_PCM
:
764 if (afd
->dwFormatIndex
>= NUM_PCM_FORMATS
) return ACMERR_NOTPOSSIBLE
;
765 afd
->pwfx
->nChannels
= PCM_Formats
[afd
->dwFormatIndex
].nChannels
;
766 afd
->pwfx
->nSamplesPerSec
= PCM_Formats
[afd
->dwFormatIndex
].rate
;
767 afd
->pwfx
->wBitsPerSample
= PCM_Formats
[afd
->dwFormatIndex
].nBits
;
768 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
769 * afd->pwfx->cbSize = 0;
771 afd
->pwfx
->nBlockAlign
=
772 (afd
->pwfx
->nChannels
* afd
->pwfx
->wBitsPerSample
) / 8;
773 afd
->pwfx
->nAvgBytesPerSec
=
774 afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nBlockAlign
;
776 case WAVE_FORMAT_MPEGLAYER3
:
777 if (afd
->dwFormatIndex
>= NUM_MPEG3_FORMATS
) return ACMERR_NOTPOSSIBLE
;
778 afd
->pwfx
->nChannels
= MPEG3_Formats
[afd
->dwFormatIndex
].nChannels
;
779 afd
->pwfx
->nSamplesPerSec
= MPEG3_Formats
[afd
->dwFormatIndex
].rate
;
780 afd
->pwfx
->wBitsPerSample
= MPEG3_Formats
[afd
->dwFormatIndex
].nBits
;
781 afd
->pwfx
->nBlockAlign
= 1;
782 fill_in_wfx(afd
->cbwfx
, afd
->pwfx
, 192000);
785 WARN("Unsupported tag %08x\n", afd
->dwFormatTag
);
786 return MMSYSERR_INVALPARAM
;
790 WARN("Unsupported query %08x\n", dwQuery
);
791 return MMSYSERR_NOTSUPPORTED
;
793 afd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
794 afd
->szFormat
[0] = 0; /* let MSACM format this for us... */
796 return MMSYSERR_NOERROR
;
799 /***********************************************************************
800 * MPEG3_FormatSuggest
803 static LRESULT
MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs
)
806 if (adfs
->cbwfxSrc
< sizeof(PCMWAVEFORMAT
) ||
807 adfs
->cbwfxDst
< sizeof(PCMWAVEFORMAT
) ||
808 MPEG3_GetFormatIndex(adfs
->pwfxSrc
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
809 /* FIXME: should do those tests against the real size (according to format tag */
811 /* If no suggestion for destination, then copy source value */
812 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NCHANNELS
))
813 adfs
->pwfxDst
->nChannels
= adfs
->pwfxSrc
->nChannels
;
814 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NSAMPLESPERSEC
))
815 adfs
->pwfxDst
->nSamplesPerSec
= adfs
->pwfxSrc
->nSamplesPerSec
;
817 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WBITSPERSAMPLE
))
819 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
820 adfs
->pwfxDst
->wBitsPerSample
= 4;
822 adfs
->pwfxDst
->wBitsPerSample
= 16;
824 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WFORMATTAG
))
826 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
827 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_MPEGLAYER3
;
829 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_PCM
;
832 /* check if result is ok */
833 if (MPEG3_GetFormatIndex(adfs
->pwfxDst
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
835 /* recompute other values */
836 switch (adfs
->pwfxDst
->wFormatTag
)
838 case WAVE_FORMAT_PCM
:
839 adfs
->pwfxDst
->nBlockAlign
= (adfs
->pwfxDst
->nChannels
* adfs
->pwfxDst
->wBitsPerSample
) / 8;
840 adfs
->pwfxDst
->nAvgBytesPerSec
= adfs
->pwfxDst
->nSamplesPerSec
* adfs
->pwfxDst
->nBlockAlign
;
842 case WAVE_FORMAT_MPEGLAYER3
:
843 adfs
->pwfxDst
->nBlockAlign
= 1;
844 fill_in_wfx(adfs
->cbwfxDst
, adfs
->pwfxDst
, 192000);
851 return MMSYSERR_NOERROR
;
854 /***********************************************************************
858 static LRESULT
MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMSIZE adss
)
862 switch (adss
->fdwSize
)
864 case ACM_STREAMSIZEF_DESTINATION
:
865 /* cbDstLength => cbSrcLength */
866 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
867 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
)
869 nblocks
= (adss
->cbDstLength
- 3000) / (DWORD
)(adsi
->pwfxDst
->nAvgBytesPerSec
* 1152 / adsi
->pwfxDst
->nSamplesPerSec
+ 0.5);
871 return ACMERR_NOTPOSSIBLE
;
872 adss
->cbSrcLength
= nblocks
* 1152 * adsi
->pwfxSrc
->nBlockAlign
;
874 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
&&
875 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
877 nblocks
= adss
->cbDstLength
/ (adsi
->pwfxDst
->nBlockAlign
* 1152);
879 return ACMERR_NOTPOSSIBLE
;
880 adss
->cbSrcLength
= nblocks
* (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
);
884 return MMSYSERR_NOTSUPPORTED
;
887 case ACM_STREAMSIZEF_SOURCE
:
888 /* cbSrcLength => cbDstLength */
889 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
890 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
)
892 nblocks
= adss
->cbSrcLength
/ (adsi
->pwfxSrc
->nBlockAlign
* 1152);
894 return ACMERR_NOTPOSSIBLE
;
895 if (adss
->cbSrcLength
% (DWORD
)(adsi
->pwfxSrc
->nBlockAlign
* 1152))
896 /* Round block count up. */
898 adss
->cbDstLength
= 3000 + nblocks
* (DWORD
)(adsi
->pwfxDst
->nAvgBytesPerSec
* 1152 / adsi
->pwfxDst
->nSamplesPerSec
+ 0.5);
900 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
&&
901 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
903 nblocks
= adss
->cbSrcLength
/ (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
);
905 return ACMERR_NOTPOSSIBLE
;
906 if (adss
->cbSrcLength
% (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
))
907 /* Round block count up. */
909 adss
->cbDstLength
= nblocks
* 1152 * adsi
->pwfxDst
->nBlockAlign
;
913 return MMSYSERR_NOTSUPPORTED
;
917 WARN("Unsupported query %08x\n", adss
->fdwSize
);
918 return MMSYSERR_NOTSUPPORTED
;
920 return MMSYSERR_NOERROR
;
923 /***********************************************************************
924 * MPEG3_StreamConvert
927 static LRESULT
MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMHEADER adsh
)
929 AcmMpeg3Data
* aad
= (AcmMpeg3Data
*)adsi
->dwDriver
;
930 DWORD nsrc
= adsh
->cbSrcLength
;
931 DWORD ndst
= adsh
->cbDstLength
;
933 if (adsh
->fdwConvert
&
934 ~(ACM_STREAMCONVERTF_BLOCKALIGN
|
935 ACM_STREAMCONVERTF_END
|
936 ACM_STREAMCONVERTF_START
))
938 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh
->fdwConvert
);
940 /* ACM_STREAMCONVERTF_BLOCKALIGN
941 * currently all conversions are block aligned, so do nothing for this flag
942 * ACM_STREAMCONVERTF_END
943 * no pending data, so do nothing for this flag
945 if ((adsh
->fdwConvert
& ACM_STREAMCONVERTF_START
))
947 MPEG3_Reset(adsi
, aad
);
950 aad
->convert(adsi
, adsh
->pbSrc
, &nsrc
, adsh
->pbDst
, &ndst
);
951 adsh
->cbSrcLengthUsed
= nsrc
;
952 adsh
->cbDstLengthUsed
= ndst
;
954 return MMSYSERR_NOERROR
;
957 /**************************************************************************
958 * MPEG3_DriverProc [exported]
960 LRESULT CALLBACK
MPEG3_DriverProc(DWORD_PTR dwDevID
, HDRVR hDriv
, UINT wMsg
,
961 LPARAM dwParam1
, LPARAM dwParam2
)
963 TRACE("(%08lx %p %04x %08lx %08lx);\n",
964 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
968 case DRV_LOAD
: return 1;
969 case DRV_FREE
: return 1;
970 case DRV_OPEN
: return MPEG3_drvOpen((LPSTR
)dwParam1
);
971 case DRV_CLOSE
: return MPEG3_drvClose(dwDevID
);
972 case DRV_ENABLE
: return 1;
973 case DRV_DISABLE
: return 1;
974 case DRV_QUERYCONFIGURE
: return 1;
975 case DRV_CONFIGURE
: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK
); return 1;
976 case DRV_INSTALL
: return DRVCNF_RESTART
;
977 case DRV_REMOVE
: return DRVCNF_RESTART
;
979 case ACMDM_DRIVER_NOTIFY
:
980 /* no caching from other ACM drivers is done so far */
981 return MMSYSERR_NOERROR
;
983 case ACMDM_DRIVER_DETAILS
:
984 return MPEG3_DriverDetails((PACMDRIVERDETAILSW
)dwParam1
);
986 case ACMDM_FORMATTAG_DETAILS
:
987 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW
)dwParam1
, dwParam2
);
989 case ACMDM_FORMAT_DETAILS
:
990 return MPEG3_FormatDetails((PACMFORMATDETAILSW
)dwParam1
, dwParam2
);
992 case ACMDM_FORMAT_SUGGEST
:
993 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST
)dwParam1
);
995 case ACMDM_STREAM_OPEN
:
996 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE
)dwParam1
);
998 case ACMDM_STREAM_CLOSE
:
999 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE
)dwParam1
);
1001 case ACMDM_STREAM_SIZE
:
1002 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMSIZE
)dwParam2
);
1004 case ACMDM_STREAM_CONVERT
:
1005 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMHEADER
)dwParam2
);
1007 case ACMDM_HARDWARE_WAVE_CAPS_INPUT
:
1008 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
:
1009 /* this converter is not a hardware driver */
1010 case ACMDM_FILTERTAG_DETAILS
:
1011 case ACMDM_FILTER_DETAILS
:
1012 /* this converter is not a filter */
1013 case ACMDM_STREAM_RESET
:
1014 /* only needed for asynchronous driver... we aren't, so just say it */
1015 return MMSYSERR_NOTSUPPORTED
;
1016 case ACMDM_STREAM_PREPARE
:
1017 case ACMDM_STREAM_UNPREPARE
:
1018 /* nothing special to do here... so don't do anything */
1019 return MMSYSERR_NOERROR
;
1022 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);