Merge svn changes up to r27441
[mplayer.git] / libmpcodecs / ad_qtaudio.c
blobcfc5dd26f8e418e5ee77011611a3e810ab399a76
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <inttypes.h>
6 #include "config.h"
8 #ifdef CONFIG_QUICKTIME
9 #include <QuickTime/QuickTimeComponents.h>
10 #endif
12 #include "mp_msg.h"
14 #include "loader/wine/windef.h"
16 #include "ad_internal.h"
17 #include "mpbswap.h"
19 #ifdef WIN32_LOADER
20 #include "loader/ldt_keeper.h"
21 #endif
23 static const ad_info_t info = {
24 "QuickTime Audio Decoder",
25 "qtaudio",
26 "A'rpi",
27 "Sascha Sommer",
28 "uses win32 quicktime DLLs"
31 LIBAD_EXTERN(qtaudio)
33 #ifndef CONFIG_QUICKTIME
34 typedef struct OpaqueSoundConverter* SoundConverter;
35 typedef unsigned long OSType;
36 typedef unsigned long UnsignedFixed;
37 typedef uint8_t Byte;
38 typedef struct SoundComponentData {
39 long flags;
40 OSType format;
41 short numChannels;
42 short sampleSize;
43 UnsignedFixed sampleRate;
44 long sampleCount;
45 Byte * buffer;
46 long reserved;
47 }SoundComponentData;
49 typedef int (__cdecl* LPFUNC1)(long flag);
50 typedef int (__cdecl* LPFUNC2)(const SoundComponentData *, const SoundComponentData *,SoundConverter *);
51 typedef int (__cdecl* LPFUNC3)(SoundConverter sc);
52 typedef int (__cdecl* LPFUNC4)(void);
53 typedef int (__cdecl* LPFUNC5)(SoundConverter sc, OSType selector,void * infoPtr);
54 typedef int (__cdecl* LPFUNC6)(SoundConverter sc,
55 unsigned long inputBytesTarget,
56 unsigned long *inputFrames,
57 unsigned long *inputBytes,
58 unsigned long *outputBytes );
59 typedef int (__cdecl* LPFUNC7)(SoundConverter sc,
60 const void *inputPtr,
61 unsigned long inputFrames,
62 void *outputPtr,
63 unsigned long *outputFrames,
64 unsigned long *outputBytes );
65 typedef int (__cdecl* LPFUNC8)(SoundConverter sc,
66 void *outputPtr,
67 unsigned long *outputFrames,
68 unsigned long *outputBytes);
69 typedef int (__cdecl* LPFUNC9)(SoundConverter sc) ;
71 static HINSTANCE qtime_qts; // handle to the preloaded quicktime.qts
72 static HINSTANCE qtml_dll;
73 static LPFUNC1 InitializeQTML;
74 static LPFUNC2 SoundConverterOpen;
75 static LPFUNC3 SoundConverterClose;
76 static LPFUNC4 TerminateQTML;
77 static LPFUNC5 SoundConverterSetInfo;
78 static LPFUNC6 SoundConverterGetBufferSizes;
79 static LPFUNC7 SoundConverterConvertBuffer;
80 static LPFUNC8 SoundConverterEndConversion;
81 static LPFUNC9 SoundConverterBeginConversion;
83 #define siDecompressionParams 2002876005 // siDecompressionParams = FOUR_CHAR_CODE('wave')
85 HMODULE WINAPI LoadLibraryA(LPCSTR);
86 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
87 int WINAPI FreeLibrary(HMODULE);
89 static int loader_init()
92 #ifdef WIN32_LOADER
93 Setup_LDT_Keeper();
94 #endif
95 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
96 qtime_qts = LoadLibraryA("QuickTime.qts");
97 if( qtime_qts == (HMODULE)NULL )
99 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed loading QuickTime.qts\n" );
100 return 1;
102 qtml_dll = LoadLibraryA("qtmlClient.dll");
103 if( qtml_dll == (HMODULE)NULL )
105 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed loading qtmlClient.dll\n" );
106 return 1;
108 #if 1
109 InitializeQTML = (LPFUNC1)GetProcAddress(qtml_dll,"InitializeQTML");
110 if ( InitializeQTML == NULL )
112 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed geting proc address InitializeQTML\n");
113 return 1;
115 SoundConverterOpen = (LPFUNC2)GetProcAddress(qtml_dll,"SoundConverterOpen");
116 if ( SoundConverterOpen == NULL )
118 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterOpen\n");
119 return 1;
121 SoundConverterClose = (LPFUNC3)GetProcAddress(qtml_dll,"SoundConverterClose");
122 if ( SoundConverterClose == NULL )
124 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterClose\n");
125 return 1;
127 TerminateQTML = (LPFUNC4)GetProcAddress(qtml_dll,"TerminateQTML");
128 if ( TerminateQTML == NULL )
130 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address TerminateQTML\n");
131 return 1;
133 SoundConverterSetInfo = (LPFUNC5)GetProcAddress(qtml_dll,"SoundConverterSetInfo");
134 if ( SoundConverterSetInfo == NULL )
136 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterSetInfo\n");
137 return 1;
139 SoundConverterGetBufferSizes = (LPFUNC6)GetProcAddress(qtml_dll,"SoundConverterGetBufferSizes");
140 if ( SoundConverterGetBufferSizes == NULL )
142 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterGetBufferSizes\n");
143 return 1;
145 SoundConverterConvertBuffer = (LPFUNC7)GetProcAddress(qtml_dll,"SoundConverterConvertBuffer");
146 if ( SoundConverterConvertBuffer == NULL )
148 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterConvertBuffer1\n");
149 return 1;
151 SoundConverterEndConversion = (LPFUNC8)GetProcAddress(qtml_dll,"SoundConverterEndConversion");
152 if ( SoundConverterEndConversion == NULL )
154 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterEndConversion\n");
155 return 1;
157 SoundConverterBeginConversion = (LPFUNC9)GetProcAddress(qtml_dll,"SoundConverterBeginConversion");
158 if ( SoundConverterBeginConversion == NULL )
160 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterBeginConversion\n");
161 return 1;
163 #endif
164 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"loader_init DONE???\n");
165 return 0;
167 #endif /* #ifndef CONFIG_QUICKTIME */
169 static SoundConverter myConverter = NULL;
170 static SoundComponentData InputFormatInfo,OutputFormatInfo;
172 static int InFrameSize;
173 static int OutFrameSize;
175 static int preinit(sh_audio_t *sh){
176 int error;
177 unsigned long FramesToGet=0; //how many frames the demuxer has to get
178 unsigned long InputBufferSize=0; //size of the input buffer
179 unsigned long OutputBufferSize=0; //size of the output buffer
180 unsigned long WantedBufferSize=0; //the size you want your buffers to be
183 #ifdef CONFIG_QUICKTIME
184 EnterMovies();
185 #else
186 if(loader_init()) return 0; // failed to load DLL
188 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"loader_init DONE!\n");
190 error = InitializeQTML(6+16);
191 if(error){
192 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"InitializeQTML:%i\n",error);
193 return 0;
195 #endif
197 #if 1
198 OutputFormatInfo.flags = InputFormatInfo.flags = 0;
199 OutputFormatInfo.sampleCount = InputFormatInfo.sampleCount = 0;
200 OutputFormatInfo.buffer = InputFormatInfo.buffer = NULL;
201 OutputFormatInfo.reserved = InputFormatInfo.reserved = 0;
202 OutputFormatInfo.numChannels = InputFormatInfo.numChannels = sh->wf->nChannels;
203 InputFormatInfo.sampleSize = sh->wf->wBitsPerSample;
204 OutputFormatInfo.sampleSize = 16;
205 OutputFormatInfo.sampleRate = InputFormatInfo.sampleRate = sh->wf->nSamplesPerSec;
206 InputFormatInfo.format = bswap_32(sh->format); //1363430706;///*1768775988;//*/1902406962;//qdm2//1768775988;//FOUR_CHAR_CODE('ima4');
207 OutputFormatInfo.format = 1313820229;// FOUR_CHAR_CODE('NONE');
209 error = SoundConverterOpen(&InputFormatInfo, &OutputFormatInfo, &myConverter);
210 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterOpen:%i\n",error);
211 if(error) return 0;
213 if(sh->codecdata){
214 error = SoundConverterSetInfo(myConverter,siDecompressionParams,sh->codecdata);
215 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterSetInfo:%i\n",error);
216 // if(error) return 0;
219 WantedBufferSize=OutputFormatInfo.numChannels*OutputFormatInfo.sampleRate*2;
220 error = SoundConverterGetBufferSizes(myConverter,
221 WantedBufferSize,&FramesToGet,&InputBufferSize,&OutputBufferSize);
222 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterGetBufferSizes:%i\n",error);
223 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"WantedBufferSize = %li\n",WantedBufferSize);
224 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"InputBufferSize = %li\n",InputBufferSize);
225 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OutputBufferSize = %li\n",OutputBufferSize);
226 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FramesToGet = %li\n",FramesToGet);
228 InFrameSize=(InputBufferSize+FramesToGet-1)/FramesToGet;
229 OutFrameSize=OutputBufferSize/FramesToGet;
231 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FrameSize: %i -> %i\n",InFrameSize,OutFrameSize);
233 error = SoundConverterBeginConversion(myConverter);
234 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterBeginConversion:%i\n",error);
235 if(error) return 0;
237 sh->audio_out_minsize=OutputBufferSize;
238 sh->audio_in_minsize=InputBufferSize;
240 sh->channels=sh->wf->nChannels;
241 sh->samplerate=sh->wf->nSamplesPerSec;
242 sh->samplesize=2; //(sh->wf->wBitsPerSample+7)/8;
244 sh->i_bps=sh->wf->nAvgBytesPerSec;
245 //InputBufferSize*WantedBufferSize/OutputBufferSize;
247 #endif
249 if(sh->format==0x3343414D){
250 // MACE 3:1
251 sh->ds->ss_div = 2*3; // 1 samples/packet
252 sh->ds->ss_mul = sh->channels*2*1; // 1 bytes/packet
253 } else
254 if(sh->format==0x3643414D){
255 // MACE 6:1
256 sh->ds->ss_div = 2*6; // 1 samples/packet
257 sh->ds->ss_mul = sh->channels*2*1; // 1 bytes/packet
260 return 1; // return values: 1=OK 0=ERROR
263 static int init(sh_audio_t *sh_audio){
265 return 1; // return values: 1=OK 0=ERROR
268 static void uninit(sh_audio_t *sh){
269 int error;
270 unsigned long ConvertedFrames=0;
271 unsigned long ConvertedBytes=0;
272 error=SoundConverterEndConversion(myConverter,NULL,&ConvertedFrames,&ConvertedBytes);
273 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterEndConversion:%i\n",error);
274 error = SoundConverterClose(myConverter);
275 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterClose:%i\n",error);
276 // error = TerminateQTML();
277 // printf("TerminateQTML:%i\n",error);
278 // FreeLibrary( qtml_dll );
279 // qtml_dll = NULL;
280 // FreeLibrary( qtime_qts );
281 // qtime_qts = NULL;
282 // printf("qt dll loader uninit done\n");
283 #ifdef CONFIG_QUICKTIME
284 ExitMovies();
285 #endif
288 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){
289 int error;
290 unsigned long FramesToGet=0; //how many frames the demuxer has to get
291 unsigned long InputBufferSize=0; //size of the input buffer
292 unsigned long ConvertedFrames=0;
293 unsigned long ConvertedBytes=0;
295 FramesToGet=minlen/OutFrameSize;
296 if(FramesToGet*OutFrameSize<minlen &&
297 (FramesToGet+1)*OutFrameSize<=maxlen) ++FramesToGet;
298 if(FramesToGet*InFrameSize>sh->a_in_buffer_size)
299 FramesToGet=sh->a_in_buffer_size/InFrameSize;
301 InputBufferSize=FramesToGet*InFrameSize;
303 // printf("FramesToGet = %li (%li -> %li bytes)\n",FramesToGet,
304 // InputBufferSize, FramesToGet*OutFrameSize);
306 if(InputBufferSize>sh->a_in_buffer_len){
307 int x=demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
308 InputBufferSize-sh->a_in_buffer_len);
309 if(x>0) sh->a_in_buffer_len+=x;
310 if(InputBufferSize>sh->a_in_buffer_len)
311 FramesToGet=sh->a_in_buffer_len/InFrameSize; // not enough data!
314 // printf("\nSoundConverterConvertBuffer(myConv=%p,inbuf=%p,frames=%d,outbuf=%p,&convframes=%p,&convbytes=%p)\n",
315 // myConverter,sh->a_in_buffer,FramesToGet,buf,&ConvertedFrames,&ConvertedBytes);
316 error = SoundConverterConvertBuffer(myConverter,sh->a_in_buffer,
317 FramesToGet,buf,&ConvertedFrames,&ConvertedBytes);
318 // printf("SoundConverterConvertBuffer:%i\n",error);
319 // printf("ConvertedFrames = %li\n",ConvertedFrames);
320 // printf("ConvertedBytes = %li\n",ConvertedBytes);
322 // InputBufferSize=(ConvertedBytes/OutFrameSize)*InFrameSize; // FIXME!!
323 InputBufferSize=FramesToGet*InFrameSize;
324 sh->a_in_buffer_len-=InputBufferSize;
325 if(sh->a_in_buffer_len<0) sh->a_in_buffer_len=0; // should not happen...
326 else if(sh->a_in_buffer_len>0){
327 memcpy(sh->a_in_buffer,&sh->a_in_buffer[InputBufferSize],sh->a_in_buffer_len);
330 return ConvertedBytes;
333 static int control(sh_audio_t *sh,int cmd,void* arg, ...){
334 // various optional functions you MAY implement:
335 return CONTROL_UNKNOWN;