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