adding the code documentation guide lines
[mplayer/glamo.git] / libmpcodecs / ad_realaud.c
blobb6bcae8a653d418b3ff6bca8d721abc2f108b6dd
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
6 #include "config.h"
8 #ifdef USE_REALCODECS
10 //#include <stddef.h>
11 #ifdef HAVE_LIBDL
12 #include <dlfcn.h>
13 #endif
14 #include "help_mp.h"
16 #include "ad_internal.h"
17 #include "wine/windef.h"
19 #ifdef USE_MACSHLB
20 #include <CoreServices/CoreServices.h>
21 #endif
23 static ad_info_t info = {
24 "RealAudio decoder",
25 "realaud",
26 "Alex Beregszaszi",
27 "Florian Schneider, Arpad Gereoffy, Alex Beregszaszi, Donnie Smith",
28 "binary real audio codecs"
31 LIBAD_EXTERN(realaud)
33 void *__builtin_new(unsigned long size) {
34 return malloc(size);
37 // required for cook's uninit:
38 void __builtin_delete(void* ize) {
39 free(ize);
42 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
43 void *__ctype_b=NULL;
44 #endif
46 static unsigned long (*raCloseCodec)(void*);
47 static unsigned long (*raDecode)(void*, char*,unsigned long,char*,unsigned int*,long);
48 static unsigned long (*raFlush)(unsigned long,unsigned long,unsigned long);
49 static unsigned long (*raFreeDecoder)(void*);
50 static void* (*raGetFlavorProperty)(void*,unsigned long,unsigned long,int*);
51 //static unsigned long (*raGetNumberOfFlavors2)(void);
52 static unsigned long (*raInitDecoder)(void*, void*);
53 static unsigned long (*raOpenCodec)(void*);
54 static unsigned long (*raOpenCodec2)(void*, void*);
55 static unsigned long (*raSetFlavor)(void*,unsigned long);
56 static void (*raSetDLLAccessPath)(char*);
57 static void (*raSetPwd)(char*,char*);
58 #ifdef USE_WIN32DLL
59 static unsigned long WINAPI (*wraCloseCodec)(void*);
60 static unsigned long WINAPI (*wraDecode)(void*, char*,unsigned long,char*,unsigned int*,long);
61 static unsigned long WINAPI (*wraFlush)(unsigned long,unsigned long,unsigned long);
62 static unsigned long WINAPI (*wraFreeDecoder)(void*);
63 static void* WINAPI (*wraGetFlavorProperty)(void*,unsigned long,unsigned long,int*);
64 static unsigned long WINAPI (*wraInitDecoder)(void*, void*);
65 static unsigned long WINAPI (*wraOpenCodec)(void*);
66 static unsigned long WINAPI (*wraOpenCodec2)(void*, void*);
67 static unsigned long WINAPI (*wraSetFlavor)(void*,unsigned long);
68 static void WINAPI (*wraSetDLLAccessPath)(char*);
69 static void WINAPI (*wraSetPwd)(char*,char*);
71 static int dll_type = 0; /* 0 = unix dlopen, 1 = win32 dll */
72 #endif
74 static void *rv_handle = NULL;
76 #if 0
77 typedef struct {
78 int samplerate;
79 short bits;
80 short channels;
81 int unk1;
82 int unk2;
83 int packetsize;
84 int unk3;
85 void* unk4;
86 } ra_init_t ;
87 #else
90 Probably the linux .so-s were compiled with old GCC without setting
91 packing, so it adds 2 bytes padding after the quality field.
92 In windows it seems that there's no padding in it.
94 -- alex
97 /* linux dlls doesn't need packing */
98 typedef struct /*__attribute__((__packed__))*/ {
99 int samplerate;
100 short bits;
101 short channels;
102 short quality;
103 /* 2bytes padding here, by gcc */
104 int bits_per_frame;
105 int packetsize;
106 int extradata_len;
107 void* extradata;
108 } ra_init_t;
110 /* windows dlls need packed structs (no padding) */
111 typedef struct __attribute__((__packed__)) {
112 int samplerate;
113 short bits;
114 short channels;
115 short quality;
116 int bits_per_frame;
117 int packetsize;
118 int extradata_len;
119 void* extradata;
120 } wra_init_t;
121 #endif
123 #ifdef HAVE_LIBDL
124 static int load_syms_linux(char *path)
126 void *handle;
128 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "opening shared obj '%s'\n", path);
129 handle = dlopen(path, RTLD_LAZY);
130 if (!handle)
132 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error: %s\n", dlerror());
133 return 0;
136 raCloseCodec = dlsym(handle, "RACloseCodec");
137 raDecode = dlsym(handle, "RADecode");
138 raFlush = dlsym(handle, "RAFlush");
139 raFreeDecoder = dlsym(handle, "RAFreeDecoder");
140 raGetFlavorProperty = dlsym(handle, "RAGetFlavorProperty");
141 raOpenCodec = dlsym(handle, "RAOpenCodec");
142 raOpenCodec2 = dlsym(handle, "RAOpenCodec2");
143 raInitDecoder = dlsym(handle, "RAInitDecoder");
144 raSetFlavor = dlsym(handle, "RASetFlavor");
145 raSetDLLAccessPath = dlsym(handle, "SetDLLAccessPath");
146 raSetPwd = dlsym(handle, "RASetPwd"); // optional, used by SIPR
148 if (raCloseCodec && raDecode && /*raFlush && */raFreeDecoder &&
149 raGetFlavorProperty && (raOpenCodec||raOpenCodec2) && raSetFlavor &&
150 /*raSetDLLAccessPath &&*/ raInitDecoder)
152 rv_handle = handle;
153 return 1;
156 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Cannot resolve symbols - incompatible dll: %s\n",path);
157 dlclose(handle);
158 return 0;
160 #endif
162 #ifdef USE_WIN32DLL
164 #ifdef WIN32_LOADER
165 #include "../loader/ldt_keeper.h"
166 #endif
167 void* WINAPI LoadLibraryA(char* name);
168 void* WINAPI GetProcAddress(void* handle,char *func);
169 int WINAPI FreeLibrary(void *handle);
171 static int load_syms_windows(char *path)
173 void *handle;
175 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "opening win32 dll '%s'\n", path);
176 #ifdef WIN32_LOADER
177 Setup_LDT_Keeper();
178 #endif
179 handle = LoadLibraryA(path);
180 if (!handle)
182 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error loading dll\n");
183 return 0;
186 wraCloseCodec = GetProcAddress(handle, "RACloseCodec");
187 wraDecode = GetProcAddress(handle, "RADecode");
188 wraFlush = GetProcAddress(handle, "RAFlush");
189 wraFreeDecoder = GetProcAddress(handle, "RAFreeDecoder");
190 wraGetFlavorProperty = GetProcAddress(handle, "RAGetFlavorProperty");
191 wraOpenCodec = GetProcAddress(handle, "RAOpenCodec");
192 wraOpenCodec2 = GetProcAddress(handle, "RAOpenCodec2");
193 wraInitDecoder = GetProcAddress(handle, "RAInitDecoder");
194 wraSetFlavor = GetProcAddress(handle, "RASetFlavor");
195 wraSetDLLAccessPath = GetProcAddress(handle, "SetDLLAccessPath");
196 wraSetPwd = GetProcAddress(handle, "RASetPwd"); // optional, used by SIPR
198 if (wraCloseCodec && wraDecode && /*wraFlush && */wraFreeDecoder &&
199 wraGetFlavorProperty && (wraOpenCodec || wraOpenCodec2) && wraSetFlavor &&
200 /*wraSetDLLAccessPath &&*/ wraInitDecoder)
202 rv_handle = handle;
203 dll_type = 1;
204 return 1;
207 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Cannot resolve symbols - incompatible dll: %s\n",path);
208 FreeLibrary(handle);
209 return 0;
212 #endif
215 #ifdef USE_MACSHLB
217 Helper function to create a function pointer (from a null terminated (!)
218 pascal string) like GetProcAddress(). Some assembler is required due
219 to different calling conventions, for further details, see
220 http://developer.apple.com/ samplecode/CFM_MachO_CFM/listing1.html .
222 Caller is expected to DisposePtr(mfp).
223 N.B.: Code is used by vd_realaud.c as well.
225 void *load_one_sym_mac(char *symbolName, CFragConnectionID *connID) {
226 OSErr err;
227 Ptr symbolAddr;
228 CFragSymbolClass symbolClass;
229 UInt32 *mfp;
230 char realname[255];
232 if (strlen(symbolName) > 255)
234 mp_msg(MSGT_DECVIDEO, MSGL_V, "FindSymbol symbolname overflow\n");
235 return NULL;
238 snprintf(realname, 255, "%c%s", strlen(symbolName), symbolName);
240 if ( (err = FindSymbol( *connID, realname,
241 &symbolAddr, &symbolClass )) != noErr ) {
242 mp_msg(MSGT_DECVIDEO,MSGL_V,"FindSymbol( \"%s\" ) failed with error code %d.\n", symbolName + 1, err );
243 return NULL;
246 if ( (mfp = (UInt32 *)NewPtr( 6 * sizeof(UInt32) )) == nil )
247 return NULL;
249 mfp[0] = 0x3D800000 | ((UInt32)symbolAddr >> 16);
250 mfp[1] = 0x618C0000 | ((UInt32)symbolAddr & 0xFFFF);
251 mfp[2] = 0x800C0000;
252 mfp[3] = 0x804C0004;
253 mfp[4] = 0x7C0903A6;
254 mfp[5] = 0x4E800420;
255 MakeDataExecutable( mfp, 6 * sizeof(UInt32) );
257 return( mfp );
260 static int load_syms_mac(char *path)
262 Ptr mainAddr;
263 OSStatus status;
264 FSRef fsref;
265 FSSpec fsspec;
266 OSErr err;
267 Str255 errMessage;
268 CFragConnectionID *connID;
270 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "opening mac shlb '%s'\n", path);
272 if ( (connID = (CFragConnectionID *)NewPtr( sizeof( CFragConnectionID ))) == nil ) {
273 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"NewPtr() failed.\n" );
274 return 0;
277 if ( (status = FSPathMakeRef( path, &fsref, NULL )) != noErr ) {
278 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSPathMakeRef() failed with error %d.\n", status );
279 return 0;
282 if ( (status = FSGetCatalogInfo( &fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL )) != noErr ) {
283 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"FSGetCatalogInfo() failed with error %d.\n", status );
284 return 0;
287 if ( (err = GetDiskFragment( &fsspec, 0, kCFragGoesToEOF, NULL, kPrivateCFragCopy, connID, &mainAddr, errMessage )) != noErr ) {
289 p2cstrcpy( errMessage, errMessage );
290 mp_msg(MSGT_DECVIDEO,MSGL_WARN,"GetDiskFragment() failed with error %d: %s\n", err, errMessage );
291 return 0;
294 raCloseCodec = load_one_sym_mac( "RACloseCodec", connID);
295 raDecode = load_one_sym_mac("RADecode", connID);
296 raFlush = load_one_sym_mac("RAFlush", connID);
297 raFreeDecoder = load_one_sym_mac("RAFreeDecoder", connID);
298 raGetFlavorProperty = load_one_sym_mac("RAGetFlavorProperty", connID);
299 raOpenCodec = load_one_sym_mac("RAOpenCodec", connID);
300 raOpenCodec2 = load_one_sym_mac("RAOpenCodec2", connID);
301 raInitDecoder = load_one_sym_mac("RAInitDecoder", connID);
302 raSetFlavor = load_one_sym_mac("RASetFlavor", connID);
303 raSetDLLAccessPath = load_one_sym_mac("SetDLLAccessPath", connID);
304 raSetPwd = load_one_sym_mac("RASetPwd", connID); // optional, used by SIPR
306 if (raCloseCodec && raDecode && /*raFlush && */raFreeDecoder &&
307 raGetFlavorProperty && (raOpenCodec || raOpenCodec2) && raSetFlavor &&
308 /*raSetDLLAccessPath &&*/ raInitDecoder)
310 rv_handle = connID;
311 return 1;
314 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Cannot resolve symbols - incompatible shlb: %s\n",path);
315 (void)CloseConnection(connID);
316 return 0;
319 #endif
321 static int preinit(sh_audio_t *sh){
322 // let's check if the driver is available, return 0 if not.
323 // (you should do that if you use external lib(s) which is optional)
324 unsigned int result;
325 int len=0;
326 void* prop;
327 char *path;
329 path = malloc(strlen(REALCODEC_PATH)+strlen(sh->codec->dll)+2);
330 if (!path) return 0;
331 sprintf(path, REALCODEC_PATH "/%s", sh->codec->dll);
333 /* first try to load linux dlls, if failed and we're supporting win32 dlls,
334 then try to load the windows ones */
336 #ifdef USE_MACSHLB
337 if (strstr(sh->codec->dll,".shlb") && !load_syms_mac(path))
338 #endif
339 #ifdef HAVE_LIBDL
340 if (strstr(sh->codec->dll,".dll") || !load_syms_linux(path))
341 #endif
342 #ifdef USE_WIN32DLL
343 if (!load_syms_windows(sh->codec->dll))
344 #endif
346 mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MissingDLLcodec, sh->codec->dll);
347 mp_msg(MSGT_DECVIDEO, MSGL_HINT, "Read the RealAudio section of the DOCS!\n");
348 free(path);
349 return 0;
352 #ifdef USE_WIN32DLL
353 if((raSetDLLAccessPath && dll_type == 0) || (wraSetDLLAccessPath && dll_type == 1)){
354 #else
355 if(raSetDLLAccessPath){
356 #endif
357 int i;
358 // used by 'SIPR'
359 path = realloc(path, strlen(REALCODEC_PATH) + 12);
360 sprintf(path, "DT_Codecs=" REALCODEC_PATH);
361 if(path[strlen(path)-1]!='/'){
362 path[strlen(path)+1]=0;
363 path[strlen(path)]='/';
365 path[strlen(path)+1]=0;
366 #ifdef USE_WIN32DLL
367 if (dll_type == 1)
369 for (i=0; i < strlen(path); i++)
370 if (path[i] == '/') path[i] = '\\';
371 wraSetDLLAccessPath(path);
373 else
374 #endif
375 raSetDLLAccessPath(path);
378 #ifdef USE_WIN32DLL
379 if (dll_type == 1){
380 if(wraOpenCodec2)
381 result=wraOpenCodec2(&sh->context,REALCODEC_PATH "\\");
382 else
383 result=wraOpenCodec(&sh->context);
384 } else
385 #endif
386 if(raOpenCodec2)
387 result=raOpenCodec2(&sh->context,REALCODEC_PATH "/");
388 else
389 result=raOpenCodec(&sh->context);
390 if(result){
391 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder open failed, error code: 0x%X\n",result);
392 return 0;
394 // printf("opencodec ok (result: %x)\n", result);
395 free(path); /* after this it isn't used anymore */
397 sh->samplerate=sh->wf->nSamplesPerSec;
398 sh->samplesize=sh->wf->wBitsPerSample/8;
399 sh->channels=sh->wf->nChannels;
402 ra_init_t init_data={
403 sh->wf->nSamplesPerSec,
404 sh->wf->wBitsPerSample,
405 sh->wf->nChannels,
406 100, // quality
407 ((short*)(sh->wf+1))[0], // subpacket size
408 ((short*)(sh->wf+1))[3], // coded frame size
409 ((short*)(sh->wf+1))[4], // codec data length
410 ((char*)(sh->wf+1))+10 // extras
412 #if defined(USE_WIN32DLL) || defined(USE_MACSHLB)
413 wra_init_t winit_data={
414 sh->wf->nSamplesPerSec,
415 sh->wf->wBitsPerSample,
416 sh->wf->nChannels,
417 100, // quality
418 ((short*)(sh->wf+1))[0], // subpacket size
419 ((short*)(sh->wf+1))[3], // coded frame size
420 ((short*)(sh->wf+1))[4], // codec data length
421 ((char*)(sh->wf+1))+10 // extras
423 #endif
424 #ifdef USE_MACSHLB
425 result=raInitDecoder(sh->context,&winit_data);
426 #else
427 #ifdef USE_WIN32DLL
428 if (dll_type == 1)
429 result=wraInitDecoder(sh->context,&winit_data);
430 else
431 #endif
432 result=raInitDecoder(sh->context,&init_data);
433 #endif
434 if(result){
435 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder init failed, error code: 0x%X\n",result);
436 return 0;
438 // printf("initdecoder ok (result: %x)\n", result);
441 #ifdef USE_WIN32DLL
442 if((raSetPwd && dll_type == 0) || (wraSetPwd && dll_type == 1)){
443 #else
444 if(raSetPwd){
445 #endif
446 // used by 'SIPR'
447 #ifdef USE_WIN32DLL
448 if (dll_type == 1)
449 wraSetPwd(sh->context,"Ardubancel Quazanga");
450 else
451 #endif
452 raSetPwd(sh->context,"Ardubancel Quazanga"); // set password... lol.
455 #ifdef USE_WIN32DLL
456 if (dll_type == 1)
457 result=wraSetFlavor(sh->context,((short*)(sh->wf+1))[2]);
458 else
459 #endif
460 result=raSetFlavor(sh->context,((short*)(sh->wf+1))[2]);
461 if(result){
462 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"Decoder flavor setup failed, error code: 0x%X\n",result);
463 return 0;
466 #ifdef USE_WIN32DLL
467 if (dll_type == 1)
468 prop=wraGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0,&len);
469 else
470 #endif
471 prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0,&len);
472 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Audio codec: [%d] %s\n",((short*)(sh->wf+1))[2],prop);
474 #ifdef USE_WIN32DLL
475 if (dll_type == 1)
476 prop=wraGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],1,&len);
477 else
478 #endif
479 prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],1,&len);
480 if(prop){
481 sh->i_bps=((*((int*)prop))+4)/8;
482 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Audio bitrate: %5.3f kbit/s (%d bps) \n",(*((int*)prop))*0.001f,sh->i_bps);
483 } else
484 sh->i_bps=12000; // dunno :((( [12000 seems to be OK for crash.rmvb too]
486 // prop=raGetFlavorProperty(sh->context,((short*)(sh->wf+1))[2],0x13,&len);
487 // mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Samples/block?: %d \n",(*((int*)prop)));
489 sh->audio_out_minsize=128000; // no idea how to get... :(
490 sh->audio_in_minsize=((short*)(sh->wf+1))[1]*sh->wf->nBlockAlign;
492 return 1; // return values: 1=OK 0=ERROR
495 static int init(sh_audio_t *sh_audio){
496 // initialize the decoder, set tables etc...
498 // you can store HANDLE or private struct pointer at sh->context
499 // you can access WAVEFORMATEX header at sh->wf
501 // set sample format/rate parameters if you didn't do it in preinit() yet.
503 return 1; // return values: 1=OK 0=ERROR
506 static void uninit(sh_audio_t *sh){
507 // uninit the decoder etc...
508 // again: you don't have to free() a_in_buffer here! it's done by the core.
509 #ifdef USE_WIN32DLL
510 if (dll_type == 1)
512 if (wraFreeDecoder) wraFreeDecoder(sh->context);
513 if (wraCloseCodec) wraCloseCodec(sh->context);
515 #endif
517 if (raFreeDecoder) raFreeDecoder(sh->context);
518 if (raCloseCodec) raCloseCodec(sh->context);
520 #ifdef USE_MACSHLB
521 if (rv_handle){
522 (void)CloseConnection(rv_handle);
523 DisposePtr((Ptr)rv_handle);
525 if (raCloseCodec) DisposePtr((Ptr)raCloseCodec);
526 if (raDecode) DisposePtr((Ptr)raDecode);
527 if (raFlush) DisposePtr((Ptr)raFlush);
528 if (raFreeDecoder) DisposePtr((Ptr)raFreeDecoder);
529 if (raGetFlavorProperty) DisposePtr((Ptr)raGetFlavorProperty);
530 if (raOpenCodec) DisposePtr((Ptr)raOpenCodec);
531 if (raOpenCodec2) DisposePtr((Ptr)raOpenCodec2);
532 if (raInitDecoder) DisposePtr((Ptr)raInitDecoder);
533 #endif
535 #ifdef USE_WIN32DLL
536 if (dll_type == 1)
538 if (rv_handle) FreeLibrary(rv_handle);
539 } else
540 #endif
541 // this dlclose() causes some memory corruption, and crashes soon (in caller):
542 // if (rv_handle) dlclose(rv_handle);
543 rv_handle = NULL;
546 static unsigned char sipr_swaps[38][2]={
547 {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
548 {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
549 {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
550 {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
551 {77,80} };
553 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){
554 int result;
555 int len=-1;
556 int sps=((short*)(sh->wf+1))[0];
557 int w=sh->wf->nBlockAlign; // 5
558 int h=((short*)(sh->wf+1))[1];
559 int cfs=((short*)(sh->wf+1))[3];
561 // printf("bs=%d sps=%d w=%d h=%d \n",sh->wf->nBlockAlign,sps,w,h);
563 #if 1
564 if(sh->a_in_buffer_len<=0){
565 // fill the buffer!
566 if (sh->format == mmioFOURCC('1','4','_','4')) {
567 demux_read_data(sh->ds, sh->a_in_buffer, sh->wf->nBlockAlign);
568 sh->a_in_buffer_size=
569 sh->a_in_buffer_len=sh->wf->nBlockAlign;
570 } else
571 if (sh->format == mmioFOURCC('2','8','_','8')) {
572 int i,j;
573 for (j = 0; j < h; j++)
574 for (i = 0; i < h/2; i++)
575 demux_read_data(sh->ds, sh->a_in_buffer+i*2*w+j*cfs, cfs);
576 sh->a_in_buffer_size=
577 sh->a_in_buffer_len=sh->wf->nBlockAlign*h;
578 } else
579 if(!sps){
580 // 'sipr' way
581 int j,n;
582 int bs=h*w*2/96; // nibbles per subpacket
583 unsigned char *p=sh->a_in_buffer;
584 demux_read_data(sh->ds, p, h*w);
585 for(n=0;n<38;n++){
586 int i=bs*sipr_swaps[n][0];
587 int o=bs*sipr_swaps[n][1];
588 // swap nibbles of block 'i' with 'o' TODO: optimize
589 for(j=0;j<bs;j++){
590 int x=(i&1) ? (p[(i>>1)]>>4) : (p[(i>>1)]&15);
591 int y=(o&1) ? (p[(o>>1)]>>4) : (p[(o>>1)]&15);
592 if(o&1) p[(o>>1)]=(p[(o>>1)]&0x0F)|(x<<4);
593 else p[(o>>1)]=(p[(o>>1)]&0xF0)|x;
594 if(i&1) p[(i>>1)]=(p[(i>>1)]&0x0F)|(y<<4);
595 else p[(i>>1)]=(p[(i>>1)]&0xF0)|y;
596 ++i;++o;
599 sh->a_in_buffer_size=
600 sh->a_in_buffer_len=w*h;
601 } else {
602 // 'cook' way
603 int x,y;
604 w/=sps;
605 for(y=0;y<h;y++)
606 for(x=0;x<w;x++){
607 demux_read_data(sh->ds, sh->a_in_buffer+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
609 sh->a_in_buffer_size=
610 sh->a_in_buffer_len=w*h*sps;
614 #else
615 if(sh->a_in_buffer_len<=0){
616 // fill the buffer!
617 demux_read_data(sh->ds, sh->a_in_buffer, sh->wf->nBlockAlign);
618 sh->a_in_buffer_size=
619 sh->a_in_buffer_len=sh->wf->nBlockAlign;
621 #endif
623 #ifdef USE_WIN32DLL
624 if (dll_type == 1)
625 result=wraDecode(sh->context, sh->a_in_buffer+sh->a_in_buffer_size-sh->a_in_buffer_len, sh->wf->nBlockAlign,
626 buf, &len, -1);
627 else
628 #endif
629 result=raDecode(sh->context, sh->a_in_buffer+sh->a_in_buffer_size-sh->a_in_buffer_len, sh->wf->nBlockAlign,
630 buf, &len, -1);
631 sh->a_in_buffer_len-=sh->wf->nBlockAlign;
633 // printf("radecode: %d bytes, res=0x%X \n",len,result);
635 return len; // return value: number of _bytes_ written to output buffer,
636 // or -1 for EOF (or uncorrectable error)
639 static int control(sh_audio_t *sh,int cmd,void* arg, ...){
640 // various optional functions you MAY implement:
641 switch(cmd){
642 case ADCTRL_RESYNC_STREAM:
643 // it is called once after seeking, to resync.
644 // Note: sh_audio->a_in_buffer_len=0; is done _before_ this call!
645 return CONTROL_TRUE;
646 case ADCTRL_SKIP_FRAME:
647 // it is called to skip (jump over) small amount (1/10 sec or 1 frame)
648 // of audio data - used to sync audio to video after seeking
649 // if you don't return CONTROL_TRUE, it will defaults to:
650 // ds_fill_buffer(sh_audio->ds); // skip 1 demux packet
651 return CONTROL_TRUE;
653 return CONTROL_UNKNOWN;
656 #endif