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