Mercurial > mplayer.hg
annotate libmpcodecs/dec_audio.c @ 7522:aa1a1249f239
-ac/-afm rewrite, now works the same way as -vc/-vfm
including audio codec fallbacks if init failed
author | arpi |
---|---|
date | Sat, 28 Sep 2002 02:23:20 +0000 |
parents | 6a2b6f3d619c |
children | 047212009a7f |
rev | line source |
---|---|
5342 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <unistd.h> | |
4 | |
5 #include "config.h" | |
6 #include "mp_msg.h" | |
7 #include "help_mp.h" | |
8 | |
9 extern int verbose; // defined in mplayer.c | |
10 | |
11 #include "stream.h" | |
12 #include "demuxer.h" | |
13 | |
14 #include "codec-cfg.h" | |
15 #include "stheader.h" | |
16 | |
17 #include "dec_audio.h" | |
18 #include "ad.h" | |
19 #include "../libao2/afmt.h" | |
20 | |
21 #ifdef USE_FAKE_MONO | |
22 int fakemono=0; | |
23 #endif | |
24 /* used for ac3surround decoder - set using -channels option */ | |
25 int audio_output_channels = 2; | |
26 | |
27 static ad_functions_t* mpadec; | |
28 | |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
29 void afm_help(){ |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
30 int i; |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
31 mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_AvailableAudioFm); |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
32 mp_msg(MSGT_DECAUDIO,MSGL_INFO," afm: info: (comment)\n"); |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
33 for (i=0; mpcodecs_ad_drivers[i] != NULL; i++) |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
34 if(mpcodecs_ad_drivers[i]->info->comment && mpcodecs_ad_drivers[i]->info->comment[0]) |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
35 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"%9s %s (%s)\n", |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
36 mpcodecs_ad_drivers[i]->info->short_name, |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
37 mpcodecs_ad_drivers[i]->info->name, |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
38 mpcodecs_ad_drivers[i]->info->comment); |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
39 else |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
40 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"%9s %s\n", |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
41 mpcodecs_ad_drivers[i]->info->short_name, |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
42 mpcodecs_ad_drivers[i]->info->name); |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
43 } |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
44 |
7522 | 45 int init_audio_codec(sh_audio_t *sh_audio) |
5342 | 46 { |
47 unsigned i; | |
5458 | 48 |
49 // reset in/out buffer size/pointer: | |
50 sh_audio->a_buffer_size=0; | |
51 sh_audio->a_buffer=NULL; | |
52 sh_audio->a_in_buffer_size=0; | |
53 sh_audio->a_in_buffer=NULL; | |
54 | |
55 // Set up some common usefull defaults. ad->preinit() can override these: | |
5342 | 56 |
57 sh_audio->samplesize=2; | |
58 #ifdef WORDS_BIGENDIAN | |
59 sh_audio->sample_format=AFMT_S16_BE; | |
60 #else | |
61 sh_audio->sample_format=AFMT_S16_LE; | |
62 #endif | |
63 sh_audio->samplerate=0; | |
5458 | 64 sh_audio->i_bps=0; // input rate (bytes/sec) |
65 sh_audio->o_bps=0; // output rate (bytes/sec) | |
5342 | 66 |
67 sh_audio->audio_out_minsize=8192;/* default size, maybe not enough for Win32/ACM*/ | |
5458 | 68 sh_audio->audio_in_minsize=0; |
5342 | 69 |
70 if(!mpadec->preinit(sh_audio)) | |
71 { | |
6989 | 72 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_ADecoderPreinitFailed); |
5342 | 73 return 0; |
74 } | |
75 | |
5458 | 76 /* allocate audio in buffer: */ |
77 if(sh_audio->audio_in_minsize>0){ | |
78 sh_audio->a_in_buffer_size=sh_audio->audio_in_minsize; | |
6989 | 79 mp_msg(MSGT_DECAUDIO,MSGL_V,MSGTR_AllocatingBytesForInputBuffer, |
5458 | 80 sh_audio->a_in_buffer_size); |
81 sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size); | |
82 memset(sh_audio->a_in_buffer,0,sh_audio->a_in_buffer_size); | |
83 sh_audio->a_in_buffer_len=0; | |
84 } | |
85 | |
5342 | 86 /* allocate audio out buffer: */ |
87 sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST; /* worst case calc.*/ | |
88 | |
6989 | 89 mp_msg(MSGT_DECAUDIO,MSGL_V,MSGTR_AllocatingBytesForOutputBuffer, |
5342 | 90 sh_audio->audio_out_minsize,MAX_OUTBURST,sh_audio->a_buffer_size); |
91 | |
92 sh_audio->a_buffer=malloc(sh_audio->a_buffer_size); | |
93 if(!sh_audio->a_buffer){ | |
94 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantAllocAudioBuf); | |
95 return 0; | |
96 } | |
97 memset(sh_audio->a_buffer,0,sh_audio->a_buffer_size); | |
98 sh_audio->a_buffer_len=0; | |
99 | |
100 if(!mpadec->init(sh_audio)){ | |
6989 | 101 mp_msg(MSGT_DECAUDIO,MSGL_WARN,MSGTR_ADecoderInitFailed); |
5458 | 102 uninit_audio(sh_audio); // free buffers |
5342 | 103 return 0; |
104 } | |
5458 | 105 |
5342 | 106 sh_audio->inited=1; |
107 | |
108 if(!sh_audio->channels || !sh_audio->samplerate){ | |
109 mp_msg(MSGT_DECAUDIO,MSGL_WARN,MSGTR_UnknownAudio); | |
5458 | 110 uninit_audio(sh_audio); // free buffers |
5342 | 111 return 0; |
112 } | |
113 | |
114 if(!sh_audio->o_bps) | |
115 sh_audio->o_bps=sh_audio->channels*sh_audio->samplerate*sh_audio->samplesize; | |
7522 | 116 |
117 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"AUDIO: %d Hz, %d ch, sfmt: 0x%X (%d bps), ratio: %d->%d (%3.1f kbit)\n", | |
118 sh_audio->samplerate,sh_audio->channels, | |
119 sh_audio->sample_format,sh_audio->samplesize, | |
120 sh_audio->i_bps,sh_audio->o_bps,sh_audio->i_bps*8*0.001); | |
5458 | 121 |
122 return 1; | |
5342 | 123 } |
124 | |
7522 | 125 int init_audio(sh_audio_t *sh_audio,char* codecname,char* afm,int status){ |
126 unsigned int orig_fourcc=sh_audio->wf?sh_audio->wf->wFormatTag:0; | |
127 sh_audio->codec=NULL; | |
128 while(1){ | |
129 int i; | |
130 // restore original fourcc: | |
131 if(sh_audio->wf) sh_audio->wf->wFormatTag=i=orig_fourcc; | |
132 if(!(sh_audio->codec=find_codec(sh_audio->format, | |
133 sh_audio->wf?(&i):NULL, sh_audio->codec,1) )) break; | |
134 if(sh_audio->wf) sh_audio->wf->wFormatTag=i; | |
135 // ok we found one codec | |
136 if(sh_audio->codec->flags&CODECS_FLAG_SELECTED) continue; // already tried & failed | |
137 if(codecname && strcmp(sh_audio->codec->name,codecname)) continue; // -ac | |
138 if(afm && strcmp(sh_audio->codec->drv,afm)) continue; // afm doesn't match | |
139 if(sh_audio->codec->status<status) continue; // too unstable | |
140 sh_audio->codec->flags|=CODECS_FLAG_SELECTED; // tagging it | |
141 // ok, it matches all rules, let's find the driver! | |
142 for (i=0; mpcodecs_ad_drivers[i] != NULL; i++) | |
143 if(!strcmp(mpcodecs_ad_drivers[i]->info->short_name,sh_audio->codec->drv)) break; | |
144 mpadec=mpcodecs_ad_drivers[i]; | |
145 if(!mpadec){ // driver not available (==compiled in) | |
146 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_AudioCodecFamilyNotAvailableStr, | |
147 sh_audio->codec->name, sh_audio->codec->drv); | |
148 continue; | |
149 } | |
150 // it's available, let's try to init! | |
151 // init() | |
152 mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_OpeningAudioDecoder,mpadec->info->short_name,mpadec->info->name); | |
153 if(!init_audio_codec(sh_audio)){ | |
154 mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_ADecoderInitFailed); | |
155 continue; // try next... | |
156 } | |
157 // Yeah! We got it! | |
158 return 1; | |
159 } | |
160 return 0; | |
161 } | |
162 | |
163 int init_best_audio_codec(sh_audio_t *sh_audio,char** audio_codec_list,char** audio_fm_list){ | |
164 char* ac_l_default[2]={"",(char*)NULL}; | |
165 // hack: | |
166 if(!audio_codec_list) audio_codec_list=ac_l_default; | |
167 // Go through the codec.conf and find the best codec... | |
168 sh_audio->inited=0; | |
169 codecs_reset_selection(1); | |
170 while(!sh_audio->inited && *audio_codec_list){ | |
171 char* audio_codec=*(audio_codec_list++); | |
172 if(audio_codec[0]){ | |
173 if(audio_codec[0]=='-'){ | |
174 // disable this codec: | |
175 select_codec(audio_codec+1,1); | |
176 } else { | |
177 // forced codec by name: | |
178 mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_ForcedAudioCodec,audio_codec); | |
179 init_audio(sh_audio,audio_codec,NULL,-1); | |
180 } | |
181 } else { | |
182 int status; | |
183 // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING. | |
184 if(audio_fm_list){ | |
185 char** fmlist=audio_fm_list; | |
186 // try first the preferred codec families: | |
187 while(!sh_audio->inited && *fmlist){ | |
188 char* audio_fm=*(fmlist++); | |
189 mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_TryForceAudioFmtStr,audio_fm); | |
190 for(status=CODECS_STATUS__MAX;status>=CODECS_STATUS__MIN;--status) | |
191 if(init_audio(sh_audio,NULL,audio_fm,status)) break; | |
192 } | |
193 } | |
194 if(!sh_audio->inited) | |
195 for(status=CODECS_STATUS__MAX;status>=CODECS_STATUS__MIN;--status) | |
196 if(init_audio(sh_audio,NULL,NULL,status)) break; | |
197 } | |
198 } | |
199 | |
200 if(!sh_audio->inited){ | |
201 mp_msg(MSGT_DECAUDIO,MSGL_HINT, MSGTR_TryUpgradeCodecsConfOrRTFM,get_path("codecs.conf")); | |
202 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantFindAudioCodec,sh_audio->format); | |
203 return 0; // failed | |
204 } | |
205 | |
206 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Selected audio codec: [%s] afm:%s (%s)\n", | |
207 sh_audio->codec->name,sh_audio->codec->drv,sh_audio->codec->info); | |
208 return 1; // success | |
209 } | |
210 | |
211 | |
212 int init_best_audio_codec_old(sh_audio_t *sh_audio,char* audio_codec,char* audio_fm){ | |
7502
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
213 // Go through the codec.conf and find the best codec... |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
214 sh_audio->codec=NULL; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
215 if(audio_fm) mp_msg(MSGT_DECAUDIO,MSGL_INFO,MSGTR_TryForceAudioFmtStr,audio_fm); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
216 while(1){ |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
217 sh_audio->codec=find_codec(sh_audio->format,NULL,sh_audio->codec,1); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
218 if(!sh_audio->codec){ |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
219 if(audio_fm) { |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
220 sh_audio->codec=NULL; /* re-search */ |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
221 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantFindAfmtFallback); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
222 audio_fm=NULL; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
223 continue; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
224 } |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
225 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantFindAudioCodec,sh_audio->format); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
226 mp_msg(MSGT_DECAUDIO,MSGL_HINT, MSGTR_TryUpgradeCodecsConfOrRTFM,get_path("codecs.conf")); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
227 return 0; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
228 } |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
229 if(audio_codec && strcmp(sh_audio->codec->name,audio_codec)) continue; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
230 if(audio_fm && strcmp(sh_audio->codec->drv,audio_fm)) continue; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
231 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"%s audio codec: [%s] afm:%s (%s)\n", |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
232 audio_codec?mp_gettext("Forcing"):mp_gettext("Detected"),sh_audio->codec->name,sh_audio->codec->drv,sh_audio->codec->info); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
233 break; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
234 } |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
235 // found it... |
7522 | 236 if(!init_audio_codec(sh_audio)){ |
7502
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
237 mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CouldntInitAudioCodec); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
238 return 0; |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
239 } |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
240 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"AUDIO: %d Hz, %d ch, sfmt: 0x%X (%d bps), ratio: %d->%d (%3.1f kbit)\n", |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
241 sh_audio->samplerate,sh_audio->channels, |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
242 sh_audio->sample_format,sh_audio->samplesize, |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
243 sh_audio->i_bps,sh_audio->o_bps,sh_audio->i_bps*8*0.001); |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
244 return 1; // success! |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
245 } |
6a2b6f3d619c
best audio/video codec selection & init moved to libmpcodecs
arpi
parents:
7240
diff
changeset
|
246 |
5342 | 247 void uninit_audio(sh_audio_t *sh_audio) |
248 { | |
7240 | 249 if(sh_audio->inited){ |
250 mp_msg(MSGT_DECAUDIO,MSGL_V,MSGTR_UninitAudioStr,sh_audio->codec->drv); | |
251 mpadec->uninit(sh_audio); | |
252 sh_audio->inited=0; | |
253 } | |
5458 | 254 if(sh_audio->a_buffer) free(sh_audio->a_buffer); |
255 sh_audio->a_buffer=NULL; | |
256 if(sh_audio->a_in_buffer) free(sh_audio->a_in_buffer); | |
257 sh_audio->a_in_buffer=NULL; | |
5342 | 258 } |
259 | |
260 int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) | |
261 { | |
262 if(sh_audio->inited) | |
263 return mpadec->decode_audio(sh_audio,buf,minlen,maxlen); | |
264 else | |
265 return -1; | |
266 } | |
267 | |
268 void resync_audio_stream(sh_audio_t *sh_audio) | |
269 { | |
6049 | 270 sh_audio->a_in_buffer_len=0; // clear audio input buffer |
5342 | 271 if(!sh_audio->inited) return; |
6049 | 272 mpadec->control(sh_audio,ADCTRL_RESYNC_STREAM,NULL); |
5342 | 273 } |
274 | |
275 void skip_audio_frame(sh_audio_t *sh_audio) | |
276 { | |
277 if(!sh_audio->inited) return; | |
278 if(mpadec->control(sh_audio,ADCTRL_SKIP_FRAME,NULL)==CONTROL_TRUE) return; | |
279 // default skip code: | |
280 ds_fill_buffer(sh_audio->ds); // skip block | |
281 } |