Merge svn changes up to r29277
[mplayer.git] / libmpcodecs / ad_qtaudio.c
blob6feeee25b33bb095612ae76ff7a9dfe40dd89a3a
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <inttypes.h>
6 #include "config.h"
7 #include "mp_msg.h"
8 #include "mpbswap.h"
9 #include "ad_internal.h"
11 #ifdef CONFIG_QUICKTIME
12 #include <QuickTime/QuickTimeComponents.h>
13 #else
14 #include "loader/ldt_keeper.h"
15 #include "loader/wine/windef.h"
16 #endif
18 static const ad_info_t info = {
19 "QuickTime Audio Decoder",
20 "qtaudio",
21 "A'rpi",
22 "Sascha Sommer",
23 "uses win32 quicktime DLLs"
26 LIBAD_EXTERN(qtaudio)
28 #ifndef CONFIG_QUICKTIME
29 typedef struct OpaqueSoundConverter* SoundConverter;
30 typedef unsigned long OSType;
31 typedef unsigned long UnsignedFixed;
32 typedef uint8_t Byte;
33 typedef struct SoundComponentData {
34 long flags;
35 OSType format;
36 short numChannels;
37 short sampleSize;
38 UnsignedFixed sampleRate;
39 long sampleCount;
40 Byte * buffer;
41 long reserved;
42 }SoundComponentData;
44 typedef int (__cdecl* LPFUNC1)(long flag);
45 typedef int (__cdecl* LPFUNC2)(const SoundComponentData *, const SoundComponentData *,SoundConverter *);
46 typedef int (__cdecl* LPFUNC3)(SoundConverter sc);
47 typedef int (__cdecl* LPFUNC4)(void);
48 typedef int (__cdecl* LPFUNC5)(SoundConverter sc, OSType selector,void * infoPtr);
49 typedef int (__cdecl* LPFUNC6)(SoundConverter sc,
50 unsigned long inputBytesTarget,
51 unsigned long *inputFrames,
52 unsigned long *inputBytes,
53 unsigned long *outputBytes );
54 typedef int (__cdecl* LPFUNC7)(SoundConverter sc,
55 const void *inputPtr,
56 unsigned long inputFrames,
57 void *outputPtr,
58 unsigned long *outputFrames,
59 unsigned long *outputBytes );
60 typedef int (__cdecl* LPFUNC8)(SoundConverter sc,
61 void *outputPtr,
62 unsigned long *outputFrames,
63 unsigned long *outputBytes);
64 typedef int (__cdecl* LPFUNC9)(SoundConverter sc) ;
66 static HINSTANCE qtime_qts; // handle to the preloaded quicktime.qts
67 static HINSTANCE qtml_dll;
68 static LPFUNC1 InitializeQTML;
69 static LPFUNC2 SoundConverterOpen;
70 static LPFUNC3 SoundConverterClose;
71 static LPFUNC4 TerminateQTML;
72 static LPFUNC5 SoundConverterSetInfo;
73 static LPFUNC6 SoundConverterGetBufferSizes;
74 static LPFUNC7 SoundConverterConvertBuffer;
75 static LPFUNC8 SoundConverterEndConversion;
76 static LPFUNC9 SoundConverterBeginConversion;
78 #define siDecompressionParams 2002876005 // siDecompressionParams = FOUR_CHAR_CODE('wave')
80 HMODULE WINAPI LoadLibraryA(LPCSTR);
81 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
82 int WINAPI FreeLibrary(HMODULE);
84 static int loader_init(void)
87 #ifdef WIN32_LOADER
88 Setup_LDT_Keeper();
89 #endif
90 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
91 qtime_qts = LoadLibraryA("QuickTime.qts");
92 if( qtime_qts == (HMODULE)NULL )
94 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed loading QuickTime.qts\n" );
95 return 1;
97 qtml_dll = LoadLibraryA("qtmlClient.dll");
98 if( qtml_dll == (HMODULE)NULL )
100 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed loading qtmlClient.dll\n" );
101 return 1;
103 #if 1
104 InitializeQTML = (LPFUNC1)GetProcAddress(qtml_dll,"InitializeQTML");
105 if ( InitializeQTML == NULL )
107 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed geting proc address InitializeQTML\n");
108 return 1;
110 SoundConverterOpen = (LPFUNC2)GetProcAddress(qtml_dll,"SoundConverterOpen");
111 if ( SoundConverterOpen == NULL )
113 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterOpen\n");
114 return 1;
116 SoundConverterClose = (LPFUNC3)GetProcAddress(qtml_dll,"SoundConverterClose");
117 if ( SoundConverterClose == NULL )
119 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterClose\n");
120 return 1;
122 TerminateQTML = (LPFUNC4)GetProcAddress(qtml_dll,"TerminateQTML");
123 if ( TerminateQTML == NULL )
125 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address TerminateQTML\n");
126 return 1;
128 SoundConverterSetInfo = (LPFUNC5)GetProcAddress(qtml_dll,"SoundConverterSetInfo");
129 if ( SoundConverterSetInfo == NULL )
131 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterSetInfo\n");
132 return 1;
134 SoundConverterGetBufferSizes = (LPFUNC6)GetProcAddress(qtml_dll,"SoundConverterGetBufferSizes");
135 if ( SoundConverterGetBufferSizes == NULL )
137 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterGetBufferSizes\n");
138 return 1;
140 SoundConverterConvertBuffer = (LPFUNC7)GetProcAddress(qtml_dll,"SoundConverterConvertBuffer");
141 if ( SoundConverterConvertBuffer == NULL )
143 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterConvertBuffer1\n");
144 return 1;
146 SoundConverterEndConversion = (LPFUNC8)GetProcAddress(qtml_dll,"SoundConverterEndConversion");
147 if ( SoundConverterEndConversion == NULL )
149 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterEndConversion\n");
150 return 1;
152 SoundConverterBeginConversion = (LPFUNC9)GetProcAddress(qtml_dll,"SoundConverterBeginConversion");
153 if ( SoundConverterBeginConversion == NULL )
155 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"failed getting proc address SoundConverterBeginConversion\n");
156 return 1;
158 #endif
159 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"loader_init DONE???\n");
160 return 0;
162 #endif /* #ifndef CONFIG_QUICKTIME */
164 static SoundConverter myConverter = NULL;
165 static SoundComponentData InputFormatInfo,OutputFormatInfo;
167 static int InFrameSize;
168 static int OutFrameSize;
170 static int preinit(sh_audio_t *sh){
171 int error;
172 unsigned long FramesToGet=0; //how many frames the demuxer has to get
173 unsigned long InputBufferSize=0; //size of the input buffer
174 unsigned long OutputBufferSize=0; //size of the output buffer
175 unsigned long WantedBufferSize=0; //the size you want your buffers to be
178 #ifdef CONFIG_QUICKTIME
179 EnterMovies();
180 #else
181 if(loader_init()) return 0; // failed to load DLL
183 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"loader_init DONE!\n");
185 error = InitializeQTML(6+16);
186 if(error){
187 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"InitializeQTML:%i\n",error);
188 return 0;
190 #endif
192 #if 1
193 OutputFormatInfo.flags = InputFormatInfo.flags = 0;
194 OutputFormatInfo.sampleCount = InputFormatInfo.sampleCount = 0;
195 OutputFormatInfo.buffer = InputFormatInfo.buffer = NULL;
196 OutputFormatInfo.reserved = InputFormatInfo.reserved = 0;
197 OutputFormatInfo.numChannels = InputFormatInfo.numChannels = sh->wf->nChannels;
198 InputFormatInfo.sampleSize = sh->wf->wBitsPerSample;
199 OutputFormatInfo.sampleSize = 16;
200 OutputFormatInfo.sampleRate = InputFormatInfo.sampleRate = sh->wf->nSamplesPerSec;
201 InputFormatInfo.format = bswap_32(sh->format); //1363430706;///*1768775988;//*/1902406962;//qdm2//1768775988;//FOUR_CHAR_CODE('ima4');
202 OutputFormatInfo.format = 1313820229;// FOUR_CHAR_CODE('NONE');
204 error = SoundConverterOpen(&InputFormatInfo, &OutputFormatInfo, &myConverter);
205 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterOpen:%i\n",error);
206 if(error) return 0;
208 if(sh->codecdata){
209 error = SoundConverterSetInfo(myConverter,siDecompressionParams,sh->codecdata);
210 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterSetInfo:%i\n",error);
211 // if(error) return 0;
214 WantedBufferSize=OutputFormatInfo.numChannels*OutputFormatInfo.sampleRate*2;
215 error = SoundConverterGetBufferSizes(myConverter,
216 WantedBufferSize,&FramesToGet,&InputBufferSize,&OutputBufferSize);
217 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterGetBufferSizes:%i\n",error);
218 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"WantedBufferSize = %li\n",WantedBufferSize);
219 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"InputBufferSize = %li\n",InputBufferSize);
220 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OutputBufferSize = %li\n",OutputBufferSize);
221 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FramesToGet = %li\n",FramesToGet);
223 InFrameSize=(InputBufferSize+FramesToGet-1)/FramesToGet;
224 OutFrameSize=OutputBufferSize/FramesToGet;
226 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FrameSize: %i -> %i\n",InFrameSize,OutFrameSize);
228 error = SoundConverterBeginConversion(myConverter);
229 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterBeginConversion:%i\n",error);
230 if(error) return 0;
232 sh->audio_out_minsize=OutputBufferSize;
233 sh->audio_in_minsize=InputBufferSize;
235 sh->channels=sh->wf->nChannels;
236 sh->samplerate=sh->wf->nSamplesPerSec;
237 sh->samplesize=2; //(sh->wf->wBitsPerSample+7)/8;
239 sh->i_bps=sh->wf->nAvgBytesPerSec;
240 //InputBufferSize*WantedBufferSize/OutputBufferSize;
242 #endif
244 if(sh->format==0x3343414D){
245 // MACE 3:1
246 sh->ds->ss_div = 2*3; // 1 samples/packet
247 sh->ds->ss_mul = sh->channels*2*1; // 1 bytes/packet
248 } else
249 if(sh->format==0x3643414D){
250 // MACE 6:1
251 sh->ds->ss_div = 2*6; // 1 samples/packet
252 sh->ds->ss_mul = sh->channels*2*1; // 1 bytes/packet
255 return 1; // return values: 1=OK 0=ERROR
258 static int init(sh_audio_t *sh_audio){
260 return 1; // return values: 1=OK 0=ERROR
263 static void uninit(sh_audio_t *sh){
264 int error;
265 unsigned long ConvertedFrames=0;
266 unsigned long ConvertedBytes=0;
267 error=SoundConverterEndConversion(myConverter,NULL,&ConvertedFrames,&ConvertedBytes);
268 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterEndConversion:%i\n",error);
269 error = SoundConverterClose(myConverter);
270 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"SoundConverterClose:%i\n",error);
271 // error = TerminateQTML();
272 // printf("TerminateQTML:%i\n",error);
273 // FreeLibrary( qtml_dll );
274 // qtml_dll = NULL;
275 // FreeLibrary( qtime_qts );
276 // qtime_qts = NULL;
277 // printf("qt dll loader uninit done\n");
278 #ifdef CONFIG_QUICKTIME
279 ExitMovies();
280 #endif
283 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){
284 int error;
285 unsigned long FramesToGet=0; //how many frames the demuxer has to get
286 unsigned long InputBufferSize=0; //size of the input buffer
287 unsigned long ConvertedFrames=0;
288 unsigned long ConvertedBytes=0;
290 FramesToGet=minlen/OutFrameSize;
291 if(FramesToGet*OutFrameSize<minlen &&
292 (FramesToGet+1)*OutFrameSize<=maxlen) ++FramesToGet;
293 if(FramesToGet*InFrameSize>sh->a_in_buffer_size)
294 FramesToGet=sh->a_in_buffer_size/InFrameSize;
296 InputBufferSize=FramesToGet*InFrameSize;
298 // printf("FramesToGet = %li (%li -> %li bytes)\n",FramesToGet,
299 // InputBufferSize, FramesToGet*OutFrameSize);
301 if(InputBufferSize>sh->a_in_buffer_len){
302 int x=demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
303 InputBufferSize-sh->a_in_buffer_len);
304 if(x>0) sh->a_in_buffer_len+=x;
305 if(InputBufferSize>sh->a_in_buffer_len)
306 FramesToGet=sh->a_in_buffer_len/InFrameSize; // not enough data!
309 // printf("\nSoundConverterConvertBuffer(myConv=%p,inbuf=%p,frames=%d,outbuf=%p,&convframes=%p,&convbytes=%p)\n",
310 // myConverter,sh->a_in_buffer,FramesToGet,buf,&ConvertedFrames,&ConvertedBytes);
311 error = SoundConverterConvertBuffer(myConverter,sh->a_in_buffer,
312 FramesToGet,buf,&ConvertedFrames,&ConvertedBytes);
313 // printf("SoundConverterConvertBuffer:%i\n",error);
314 // printf("ConvertedFrames = %li\n",ConvertedFrames);
315 // printf("ConvertedBytes = %li\n",ConvertedBytes);
317 // InputBufferSize=(ConvertedBytes/OutFrameSize)*InFrameSize; // FIXME!!
318 InputBufferSize=FramesToGet*InFrameSize;
319 sh->a_in_buffer_len-=InputBufferSize;
320 if(sh->a_in_buffer_len<0) sh->a_in_buffer_len=0; // should not happen...
321 else if(sh->a_in_buffer_len>0){
322 memcpy(sh->a_in_buffer,&sh->a_in_buffer[InputBufferSize],sh->a_in_buffer_len);
325 return ConvertedBytes;
328 static int control(sh_audio_t *sh,int cmd,void* arg, ...){
329 // various optional functions you MAY implement:
330 return CONTROL_UNKNOWN;