13 #include "ad_internal.h"
14 #include "osdep/timer.h"
16 static ad_info_t info
=
32 static int init(sh_audio_t
*sh_audio
)
34 int ret
=decode_audio(sh_audio
,sh_audio
->a_buffer
,4096,sh_audio
->a_buffer_size
);
36 mp_msg(MSGT_DECAUDIO
,MSGL_INFO
,"ACM decoding error: %d\n",ret
);
39 sh_audio
->a_buffer_len
=ret
;
43 extern void print_wave_header(WAVEFORMATEX
*h
, int verbose_level
);
45 static int preinit(sh_audio_t
*sh_audio
)
48 WAVEFORMATEX
*in_fmt
= sh_audio
->wf
;
52 priv
= malloc(sizeof(acm_context_t
));
55 sh_audio
->context
= priv
;
57 mp_msg(MSGT_WIN32
, MSGL_V
, "======= Win32 (ACM) AUDIO Codec init =======\n");
59 // priv->handle = NULL;
61 priv
->o_wf
= malloc(sizeof(WAVEFORMATEX
));
64 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,MSGTR_ACMiniterror
);
68 priv
->o_wf
->nChannels
= in_fmt
->nChannels
;
69 priv
->o_wf
->nSamplesPerSec
= in_fmt
->nSamplesPerSec
;
70 priv
->o_wf
->nAvgBytesPerSec
= 2*in_fmt
->nSamplesPerSec
*in_fmt
->nChannels
;
71 priv
->o_wf
->wFormatTag
= WAVE_FORMAT_PCM
;
72 priv
->o_wf
->nBlockAlign
= 2*in_fmt
->nChannels
;
73 priv
->o_wf
->wBitsPerSample
= 16;
74 // priv->o_wf->wBitsPerSample = inf_fmt->wBitsPerSample;
75 priv
->o_wf
->cbSize
= 0;
77 if ( mp_msg_test(MSGT_DECAUDIO
,MSGL_V
) )
79 mp_msg(MSGT_DECAUDIO
, MSGL_V
, "Input format:\n");
80 print_wave_header(in_fmt
, MSGL_V
);
81 mp_msg(MSGT_DECAUDIO
, MSGL_V
, "Output format:\n");
82 print_wave_header(priv
->o_wf
, MSGL_V
);
85 MSACM_RegisterDriver((const char *)sh_audio
->codec
->dll
, in_fmt
->wFormatTag
, 0);
86 ret
= acmStreamOpen(&priv
->handle
, (HACMDRIVER
)NULL
, in_fmt
,
87 priv
->o_wf
, NULL
, 0, 0, 0);
90 if (ret
== ACMERR_NOTPOSSIBLE
)
91 mp_msg(MSGT_WIN32
, MSGL_ERR
, "ACM_Decoder: Unappropriate audio format\n");
93 mp_msg(MSGT_WIN32
, MSGL_ERR
, "ACM_Decoder: acmStreamOpen error: %d\n",
95 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,MSGTR_ACMiniterror
);
98 mp_msg(MSGT_WIN32
, MSGL_V
, "Audio codec opened OK! ;-)\n");
100 acmStreamSize(priv
->handle
, in_fmt
->nBlockAlign
, &srcsize
, ACM_STREAMSIZEF_SOURCE
);
101 //if ( mp_msg_test(MSGT_DECAUDIO,MSGL_V) ) printf("Audio ACM output buffer min. size: %ld (reported by codec)\n", srcsize);
103 //if (srcsize < MAX_OUTBURST) srcsize = MAX_OUTBURST;
106 mp_msg(MSGT_WIN32
, MSGL_WARN
, "Warning! ACM codec reports srcsize=0\n");
109 // limit srcsize to 4-16kb
110 //while(srcsize && srcsize<4096) srcsize*=2;
111 //while(srcsize>16384) srcsize/=2;
112 sh_audio
->audio_out_minsize
=srcsize
; // audio output min. size
113 mp_msg(MSGT_WIN32
,MSGL_V
,"Audio ACM output buffer min. size: %ld\n",srcsize
);
115 acmStreamSize(priv
->handle
, srcsize
, &srcsize
, ACM_STREAMSIZEF_DESTINATION
);
116 // if(srcsize<in_fmt->nBlockAlign) srcsize=in_fmt->nBlockAlign;
120 mp_msg(MSGT_WIN32
, MSGL_WARN
, "Warning! ACM codec reports srcsize=0\n");
121 srcsize
= 2*in_fmt
->nBlockAlign
;
124 mp_msg(MSGT_WIN32
,MSGL_V
,"Audio ACM input buffer min. size: %ld\n",srcsize
);
126 sh_audio
->audio_in_minsize
=2*srcsize
; // audio input min. size
128 sh_audio
->i_bps
=sh_audio
->wf
->nAvgBytesPerSec
;
129 sh_audio
->channels
=priv
->o_wf
->nChannels
;
130 sh_audio
->samplerate
=priv
->o_wf
->nSamplesPerSec
;
131 sh_audio
->samplesize
=2;
133 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: Win32/ACM audio codec init OK!\n");
137 static void uninit(sh_audio_t
*sh
)
140 acm_context_t
*priv
= sh
->context
;
142 ret
= acmStreamClose(priv
->handle
, 0);
148 case ACMERR_CANCELED
:
149 mp_msg(MSGT_WIN32
, MSGL_DBG2
, "ACM_Decoder: stream busy, waiting..\n");
150 usec_sleep(100000000);
152 case ACMERR_UNPREPARED
:
153 case ACMERR_NOTPOSSIBLE
:
156 mp_msg(MSGT_WIN32
, MSGL_WARN
, "ACM_Decoder: unknown error occurred: %ld\n", ret
);
160 MSACM_UnregisterAllDrivers();
166 static int control(sh_audio_t
*sh_audio
,int cmd
,void* arg
, ...)
171 case ADCTRL_SKIP_FRAME
:
172 skip
=sh_audio
->wf
->nBlockAlign
;
174 skip
=(sh_audio
->wf
->nAvgBytesPerSec
/16)&(~7);
177 demux_read_data(sh_audio
->ds
,NULL
,skip
);
180 return CONTROL_UNKNOWN
;
183 static int decode_audio(sh_audio_t
*sh_audio
,unsigned char *buf
,int minlen
,int maxlen
)
189 acm_context_t
*priv
= sh_audio
->context
;
191 acmStreamSize(priv
->handle
, len
, &srcsize
, ACM_STREAMSIZEF_DESTINATION
);
192 mp_msg(MSGT_WIN32
,MSGL_DBG3
,"acm says: srcsize=%ld (buffsize=%d) out_size=%ld\n",srcsize
,sh_audio
->a_in_buffer_size
,len
);
194 if(srcsize
<sh_audio
->wf
->nBlockAlign
){
195 srcsize
=sh_audio
->wf
->nBlockAlign
;
196 acmStreamSize(priv
->handle
, srcsize
, &len
, ACM_STREAMSIZEF_SOURCE
);
197 if(len
>maxlen
) len
=maxlen
;
200 // if(srcsize==0) srcsize=((WAVEFORMATEX *)&sh_audio->o_wf_ext)->nBlockAlign;
201 if(srcsize
>sh_audio
->a_in_buffer_size
) srcsize
=sh_audio
->a_in_buffer_size
; // !!!!!!
202 if(sh_audio
->a_in_buffer_len
<srcsize
){
203 sh_audio
->a_in_buffer_len
+=
204 demux_read_data(sh_audio
->ds
,&sh_audio
->a_in_buffer
[sh_audio
->a_in_buffer_len
],
205 srcsize
-sh_audio
->a_in_buffer_len
);
207 mp_msg(MSGT_WIN32
,MSGL_DBG3
,"acm convert %d -> %ld bytes\n",sh_audio
->a_in_buffer_len
,len
);
208 memset(&ash
, 0, sizeof(ash
));
209 ash
.cbStruct
=sizeof(ash
);
212 ash
.pbSrc
=sh_audio
->a_in_buffer
;
213 ash
.cbSrcLength
=sh_audio
->a_in_buffer_len
;
216 hr
=acmStreamPrepareHeader(priv
->handle
,&ash
,0);
218 mp_msg(MSGT_WIN32
,MSGL_V
,"ACM_Decoder: acmStreamPrepareHeader error %d\n",(int)hr
);
221 hr
=acmStreamConvert(priv
->handle
,&ash
,0);
223 mp_msg(MSGT_WIN32
,MSGL_DBG2
,"ACM_Decoder: acmStreamConvert error %d\n",(int)hr
);
226 case ACMERR_NOTPOSSIBLE
:
227 case ACMERR_UNPREPARED
:
228 mp_msg(MSGT_WIN32
, MSGL_DBG2
, "ACM_Decoder: acmStreamConvert error: probarly not initialized!\n");
232 mp_msg(MSGT_WIN32
,MSGL_DBG2
,"acm converted %ld -> %ld\n",ash
.cbSrcLengthUsed
,ash
.cbDstLengthUsed
);
233 if(ash
.cbSrcLengthUsed
>=sh_audio
->a_in_buffer_len
){
234 sh_audio
->a_in_buffer_len
=0;
236 sh_audio
->a_in_buffer_len
-=ash
.cbSrcLengthUsed
;
237 memcpy(sh_audio
->a_in_buffer
,&sh_audio
->a_in_buffer
[ash
.cbSrcLengthUsed
],sh_audio
->a_in_buffer_len
);
239 len
=ash
.cbDstLengthUsed
;
240 hr
=acmStreamUnprepareHeader(priv
->handle
,&ash
,0);
242 mp_msg(MSGT_WIN32
,MSGL_V
,"ACM_Decoder: acmStreamUnprepareHeader error %d\n",(int)hr
);