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
25gboolean mix_sst_params_convert_mp3(MixAudioConfigParamsMP3 *acp, struct snd_sst_params *s);
26gboolean mix_sst_params_convert_wma(MixAudioConfigParamsWMA *acp, struct snd_sst_params *s);
27gboolean mix_sst_params_convert_aac(MixAudioConfigParamsAAC *acp, struct snd_sst_params *s);
28void mix_sst_params_to_mp3(MixAudioConfigParamsMP3 *acp, struct snd_mp3_params *params);
29void mix_sst_params_to_wma(MixAudioConfigParamsWMA *acp, struct snd_wma_params *params);
30void mix_sst_params_to_aac(MixAudioConfigParamsAAC *acp, struct snd_aac_params *params);
31void mix_sst_set_bps(MixAudioConfigParams *acp, guchar pcm_wd_sz);
32void 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 */
38gboolean 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
55gboolean 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
73gboolean 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
112gboolean 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
234MixAudioConfigParams *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
262MixAudioConfigParams *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
329void 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
342void 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
371void 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
407void 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
421void 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