2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "libmpdemux/aviprint.h"
27 #include "loader/wineacm.h"
29 #include "ad_internal.h"
30 #include "osdep/timer.h"
32 static const ad_info_t info
=
48 static int init(sh_audio_t
*sh_audio
)
50 int ret
=decode_audio(sh_audio
,sh_audio
->a_buffer
,4096,sh_audio
->a_buffer_size
);
52 mp_msg(MSGT_DECAUDIO
,MSGL_INFO
,"ACM decoding error: %d\n",ret
);
55 sh_audio
->a_buffer_len
=ret
;
59 static int preinit(sh_audio_t
*sh_audio
)
62 WAVEFORMATEX
*in_fmt
= sh_audio
->wf
;
66 priv
= malloc(sizeof(acm_context_t
));
69 sh_audio
->context
= priv
;
71 mp_msg(MSGT_WIN32
, MSGL_V
, "======= Win32 (ACM) AUDIO Codec init =======\n");
73 // priv->handle = NULL;
75 priv
->o_wf
= malloc(sizeof(WAVEFORMATEX
));
78 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,MSGTR_ACMiniterror
);
82 priv
->o_wf
->nChannels
= in_fmt
->nChannels
;
83 priv
->o_wf
->nSamplesPerSec
= in_fmt
->nSamplesPerSec
;
84 priv
->o_wf
->nAvgBytesPerSec
= 2*in_fmt
->nSamplesPerSec
*in_fmt
->nChannels
;
85 priv
->o_wf
->wFormatTag
= WAVE_FORMAT_PCM
;
86 priv
->o_wf
->nBlockAlign
= 2*in_fmt
->nChannels
;
87 priv
->o_wf
->wBitsPerSample
= 16;
88 // priv->o_wf->wBitsPerSample = inf_fmt->wBitsPerSample;
89 priv
->o_wf
->cbSize
= 0;
91 if ( mp_msg_test(MSGT_DECAUDIO
,MSGL_V
) )
93 mp_msg(MSGT_DECAUDIO
, MSGL_V
, "Input format:\n");
94 print_wave_header(in_fmt
, MSGL_V
);
95 mp_msg(MSGT_DECAUDIO
, MSGL_V
, "Output format:\n");
96 print_wave_header(priv
->o_wf
, MSGL_V
);
99 MSACM_RegisterDriver((const char *)sh_audio
->codec
->dll
, in_fmt
->wFormatTag
, 0);
100 ret
= acmStreamOpen(&priv
->handle
, (HACMDRIVER
)NULL
, in_fmt
,
101 priv
->o_wf
, NULL
, 0, 0, 0);
104 if (ret
== ACMERR_NOTPOSSIBLE
)
105 mp_msg(MSGT_WIN32
, MSGL_ERR
, "ACM_Decoder: Unappropriate audio format\n");
107 mp_msg(MSGT_WIN32
, MSGL_ERR
, "ACM_Decoder: acmStreamOpen error: %d\n",
109 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,MSGTR_ACMiniterror
);
112 mp_msg(MSGT_WIN32
, MSGL_V
, "Audio codec opened OK! ;-)\n");
114 acmStreamSize(priv
->handle
, in_fmt
->nBlockAlign
, &srcsize
, ACM_STREAMSIZEF_SOURCE
);
115 //if ( mp_msg_test(MSGT_DECAUDIO,MSGL_V) ) printf("Audio ACM output buffer min. size: %ld (reported by codec)\n", srcsize);
117 //if (srcsize < MAX_OUTBURST) srcsize = MAX_OUTBURST;
120 mp_msg(MSGT_WIN32
, MSGL_WARN
, "Warning! ACM codec reports srcsize=0\n");
123 // limit srcsize to 4-16kb
124 //while(srcsize && srcsize<4096) srcsize*=2;
125 //while(srcsize>16384) srcsize/=2;
126 sh_audio
->audio_out_minsize
=srcsize
; // audio output min. size
127 mp_msg(MSGT_WIN32
,MSGL_V
,"Audio ACM output buffer min. size: %ld\n",srcsize
);
129 acmStreamSize(priv
->handle
, srcsize
, &srcsize
, ACM_STREAMSIZEF_DESTINATION
);
130 // if(srcsize<in_fmt->nBlockAlign) srcsize=in_fmt->nBlockAlign;
134 mp_msg(MSGT_WIN32
, MSGL_WARN
, "Warning! ACM codec reports srcsize=0\n");
135 srcsize
= 2*in_fmt
->nBlockAlign
;
138 mp_msg(MSGT_WIN32
,MSGL_V
,"Audio ACM input buffer min. size: %ld\n",srcsize
);
140 sh_audio
->audio_in_minsize
=2*srcsize
; // audio input min. size
142 sh_audio
->i_bps
=sh_audio
->wf
->nAvgBytesPerSec
;
143 sh_audio
->channels
=priv
->o_wf
->nChannels
;
144 sh_audio
->samplerate
=priv
->o_wf
->nSamplesPerSec
;
145 sh_audio
->samplesize
=2;
147 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: Win32/ACM audio codec init OK!\n");
151 static void uninit(sh_audio_t
*sh
)
154 acm_context_t
*priv
= sh
->context
;
157 ret
= acmStreamClose(priv
->handle
, 0);
163 case ACMERR_CANCELED
:
164 mp_msg(MSGT_WIN32
, MSGL_DBG2
, "ACM_Decoder: stream busy, waiting..\n");
165 usec_sleep(100000000);
167 case ACMERR_UNPREPARED
:
168 case ACMERR_NOTPOSSIBLE
:
171 mp_msg(MSGT_WIN32
, MSGL_WARN
, "ACM_Decoder: unknown error occurred: %ld\n", ret
);
175 MSACM_UnregisterAllDrivers();
181 static int control(sh_audio_t
*sh_audio
,int cmd
,void* arg
, ...)
186 case ADCTRL_SKIP_FRAME
:
187 skip
=sh_audio
->wf
->nBlockAlign
;
189 skip
=(sh_audio
->wf
->nAvgBytesPerSec
/16)&(~7);
192 demux_read_data(sh_audio
->ds
,NULL
,skip
);
195 return CONTROL_UNKNOWN
;
198 static int decode_audio(sh_audio_t
*sh_audio
,unsigned char *buf
,int minlen
,int maxlen
)
204 acm_context_t
*priv
= sh_audio
->context
;
206 acmStreamSize(priv
->handle
, len
, &srcsize
, ACM_STREAMSIZEF_DESTINATION
);
207 mp_msg(MSGT_WIN32
,MSGL_DBG3
,"acm says: srcsize=%ld (buffsize=%d) out_size=%ld\n",srcsize
,sh_audio
->a_in_buffer_size
,len
);
209 if(srcsize
<sh_audio
->wf
->nBlockAlign
){
210 srcsize
=sh_audio
->wf
->nBlockAlign
;
211 acmStreamSize(priv
->handle
, srcsize
, &len
, ACM_STREAMSIZEF_SOURCE
);
212 if(len
>maxlen
) len
=maxlen
;
215 // if(srcsize==0) srcsize=((WAVEFORMATEX *)&sh_audio->o_wf_ext)->nBlockAlign;
216 if(srcsize
>sh_audio
->a_in_buffer_size
) srcsize
=sh_audio
->a_in_buffer_size
; // !!!!!!
217 if(sh_audio
->a_in_buffer_len
<srcsize
){
218 sh_audio
->a_in_buffer_len
+=
219 demux_read_data(sh_audio
->ds
,&sh_audio
->a_in_buffer
[sh_audio
->a_in_buffer_len
],
220 srcsize
-sh_audio
->a_in_buffer_len
);
222 mp_msg(MSGT_WIN32
,MSGL_DBG3
,"acm convert %d -> %ld bytes\n",sh_audio
->a_in_buffer_len
,len
);
223 memset(&ash
, 0, sizeof(ash
));
224 ash
.cbStruct
=sizeof(ash
);
227 ash
.pbSrc
=sh_audio
->a_in_buffer
;
228 ash
.cbSrcLength
=sh_audio
->a_in_buffer_len
;
231 hr
=acmStreamPrepareHeader(priv
->handle
,&ash
,0);
233 mp_msg(MSGT_WIN32
,MSGL_V
,"ACM_Decoder: acmStreamPrepareHeader error %d\n",(int)hr
);
236 hr
=acmStreamConvert(priv
->handle
,&ash
,0);
238 mp_msg(MSGT_WIN32
,MSGL_DBG2
,"ACM_Decoder: acmStreamConvert error %d\n",(int)hr
);
241 case ACMERR_NOTPOSSIBLE
:
242 case ACMERR_UNPREPARED
:
243 mp_msg(MSGT_WIN32
, MSGL_DBG2
, "ACM_Decoder: acmStreamConvert error: probarly not initialized!\n");
247 mp_msg(MSGT_WIN32
,MSGL_DBG2
,"acm converted %ld -> %ld\n",ash
.cbSrcLengthUsed
,ash
.cbDstLengthUsed
);
248 if(ash
.cbSrcLengthUsed
>=sh_audio
->a_in_buffer_len
){
249 sh_audio
->a_in_buffer_len
=0;
251 sh_audio
->a_in_buffer_len
-=ash
.cbSrcLengthUsed
;
252 memcpy(sh_audio
->a_in_buffer
,&sh_audio
->a_in_buffer
[ash
.cbSrcLengthUsed
],sh_audio
->a_in_buffer_len
);
254 len
=ash
.cbDstLengthUsed
;
255 hr
=acmStreamUnprepareHeader(priv
->handle
,&ash
,0);
257 mp_msg(MSGT_WIN32
,MSGL_V
,"ACM_Decoder: acmStreamUnprepareHeader error %d\n",(int)hr
);