1 /*
2 INTEL CONFIDENTIAL
3 Copyright 2009 Intel Corporation All Rights Reserved.
4 The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5
6 No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7 */
8
9
10 #include <glib.h>
11 #include <glib/gprintf.h>
12 #include <linux/types.h>
13 #include "mixacpmp3.h"
14 #include "mixacpwma.h"
15 #include "mixacpaac.h"
16 #include "intel_sst_ioctl.h"
17 #include "mixacp.h"
18 #include "sst_proxy.h"
19
20 #ifdef G_LOG_DOMAIN
21 #undef G_LOG_DOMAIN
22 #define G_LOG_DOMAIN ((gchar*)"mixaudio")
23 #endif
24
25 gboolean mix_sst_params_convert_mp3(MixAudioConfigParamsMP3 *acp, struct snd_sst_params *s);
26 gboolean mix_sst_params_convert_wma(MixAudioConfigParamsWMA *acp, struct snd_sst_params *s);
27 gboolean mix_sst_params_convert_aac(MixAudioConfigParamsAAC *acp, struct snd_sst_params *s);
28 void mix_sst_params_to_mp3(MixAudioConfigParamsMP3 *acp, struct snd_mp3_params *params);
29 void mix_sst_params_to_wma(MixAudioConfigParamsWMA *acp, struct snd_wma_params *params);
30 void mix_sst_params_to_aac(MixAudioConfigParamsAAC *acp, struct snd_aac_params *params);
31 void mix_sst_set_bps(MixAudioConfigParams *acp, guchar pcm_wd_sz);
32 void mix_sst_set_op_align(MixAudioConfigParams *acp, guchar op_align);
33
34 /*
35 * Utilities that convert param object to driver struct.
36 * No Mix Context needed. However, it knows about the driver's param structure.
37 */
mix_sst_params_convert(MixAudioConfigParams * acp,struct snd_sst_params * s)38 gboolean mix_sst_params_convert(MixAudioConfigParams *acp, struct snd_sst_params *s)
39 {
40 gboolean ret = FALSE;
41
42 if (!s) return FALSE;
43
44 if (MIX_IS_AUDIOCONFIGPARAMSMP3(acp))
45 ret = mix_sst_params_convert_mp3(MIX_AUDIOCONFIGPARAMSMP3(acp), s);
46 else if (MIX_IS_AUDIOCONFIGPARAMSWMA(acp))
47 ret = mix_sst_params_convert_wma(MIX_AUDIOCONFIGPARAMSWMA(acp), s);
48 else if (MIX_IS_AUDIOCONFIGPARAMSAAC(acp))
49 ret = mix_sst_params_convert_aac(MIX_AUDIOCONFIGPARAMSAAC(acp), s);
50
51 return ret;
52 }
53
54
mix_sst_params_convert_mp3(MixAudioConfigParamsMP3 * acp,struct snd_sst_params * s)55 gboolean mix_sst_params_convert_mp3(MixAudioConfigParamsMP3 *acp, struct snd_sst_params *s)
56 {
57 struct snd_mp3_params *p = &s->sparams.uc.mp3_params;
58
59 s->codec = p->codec = SST_CODEC_TYPE_MP3;
60 p->num_chan = MIX_ACP_NUM_CHANNELS(acp);
61 p->brate = MIX_ACP_BITRATE(acp);
62 p->sfreq = MIX_ACP_SAMPLE_FREQ(acp);
63 p->crc_check = MIX_ACP_MP3_CRC(acp);
64 p->pcm_wd_sz = mix_acp_get_bps(MIX_AUDIOCONFIGPARAMS(acp));
65 if (p->pcm_wd_sz == MIX_ACP_BPS_16)
66 p->op_align = MIX_ACP_OUTPUT_ALIGN_16;
67 else
68 p->op_align = mix_acp_get_op_align(MIX_AUDIOCONFIGPARAMS(acp));
69
70 return TRUE;
71 }
72
mix_sst_params_convert_wma(MixAudioConfigParamsWMA * acp,struct snd_sst_params * s)73 gboolean mix_sst_params_convert_wma(MixAudioConfigParamsWMA *acp, struct snd_sst_params *s)
74 {
75 struct snd_wma_params *p = &s->sparams.uc.wma_params;
76
77 p->num_chan = MIX_ACP_NUM_CHANNELS(acp);
78 p->brate = MIX_ACP_BITRATE(acp);
79 p->sfreq = MIX_ACP_SAMPLE_FREQ(acp);
80 p->wma_encode_opt = MIX_ACP_WMA_ENCODE_OPT(acp);
81 p->block_align = MIX_ACP_WMA_BLOCK_ALIGN(acp);
82 p->channel_mask = MIX_ACP_WMA_CHANNEL_MASK(acp);
83 p->format_tag = MIX_ACP_WMA_FORMAT_TAG(acp);
84 p->pcm_src = MIX_ACP_WMA_PCM_BIT_WIDTH(acp);
85 p->pcm_wd_sz = mix_acp_get_bps(MIX_AUDIOCONFIGPARAMS(acp));
86 if (p->pcm_wd_sz == MIX_ACP_BPS_16)
87 p->op_align = MIX_ACP_OUTPUT_ALIGN_16;
88 else
89 p->op_align = mix_acp_get_op_align(MIX_AUDIOCONFIGPARAMS(acp));
90
91 switch (mix_acp_wma_get_version(acp))
92 {
93 case MIX_AUDIO_WMA_V9:
94 s->codec = p->codec = SST_CODEC_TYPE_WMA9;
95 break;
96 case MIX_AUDIO_WMA_V10:
97 s->codec = p->codec = SST_CODEC_TYPE_WMA10;
98 break;
99 case MIX_AUDIO_WMA_V10P:
100 s->codec = p->codec = SST_CODEC_TYPE_WMA10P;
101 break;
102 default:
103 break;
104 }
105
106 return TRUE;
107 }
108
109 #define AAC_DUMP(param) g_message("snd_aac_params.%s=%u", #param, p->param)
110 #define AAC_DUMP_I(param, idx) g_message("snd_aac_params.%s[%d]=%x", #param, idx, p->param[idx])
111
mix_sst_params_convert_aac(MixAudioConfigParamsAAC * acp,struct snd_sst_params * s)112 gboolean mix_sst_params_convert_aac(MixAudioConfigParamsAAC *acp, struct snd_sst_params *s)
113 {
114 struct snd_aac_params *p = &s->sparams.uc.aac_params;
115
116 // I have only AOT, where tools are usually specified at eAOT.
117 // However, sometimes, AOT could tell us the tool involved. e.g.
118 // AOT==5 --> SBR
119 // AOT==29 --> PS
120 // AOT==2 --> AAC-LC
121
122 // we know SBR present only if it is indicated presence, or AOT says so.
123 guint aot = mix_acp_aac_get_aot(acp);
124 p->sbr_present = ((MIX_ACP_AAC_SBR_FLAG(acp) == 1) ||
125 (aot == 5) ||
126 (MIX_ACP_AAC_PS_FLAG(acp) == 1) ||
127 (aot == 29))?1:0;
128
129 // As far as we know, we should:
130 // set sbr_present flag for SST in case of possible implicit signalling of SBR, and
131 // we should use HEAACv2 decoder in case of possible implicit signalling of PS.
132 // Although we should theoretically select HEAACv2 decoder for HEAACv1 and HEAAC,
133 // it is not advisable since HEAACv2 decoder has more overhead as per SST team.
134 // So MixAudio is implicitly selecting codec base on AOT, psPresentFlag and sbrPresentFlag.
135 // Application can override the selection by explicitly setting psPresentFlag and/or sbrPresentFlag.
136 if ((MIX_ACP_AAC_PS_FLAG(acp) == 1) || (aot == 29))
137 {
138 // PS present.
139 s->codec = p->codec = SST_CODEC_TYPE_eAACP;
140 }
141 else if (p->sbr_present == 1)
142 {
143 s->codec = p->codec = SST_CODEC_TYPE_AACP;
144 }
145 else
146 {
147 s->codec = p->codec = SST_CODEC_TYPE_AAC;
148 }
149
150 p->num_chan = MIX_ACP_AAC_CHANNELS(acp); // core/internal channels
151 p->ext_chl = MIX_ACP_NUM_CHANNELS(acp); // external channels
152 p->aac_srate = MIX_ACP_AAC_SAMPLE_RATE(acp); // aac decoder internal frequency
153 p->sfreq = MIX_ACP_SAMPLE_FREQ(acp); // output/external frequency
154
155 p->brate = MIX_ACP_BITRATE(acp);
156 p->mpg_id = (guint)mix_acp_aac_get_mpeg_id(acp);
157 p->bs_format = mix_acp_aac_get_bit_stream_format(acp);
158 p->aac_profile = mix_acp_aac_get_aac_profile(acp);
159 // AOT defined by MPEG spec is 5 for SBR but SST definition is 4 for SBR.
160 if (aot == 5)
161 p->aot = 4;
162 else if (aot == 2)
163 p->aot = aot;
164 p->crc_check = MIX_ACP_AAC_CRC(acp);
165 p->brate_type = mix_acp_aac_get_bit_rate_type(acp);
166 p->pce_present = MIX_ACP_AAC_PCE_FLAG(acp);
167 p->pcm_wd_sz = mix_acp_get_bps(MIX_AUDIOCONFIGPARAMS(acp));
168
169 if (p->pcm_wd_sz == MIX_ACP_BPS_16)
170 p->op_align = MIX_ACP_OUTPUT_ALIGN_16;
171 else
172 p->op_align = mix_acp_get_op_align(MIX_AUDIOCONFIGPARAMS(acp));
173
174 //p->aac_srate = ; // __u32 aac_srate; /* Plain AAC decoder operating sample rate */
175 //p->ext_chl = ; // __u8 ext_chl; /* No.of external channels */
176
177 switch (p->bs_format)
178 {
179 case MIX_AAC_BS_ADTS:
180 g_sprintf((gchar*)p->bit_stream_format, "adts");
181 break;
182 case MIX_AAC_BS_ADIF:
183 g_sprintf((gchar*)p->bit_stream_format, "adif");
184 break;
185 case MIX_AAC_BS_RAW:
186 g_sprintf((gchar*)p->bit_stream_format, "raw");
187 p->num_syntc_elems = 0;
188 p->syntc_id[0] = (gint8)-1; /* 0 for ID_SCE(Dula Mono), -1 for raw */
189 p->syntc_id[1] = (gint8)-1;
190 p->syntc_tag[0] = (gint8)-1; /* raw - -1 and 0 -16 for rest of the streams */
191 p->syntc_tag[1] = (gint8)-1;
192 break;
193 default:
194 break;
195 }
196
197 {
198 AAC_DUMP(codec);
199 AAC_DUMP(num_chan); /* 1=Mono, 2=Stereo*/
200 AAC_DUMP(pcm_wd_sz); /* 16/24 - bit*/
201 AAC_DUMP(brate);
202 AAC_DUMP(sfreq); /* Sampling freq eg. 8000, 441000, 48000 */
203 AAC_DUMP(aac_srate); /* Plain AAC decoder operating sample rate */
204 AAC_DUMP(mpg_id); /* 0=MPEG-2, 1=MPEG-4 */
205 AAC_DUMP(bs_format); /* input bit stream format adts=0, adif=1, raw=2 */
206 AAC_DUMP(aac_profile); /* 0=Main Profile, 1=LC profile, 3=SSR profile */
207 AAC_DUMP(ext_chl); /* No.of external channels */
208 AAC_DUMP(aot); /* Audio object type. 1=Main , 2=LC , 3=SSR, 4=SBR*/
209 AAC_DUMP(op_align); /* output alignment 0=16 bit , 1=MSB, 2= LSB align */
210 AAC_DUMP(brate_type); /* 0=CBR, 1=VBR */
211 AAC_DUMP(crc_check); /* crc check 0= disable, 1=enable */
212 // AAC_DUMP(bit_stream_format[8]); /* input bit stream format adts/adif/raw */
213 g_message("snd_aac_params.bit_stream_format=%s", p->bit_stream_format);
214 AAC_DUMP(jstereo); /* Joint stereo Flag */
215 AAC_DUMP(sbr_present); /* 1 = SBR Present, 0 = SBR absent, for RAW */
216 AAC_DUMP(downsample); /* 1 = Downsampling ON, 0 = Downsampling OFF */
217 AAC_DUMP(num_syntc_elems); /* 1- Mono/stereo, 0 - Dual Mono, 0 - for raw */
218 g_message("snd_aac_params.syntc_id[0]=%x", p->syntc_id[0]);
219 g_message("snd_aac_params.syntc_id[1]=%x", p->syntc_id[1]);
220 g_message("snd_aac_params.syntc_tag[0]=%x", p->syntc_tag[0]);
221 g_message("snd_aac_params.syntc_tag[1]=%x", p->syntc_tag[1]);
222 //AAC_DUMP_I(syntc_id, 0); /* 0 for ID_SCE(Dula Mono), -1 for raw */
223 //AAC_DUMP_I(syntc_id, 1); /* 0 for ID_SCE(Dula Mono), -1 for raw */
224 //AAC_DUMP_I(syntc_tag, 0); /* raw - -1 and 0 -16 for rest of the streams */
225 //AAC_DUMP_I(syntc_tag, 1); /* raw - -1 and 0 -16 for rest of the streams */
226 AAC_DUMP(pce_present); /* Flag. 1- present 0 - not present, for RAW */
227 AAC_DUMP(reserved);
228 AAC_DUMP(reserved1);
229 }
230
231 return TRUE;
232 }
233
mix_sst_acp_from_codec(guint codec)234 MixAudioConfigParams *mix_sst_acp_from_codec(guint codec)
235 {
236 MixAudioConfigParams *ret = NULL;
237
238 // need stream specific ACP
239 switch (codec)
240 {
241 case SST_CODEC_TYPE_MP3:
242 case SST_CODEC_TYPE_MP24:
243 ret = (MixAudioConfigParams*)mix_acp_mp3_new();
244 break;
245 case SST_CODEC_TYPE_AAC:
246 case SST_CODEC_TYPE_AACP:
247 case SST_CODEC_TYPE_eAACP:
248 ret = (MixAudioConfigParams*)mix_acp_aac_new();
249 break;
250 case SST_CODEC_TYPE_WMA9:
251 case SST_CODEC_TYPE_WMA10:
252 case SST_CODEC_TYPE_WMA10P:
253 ret = (MixAudioConfigParams*)mix_acp_wma_new();
254 break;
255 }
256
257 return ret;
258 }
259
260
261
mix_sst_params_to_acp(struct snd_sst_get_stream_params * stream_params)262 MixAudioConfigParams *mix_sst_params_to_acp(struct snd_sst_get_stream_params *stream_params)
263 {
264 MixAudioConfigParams *ret = NULL;
265
266 gboolean allocated = FALSE;
267 // Ingoring stream_params.codec_params.result, which seem to return details specific to stream allocation.
268 switch (stream_params->codec_params.result)
269 {
270 // Please refers to SST API doc for return value definition.
271 case 5:
272 g_debug("last SET_PARAMS succeeded with Stream Parameter Modified.");
273 case 0:
274 allocated = TRUE;
275 break;
276 case 1:
277 // last SET_PARAMS failed STREAM was not available.
278 case 2:
279 // last SET_PARAMS failed CODEC was not available.
280 case 3:
281 // last SET_PARAMS failed CODEC was not supported.
282 case 4:
283 // last SET_PARAMS failed Invalid Stream Parameters.
284 case 6:
285 // last SET_PARAMS failed Invalid Stream ID.
286 default:
287 // last SET_PARAMS failed unexpectedly.
288 break;
289 }
290
291 if (allocated)
292 {
293 switch (stream_params->codec_params.codec)
294 {
295 case SST_CODEC_TYPE_MP3:
296 case SST_CODEC_TYPE_MP24:
297 ret = (MixAudioConfigParams*)mix_acp_mp3_new();
298 mix_sst_params_to_mp3(MIX_AUDIOCONFIGPARAMSMP3(ret), &stream_params->codec_params.sparams.uc.mp3_params);
299 break;
300 case SST_CODEC_TYPE_AAC:
301 case SST_CODEC_TYPE_AACP:
302 case SST_CODEC_TYPE_eAACP:
303 ret = (MixAudioConfigParams*)mix_acp_aac_new();
304 mix_sst_params_to_aac(MIX_AUDIOCONFIGPARAMSAAC(ret), &stream_params->codec_params.sparams.uc.aac_params);
305 break;
306 case SST_CODEC_TYPE_WMA9:
307 case SST_CODEC_TYPE_WMA10:
308 case SST_CODEC_TYPE_WMA10P:
309 ret = (MixAudioConfigParams*)mix_acp_wma_new();
310 mix_sst_params_to_wma(MIX_AUDIOCONFIGPARAMSWMA(ret), &stream_params->codec_params.sparams.uc.wma_params);
311 break;
312 }
313 }
314
315 if (!ret) ret = mix_acp_new();
316
317 if (ret)
318 {
319 // Be sure to update all vars that becomes available since the ACP could set defaults.
320 MIX_ACP_SAMPLE_FREQ(ret) = stream_params->pcm_params.sfreq;
321 MIX_ACP_NUM_CHANNELS(ret) = stream_params->pcm_params.num_chan;
322 mix_sst_set_bps(MIX_AUDIOCONFIGPARAMS(ret), stream_params->pcm_params.pcm_wd_sz);
323 }
324
325 return ret;
326 }
327
328
mix_sst_params_to_mp3(MixAudioConfigParamsMP3 * acp,struct snd_mp3_params * params)329 void mix_sst_params_to_mp3(MixAudioConfigParamsMP3 *acp, struct snd_mp3_params *params)
330 {
331 if(!acp || !params) return;
332
333 MIX_ACP_NUM_CHANNELS(MIX_AUDIOCONFIGPARAMS(acp)) = params->num_chan;
334 MIX_ACP_BITRATE(MIX_AUDIOCONFIGPARAMS(acp)) = params->brate;
335 MIX_ACP_SAMPLE_FREQ(MIX_AUDIOCONFIGPARAMS(acp)) = params->sfreq;
336 MIX_ACP_MP3_CRC(acp) = params->crc_check;
337
338 mix_sst_set_bps(MIX_AUDIOCONFIGPARAMS(acp), params->pcm_wd_sz);
339 mix_sst_set_op_align(MIX_AUDIOCONFIGPARAMS(acp), params->op_align);
340 }
341
mix_sst_params_to_wma(MixAudioConfigParamsWMA * acp,struct snd_wma_params * params)342 void mix_sst_params_to_wma(MixAudioConfigParamsWMA *acp, struct snd_wma_params *params)
343 {
344
345 MIX_ACP_BITRATE(acp) = params->brate;
346 MIX_ACP_SAMPLE_FREQ(acp) = params->sfreq;
347 MIX_ACP_WMA_ENCODE_OPT(acp) = params->wma_encode_opt;
348 MIX_ACP_WMA_BLOCK_ALIGN(acp) = params->block_align;
349 MIX_ACP_WMA_CHANNEL_MASK(acp) = params->channel_mask;
350 MIX_ACP_WMA_FORMAT_TAG(acp) = params->format_tag;
351 MIX_ACP_WMA_PCM_BIT_WIDTH(acp) = params->pcm_src;
352
353 mix_sst_set_bps(MIX_AUDIOCONFIGPARAMS(acp), params->pcm_wd_sz);
354 mix_sst_set_op_align(MIX_AUDIOCONFIGPARAMS(acp), params->op_align);
355
356 switch (params->codec)
357 {
358 case SST_CODEC_TYPE_WMA9:
359 mix_acp_wma_set_version(acp, MIX_AUDIO_WMA_V9);
360 break;
361 case SST_CODEC_TYPE_WMA10:
362 mix_acp_wma_set_version(acp, MIX_AUDIO_WMA_V10);
363 break;
364 case SST_CODEC_TYPE_WMA10P:
365 mix_acp_wma_set_version(acp, MIX_AUDIO_WMA_V10P);
366 break;
367 }
368 }
369
370
mix_sst_params_to_aac(MixAudioConfigParamsAAC * acp,struct snd_aac_params * params)371 void mix_sst_params_to_aac(MixAudioConfigParamsAAC *acp, struct snd_aac_params *params)
372 {
373 if (params->codec == SST_CODEC_TYPE_eAACP)
374 {
375 MIX_ACP_AAC_PS_FLAG(acp) = TRUE;
376 }
377
378 MIX_ACP_NUM_CHANNELS(acp) = params->num_chan;
379 MIX_ACP_BITRATE(acp) = params->brate;
380 MIX_ACP_SAMPLE_FREQ(acp) = params->sfreq;
381 mix_acp_aac_set_mpeg_id(acp, params->mpg_id);
382 mix_acp_aac_set_bit_stream_format(acp, params->bs_format);
383 mix_acp_aac_set_aac_profile(acp, params->aac_profile);
384
385 // SST API specific 4 for SBR while AOT definition in MPEG 4 spec specific 5.
386 // converting.
387 if (params->aot == 4)
388 mix_acp_aac_set_aot(acp, 5);
389 else if (params->aot == 2)
390 mix_acp_aac_set_aot(acp, params->aot);
391
392 MIX_ACP_AAC_CRC(acp) = params->crc_check;
393 mix_acp_aac_set_bit_rate_type(acp, params->brate_type);
394 MIX_ACP_AAC_SBR_FLAG(acp) = params->sbr_present;
395 MIX_ACP_AAC_PCE_FLAG(acp) = params->pce_present;
396
397 mix_sst_set_bps(MIX_AUDIOCONFIGPARAMS(acp), params->pcm_wd_sz);
398 mix_sst_set_op_align(MIX_AUDIOCONFIGPARAMS(acp), params->op_align);
399
400 acp->num_syntc_elems = params->num_syntc_elems;
401 acp->syntc_id[0] = params->syntc_id[0];
402 acp->syntc_id[1] = params->syntc_id[1];
403 acp->syntc_tag[0] = params->syntc_tag[0];
404 acp->syntc_tag[1] = params->syntc_tag[1];
405 }
406
mix_sst_set_bps(MixAudioConfigParams * acp,guchar pcm_wd_sz)407 void mix_sst_set_bps(MixAudioConfigParams *acp, guchar pcm_wd_sz)
408 {
409 switch (pcm_wd_sz)
410 {
411 case MIX_ACP_BPS_16:
412 case MIX_ACP_BPS_24:
413 break;
414 default:
415 pcm_wd_sz = MIX_ACP_BPS_UNKNOWN;
416 break;
417 }
418 mix_acp_set_bps(MIX_AUDIOCONFIGPARAMS(acp), pcm_wd_sz);
419 }
420
mix_sst_set_op_align(MixAudioConfigParams * acp,guchar op_align)421 void mix_sst_set_op_align(MixAudioConfigParams *acp, guchar op_align)
422 {
423 switch (op_align)
424 {
425 case MIX_ACP_OUTPUT_ALIGN_16:
426 case MIX_ACP_OUTPUT_ALIGN_MSB:
427 case MIX_ACP_OUTPUT_ALIGN_LSB:
428 break;
429 default:
430 op_align = MIX_ACP_OUTPUT_ALIGN_UNKNOWN;
431 break;
432 }
433 mix_acp_set_op_align(MIX_AUDIOCONFIGPARAMS(acp), op_align);
434 }
435
436