LCOV - code coverage report
Current view: top level - compositor - audio_mixer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 522 622 83.9 %
Date: 2021-04-29 23:48:07 Functions: 32 33 97.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/compositor_dev.h>
      27             : 
      28             : /*
      29             :         Notes about the mixer:
      30             :         1- spatialization is out of scope for the mixer (eg that's the sound node responsability)
      31             :         2- mixing is performed by resampling input source & deinterleaving its channels into dedicated buffer.
      32             :         We could directly deinterleave in the main mixer ouput buffer, but this would prevent any future
      33             :         gain correction.
      34             : */
      35             : typedef struct
      36             : {
      37             :         GF_AudioInterface *src;
      38             : 
      39             :         s32 *ch_buf[GF_AUDIO_MIXER_MAX_CHANNELS];
      40             :         /*resampled buffer*/
      41             :         u32 buffer_size;
      42             : 
      43             :         u32 bytes_per_sec, bit_depth;
      44             : 
      45             :         Bool has_prev;
      46             :         s32 last_channels[GF_AUDIO_MIXER_MAX_CHANNELS];
      47             : 
      48             :         u32 in_bytes_used, out_samples_written, out_samples_to_write;
      49             : 
      50             :         u32 out_samples_pos, in_samples_pos, scaled_sr, bytes_p_samp;
      51             :         u32 ratio_aligned;
      52             : 
      53             :         Fixed speed;
      54             :         Fixed pan[GF_AUDIO_MIXER_MAX_CHANNELS];
      55             : 
      56             :         s32 (*get_sample)(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride);
      57             :         Bool is_planar;
      58             :         Bool muted;
      59             : } MixerInput;
      60             : 
      61             : struct __audiomix
      62             : {
      63             :         /*src*/
      64             :         GF_List *sources;
      65             :         /*output config*/
      66             :         u32 sample_rate;
      67             :         u32 nb_channels;
      68             :         u32 afmt, bit_depth;
      69             :         u64 channel_layout;
      70             :         GF_Mutex *mx;
      71             :         /*if set forces stereo/mono*/
      72             :         Bool force_channel_out;
      73             :         /*set to true by mixer when detecting an audio config change*/
      74             :         Bool must_reconfig;
      75             :         Bool isEmpty;
      76             :         Bool source_buffering;
      77             :         /*set to non null if this outputs directly to the driver, in which case audio formats have to be checked*/
      78             :         struct _audio_render *ar;
      79             : 
      80             :         Fixed max_speed;
      81             : 
      82             :         s32 *output;
      83             :         u32 output_size;
      84             : };
      85             : 
      86             : #define GF_S24_MAX      8388607
      87             : #define GF_S24_MIN      -8388608
      88             : 
      89             : 
      90             : GF_EXPORT
      91         653 : GF_AudioMixer *gf_mixer_new(struct _audio_render *ar)
      92             : {
      93             :         GF_AudioMixer *am;
      94         653 :         am = (GF_AudioMixer *) gf_malloc(sizeof(GF_AudioMixer));
      95         653 :         if (!am) return NULL;
      96             :         memset(am, 0, sizeof(GF_AudioMixer));
      97         653 :         am->mx = gf_mx_new("AudioMix");
      98         653 :         am->sources = gf_list_new();
      99         653 :         am->isEmpty = GF_TRUE;
     100         653 :         am->ar = ar;
     101         653 :         am->sample_rate = 44100;
     102         653 :         am->afmt = GF_AUDIO_FMT_S16;
     103         653 :         am->bit_depth = gf_audio_fmt_bit_depth(am->afmt);
     104         653 :         am->nb_channels = 2;
     105         653 :         am->output = NULL;
     106         653 :         am->output_size = 0;
     107         653 :         am->max_speed = FIX_MAX;
     108         653 :         return am;
     109             : }
     110             : 
     111         188 : Bool gf_mixer_must_reconfig(GF_AudioMixer *am)
     112             : {
     113         188 :         return am->must_reconfig;
     114             : }
     115             : 
     116         605 : void gf_mixer_set_max_speed(GF_AudioMixer *am, Double max_speed)
     117             : {
     118         605 :         am->max_speed = FLT2FIX(max_speed);
     119         605 : }
     120             : 
     121             : GF_EXPORT
     122         652 : void gf_mixer_del(GF_AudioMixer *am)
     123             : {
     124         652 :         gf_mixer_remove_all(am);
     125         652 :         gf_list_del(am->sources);
     126         652 :         gf_mx_del(am->mx);
     127         652 :         if (am->output) gf_free(am->output);
     128         652 :         gf_free(am);
     129         652 : }
     130             : 
     131        3162 : void gf_mixer_remove_all(GF_AudioMixer *am)
     132             : {
     133             :         u32 j;
     134        3162 :         gf_mixer_lock(am, GF_TRUE);
     135        6386 :         while (gf_list_count(am->sources)) {
     136          62 :                 MixerInput *in = (MixerInput *)gf_list_get(am->sources, 0);
     137          62 :                 gf_list_rem(am->sources, 0);
     138        1550 :                 for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
     139        1488 :                         if (in->ch_buf[j]) gf_free(in->ch_buf[j]);
     140             :                 }
     141          62 :                 gf_free(in);
     142             :         }
     143        3162 :         am->isEmpty = GF_TRUE;
     144        3162 :         gf_mixer_lock(am, GF_FALSE);
     145        3162 : }
     146             : 
     147           0 : Bool gf_mixer_is_src_present(GF_AudioMixer *am, GF_AudioInterface *ifce)
     148             : {
     149             :         MixerInput *in;
     150          65 :         u32 i = 0;
     151          71 :         while ((in = (MixerInput *)gf_list_enum(am->sources, &i))) {
     152           6 :                 if (in->src == ifce) return GF_TRUE;
     153             :         }
     154             :         return GF_FALSE;
     155             : }
     156          35 : u32 gf_mixer_get_src_count(GF_AudioMixer *am)
     157             : {
     158          35 :         return gf_list_count(am->sources);
     159             : }
     160             : 
     161           1 : GF_Err gf_mixer_force_channel_out(GF_AudioMixer *am, u32 num_channels)
     162             : {
     163           1 :         if (num_channels > GF_AUDIO_MIXER_MAX_CHANNELS) {
     164           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Number of output channels %d higher than max channels supported %d\n", num_channels, GF_AUDIO_MIXER_MAX_CHANNELS));
     165             :                 return GF_NOT_SUPPORTED;
     166             :         }
     167           1 :         am->force_channel_out = GF_TRUE;
     168           1 :         am->nb_channels = num_channels;
     169           1 :         return GF_OK;
     170             : }
     171             : 
     172           1 : u32 gf_mixer_get_block_align(GF_AudioMixer *am)
     173             : {
     174           1 :         return am->nb_channels * am->bit_depth/8;
     175             : }
     176             : 
     177             : GF_EXPORT
     178      225188 : void gf_mixer_lock(GF_AudioMixer *am, Bool lockIt)
     179             : {
     180             :         //GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[AudioMixer] Thread ID %d is %s the audio mixer\n", gf_th_id(), lockIt ? "locking" : "unlocking" ));
     181      225188 :         if (lockIt) {
     182      112594 :                 gf_mx_p(am->mx);
     183             :         } else {
     184      112594 :                 gf_mx_v(am->mx);
     185             :         }
     186      225188 : }
     187             : 
     188             : GF_EXPORT
     189          42 : Bool gf_mixer_empty(GF_AudioMixer *am)
     190             : {
     191          42 :         return am->isEmpty;
     192             : }
     193             : 
     194             : GF_EXPORT
     195       28645 : Bool gf_mixer_buffering(GF_AudioMixer *am)
     196             : {
     197       28645 :         return am->source_buffering;
     198             : }
     199             : 
     200             : GF_EXPORT
     201          65 : void gf_mixer_add_input(GF_AudioMixer *am, GF_AudioInterface *src)
     202             : {
     203             :         MixerInput *in;
     204          65 :         if (gf_mixer_is_src_present(am, src)) return;
     205          65 :         gf_mixer_lock(am, GF_TRUE);
     206          65 :         GF_SAFEALLOC(in, MixerInput);
     207          65 :         if (!in) {
     208           0 :                 gf_mixer_lock(am, GF_FALSE);
     209           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Cannot allocate input source\n"));
     210             :                 return;
     211             :         }
     212          65 :         in->src = src;
     213          65 :         gf_list_add(am->sources, in);
     214          65 :         am->must_reconfig = GF_TRUE;
     215          65 :         am->isEmpty = GF_FALSE;
     216          65 :         gf_mixer_lock(am, GF_FALSE);
     217             : }
     218             : 
     219          21 : void gf_mixer_remove_input(GF_AudioMixer *am, GF_AudioInterface *src)
     220             : {
     221             :         u32 i, j, count;
     222          21 :         if (am->isEmpty) return;
     223           3 :         gf_mixer_lock(am, GF_TRUE);
     224           3 :         count = gf_list_count(am->sources);
     225           3 :         for (i=0; i<count; i++) {
     226           3 :                 MixerInput *in = (MixerInput *)gf_list_get(am->sources, i);
     227           3 :                 if (in->src != src) continue;
     228           3 :                 gf_list_rem(am->sources, i);
     229          75 :                 for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
     230          72 :                         if (in->ch_buf[j]) gf_free(in->ch_buf[j]);
     231             :                 }
     232           3 :                 gf_free(in);
     233           3 :                 break;
     234             :         }
     235           3 :         am->isEmpty = gf_list_count(am->sources) ? GF_FALSE : GF_TRUE;
     236             :         /*we don't ask for reconfig when removing a node*/
     237           3 :         gf_mixer_lock(am, GF_FALSE);
     238             : }
     239             : 
     240             : 
     241             : static GF_Err get_best_samplerate(GF_AudioMixer *am, u32 *out_sr, u32 *out_ch, u32 *out_fmt)
     242             : {
     243             :         if (!am->ar) return GF_OK;
     244             : #ifdef ENABLE_AOUT
     245             :         if (!am->ar->audio_out || !am->ar->audio_out->QueryOutputSampleRate) return GF_OK;
     246             :         return am->ar->audio_out->QueryOutputSampleRate(am->ar->audio_out, out_sr, out_ch, out_fmt);
     247             : #endif
     248             :         return GF_OK;
     249             : }
     250             : 
     251             : GF_EXPORT
     252         630 : void gf_mixer_get_config(GF_AudioMixer *am, u32 *outSR, u32 *outCH, u32 *outFMT, u64 *outChCfg)
     253             : {
     254         630 :         (*outFMT) = am->afmt;
     255         630 :         (*outCH) = am->nb_channels;
     256         630 :         (*outSR) = am->sample_rate;
     257         630 :         (*outChCfg) = am->channel_layout;
     258         630 : }
     259             : 
     260             : GF_EXPORT
     261         709 : GF_Err gf_mixer_set_config(GF_AudioMixer *am, u32 outSR, u32 outCH, u32 outFMT, u64 outChCfg)
     262             : {
     263         709 :         if ((am->afmt == outFMT) && (am->nb_channels == outCH)
     264         634 :                 && (am->sample_rate==outSR) && (am->channel_layout == outChCfg)) return GF_OK;
     265             : 
     266          84 :         if (outCH > GF_AUDIO_MIXER_MAX_CHANNELS) {
     267           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Number of output channels %d higher than max channels supported %d\n", outCH, GF_AUDIO_MIXER_MAX_CHANNELS));
     268             :                 return GF_NOT_SUPPORTED;
     269             :         }
     270          84 :         if (!outSR) {
     271           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Invalid output sample rate 0\n"));
     272             :                 return GF_NOT_SUPPORTED;
     273             :         }
     274          84 :         gf_mixer_lock(am, GF_TRUE);
     275          84 :         am->afmt = outFMT;
     276          84 :         am->bit_depth = gf_audio_fmt_bit_depth(am->afmt);
     277          84 :         if (!am->force_channel_out)
     278          84 :                 am->nb_channels = outCH;
     279             :         if (get_best_samplerate(am, &outSR, &outCH, &outFMT) == GF_OK) {
     280          84 :                 am->sample_rate = outSR;
     281          84 :                 if (outCH>2) am->channel_layout = outChCfg;
     282          83 :                 else if (outCH==2) am->channel_layout = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;
     283           8 :                 else am->channel_layout = GF_AUDIO_CH_FRONT_LEFT;
     284             :         }
     285             :         /*if main mixer recfg output*/
     286          84 :         if (am->ar)  am->ar->need_reconfig = GF_TRUE;
     287          84 :         am->must_reconfig = GF_FALSE;
     288          84 :         gf_mixer_lock(am, GF_FALSE);
     289          84 :         return GF_OK;
     290             : }
     291             : 
     292             : static GFINLINE s32 make_s24_int(u8 *ptr)
     293             : {
     294             :         s32 val;
     295             :         s16 res;
     296             :         memcpy(&res, ptr+1, 2);
     297       73728 :         val = res * 256;
     298       73728 :         val |= ptr[0];
     299             :         return val;
     300             : }
     301             : 
     302             : #define MIX_S16_SCALE   65535
     303             : #define MIX_S24_SCALE   255
     304             : #define MIX_U8_SCALE    16777215
     305             : 
     306       82944 : s32 input_sample_s32(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     307             : {
     308             :         s32 *src = (s32 *)data;
     309       82944 :         return src[sample_offset*nb_ch + channel];
     310             : }
     311       36864 : s32 input_sample_s32p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     312             : {
     313             :         s32 *src = (s32 *)data;
     314       36864 :         return src[sample_offset + planar_stride*channel/4];
     315             : }
     316       36864 : s32 input_sample_s24(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     317             : {
     318       73728 :         return make_s24_int(&data[sample_offset*nb_ch*3 + 3*channel]) * MIX_S24_SCALE;
     319             : }
     320       36864 : s32 input_sample_s24p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     321             : {
     322       73728 :         return make_s24_int(&data[sample_offset*3 + channel*planar_stride]) * MIX_S24_SCALE;
     323             : }
     324             : 
     325             : #define TRUNC_FLT_DBL(_a) \
     326             :         if (_a<-1.0) return GF_INT_MIN;\
     327             :         else if (_a>1.0) return GF_INT_MAX;\
     328             :         return (s32) (_a * GF_INT_MAX);\
     329             : 
     330       50304 : s32 input_sample_flt(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     331             : {
     332             :         Float *src = (Float *)data;
     333       50304 :         Float samp = src[sample_offset*nb_ch + channel];
     334       50304 :         TRUNC_FLT_DBL(samp);
     335             : }
     336     8529854 : s32 input_sample_fltp(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     337             : {
     338             :         Float *src = (Float *)data;
     339     8529854 :         Float samp = src[sample_offset + planar_stride*channel/4];
     340     8529854 :         TRUNC_FLT_DBL(samp);
     341             : }
     342       36864 : s32 input_sample_dbl(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     343             : {
     344             :         Double *src = (Double *)data;
     345       36864 :         Double samp = src[sample_offset*nb_ch + channel];
     346       36864 :         TRUNC_FLT_DBL(samp);
     347             : }
     348       36864 : s32 input_sample_dblp(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     349             : {
     350             :         Double *src = (Double *)data;
     351       36864 :         Double samp = src[sample_offset + planar_stride * channel / 8];
     352       36864 :         TRUNC_FLT_DBL(samp);
     353             : }
     354    14999908 : s32 input_sample_s16(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     355             : {
     356             :         s16 *src = (s16 *)data;
     357    14999908 :         s32 res = src[sample_offset*nb_ch + channel];
     358    14999908 :         return res * MIX_S16_SCALE;
     359             : }
     360       55296 : s32 input_sample_s16p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     361             : {
     362             :         s16 *src = (s16 *)data;
     363       55296 :         s32 res = src[sample_offset + planar_stride*channel / 2];
     364       55296 :         return res * MIX_S16_SCALE;
     365             : }
     366       36864 : s32 input_sample_u8(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     367             : {
     368       36864 :         s32 res = data[sample_offset*nb_ch + channel];
     369       36864 :         res -= 128;
     370       36864 :         return res * MIX_U8_SCALE;
     371             : }
     372       36864 : s32 input_sample_u8p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
     373             : {
     374       36864 :         s32 res = data[sample_offset + planar_stride*channel];
     375       36864 :         res -= 128;
     376       36864 :         return res * MIX_U8_SCALE;
     377             : }
     378             : 
     379          64 : static void gf_am_configure_source(MixerInput *in)
     380             : {
     381          64 :         in->bit_depth = gf_audio_fmt_bit_depth(in->src->afmt);
     382          64 :         in->bytes_per_sec = in->src->samplerate * in->src->chan * in->bit_depth / 8;
     383          64 :         in->is_planar = gf_audio_fmt_is_planar(in->src->afmt);
     384          64 :         switch (in->src->afmt) {
     385           2 :         case GF_AUDIO_FMT_S32:
     386           2 :                 in->get_sample = input_sample_s32;
     387           2 :                 break;
     388           1 :         case GF_AUDIO_FMT_S32P:
     389           1 :                 in->get_sample = input_sample_s32p;
     390           1 :                 break;
     391           1 :         case GF_AUDIO_FMT_S24:
     392           1 :                 in->get_sample = input_sample_s24;
     393           1 :                 break;
     394           1 :         case GF_AUDIO_FMT_S24P:
     395           1 :                 in->get_sample = input_sample_s24p;
     396           1 :                 break;
     397           4 :         case GF_AUDIO_FMT_FLT:
     398           4 :                 in->get_sample = input_sample_flt;
     399           4 :                 break;
     400          28 :         case GF_AUDIO_FMT_FLTP:
     401          28 :                 in->get_sample = input_sample_fltp;
     402          28 :                 break;
     403           1 :         case GF_AUDIO_FMT_DBL:
     404           1 :                 in->get_sample = input_sample_dbl;
     405           1 :                 break;
     406           1 :         case GF_AUDIO_FMT_DBLP:
     407           1 :                 in->get_sample = input_sample_dblp;
     408           1 :                 break;
     409          21 :         case GF_AUDIO_FMT_S16:
     410          21 :                 in->get_sample = input_sample_s16;
     411          21 :                 break;
     412           2 :         case GF_AUDIO_FMT_S16P:
     413           2 :                 in->get_sample = input_sample_s16p;
     414           2 :                 break;
     415           1 :         case GF_AUDIO_FMT_U8:
     416           1 :                 in->get_sample = input_sample_u8;
     417           1 :                 break;
     418           1 :         case GF_AUDIO_FMT_U8P:
     419           1 :                 in->get_sample = input_sample_u8p;
     420           1 :                 break;
     421             :         }
     422          64 : }
     423             : 
     424             : GF_EXPORT
     425       37195 : Bool gf_mixer_reconfig(GF_AudioMixer *am)
     426             : {
     427             :         u32 i, count, numInit, max_sample_rate, max_channels, max_afmt, cfg_changed;
     428             :         u64 ch_layout;
     429       37195 :         gf_mixer_lock(am, GF_TRUE);
     430       37195 :         if (am->isEmpty || !am->must_reconfig) {
     431       37062 :                 gf_mixer_lock(am, GF_FALSE);
     432       37062 :                 return GF_FALSE;
     433             :         }
     434             : 
     435         133 :         if (am->ar && am->ar->config_forced) {
     436           0 :                 am->must_reconfig = GF_FALSE;
     437           0 :                 gf_mixer_lock(am, GF_FALSE);
     438           0 :                 return GF_FALSE;
     439             :         }
     440             : 
     441             :         numInit = 0;
     442         133 :         max_channels = am->nb_channels;
     443         133 :         max_afmt = am->afmt;
     444             :         cfg_changed = 0;
     445             :         max_sample_rate = 0;
     446             : 
     447             :         ch_layout = 0;
     448             : 
     449         133 :         count = gf_list_count(am->sources);
     450             :         assert(count);
     451         281 :         for (i=0; i<count; i++) {
     452             :                 Bool has_cfg;
     453         148 :                 MixerInput *in = (MixerInput *) gf_list_get(am->sources, i);
     454         148 :                 has_cfg = in->src->GetConfig(in->src, GF_TRUE);
     455         148 :                 if (has_cfg) {
     456             :                         /*check same cfg...*/
     457          25 :                         if (in->src->samplerate * in->src->chan * in->bit_depth == 8*in->bytes_per_sec) {
     458          24 :                                 numInit++;
     459          24 :                                 continue;
     460             :                         }
     461         123 :                 } else continue;
     462             :                 /*update out cfg*/
     463           1 :                 if ((count==1) && (max_sample_rate != in->src->samplerate)) {
     464             : //                      cfg_changed = 1;
     465             :                         max_sample_rate = in->src->samplerate;
     466           0 :                 } else if (max_sample_rate<in->src->samplerate) {
     467             : //                      cfg_changed = 1;
     468             :                         max_sample_rate = in->src->samplerate;
     469             :                 }
     470           1 :                 if ((count==1) && (max_afmt != in->src->afmt)) {
     471             :                         cfg_changed = 1;
     472             :                         max_afmt = in->src->afmt;
     473           0 :                 } else if (max_afmt<in->src->afmt) {
     474             :                         cfg_changed = 1;
     475             :                         max_afmt = in->src->afmt;
     476             :                 }
     477           1 :                 if (!am->force_channel_out) {
     478           1 :                         if ((count==1) && (max_channels!=in->src->chan)) {
     479             :                                 cfg_changed = 1;
     480             :                                 max_channels = in->src->chan;
     481             : //                              if (in->src->forced_layout)
     482           0 :                                         ch_layout |= in->src->ch_layout;
     483             :                         }
     484             :                         else {
     485             :                                 u32 nb_ch = in->src->chan;
     486           1 :                                 if (in->src->forced_layout) {
     487           0 :                                         u64 cfg = in->src->ch_layout;
     488             :                                         nb_ch = 0;
     489           0 :                                         while (cfg) {
     490           0 :                                                 nb_ch++;
     491           0 :                                                 cfg >>= 1;
     492             :                                         }
     493           0 :                                         ch_layout |= in->src->ch_layout;
     494             :                                 }
     495           1 :                                 if (max_channels < nb_ch) {
     496             :                                         cfg_changed = 1;
     497             :                                         max_channels = nb_ch;
     498           0 :                                         if (nb_ch > 2) ch_layout |= in->src->ch_layout;
     499             :                                 }
     500             :                         }
     501             :                 }
     502             : 
     503           1 :                 numInit++;
     504           1 :                 gf_am_configure_source(in);
     505             : 
     506             :                 /*cfg has changed, we must reconfig everything*/
     507           1 :                 if (cfg_changed || (max_sample_rate != am->sample_rate) ) {
     508           1 :                         in->ratio_aligned = 0;
     509           1 :                         in->bit_depth = 0;
     510           1 :                         memset(&in->last_channels, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
     511             :                 }
     512             :         }
     513             : 
     514         133 :         if (cfg_changed || (max_sample_rate && (max_sample_rate != am->sample_rate)) ) {
     515           1 :                 if (max_channels>2) {
     516           0 :                         if (!ch_layout) {
     517             :                                 //TODO pickup default layout ?
     518           0 :                         } else if (ch_layout != am->channel_layout) {
     519             :                                 /*recompute num channel based on all input channels*/
     520             :                                 max_channels = 0;
     521           0 :                                 if (ch_layout & GF_AUDIO_CH_FRONT_LEFT) max_channels ++;
     522           0 :                                 if (ch_layout & GF_AUDIO_CH_FRONT_RIGHT) max_channels ++;
     523           0 :                                 if (ch_layout & GF_AUDIO_CH_FRONT_CENTER) max_channels ++;
     524           0 :                                 if (ch_layout & GF_AUDIO_CH_LFE) max_channels ++;
     525           0 :                                 if (ch_layout & GF_AUDIO_CH_SURROUND_LEFT) max_channels ++;
     526           0 :                                 if (ch_layout & GF_AUDIO_CH_SURROUND_RIGHT) max_channels ++;
     527           0 :                                 if (ch_layout & GF_AUDIO_CH_REAR_CENTER) max_channels ++;
     528           0 :                                 if (ch_layout & GF_AUDIO_CH_REAR_SURROUND_LEFT) max_channels ++;
     529           0 :                                 if (ch_layout & GF_AUDIO_CH_REAR_SURROUND_RIGHT) max_channels ++;
     530             :                         }
     531             :                 } else {
     532             :                         ch_layout = GF_AUDIO_CH_FRONT_LEFT;
     533           1 :                         if (max_channels==2) ch_layout |= GF_AUDIO_CH_FRONT_RIGHT;
     534             :                 }
     535           1 :                 gf_mixer_set_config(am, max_sample_rate, max_channels, max_afmt, ch_layout);
     536             :         }
     537             : 
     538         133 :         if (numInit == count) am->must_reconfig = GF_FALSE;
     539         133 :         if (am->ar) cfg_changed = 1;
     540             : 
     541         133 :         gf_mixer_lock(am, GF_FALSE);
     542         133 :         return cfg_changed;
     543             : }
     544             : 
     545             : static GFINLINE u32 get_channel_out_pos(u32 in_ch, u64 out_ch_layout)
     546             : {
     547             :         u32 i, cfg, pos;
     548             :         pos = 0;
     549           0 :         for (i=0; i<9; i++) {
     550           0 :                 cfg = 1<<(i);
     551           0 :                 if (out_ch_layout & cfg) {
     552           0 :                         if (cfg == in_ch) return pos;
     553           0 :                         pos++;
     554             :                 }
     555             :         }
     556             :         return GF_AUDIO_MIXER_MAX_CHANNELS;
     557             : }
     558             : 
     559             : /*this is crude, we'd need a matrix or something*/
     560     8046935 : static GFINLINE void gf_mixer_map_channels(s32 *inChan, u32 nb_in, u64 in_ch_layout, Bool forced_layout, u32 nb_out, u64 out_ch_layout)
     561             : {
     562             :         u32 i;
     563     8046935 :         if (nb_in==1) {
     564             :                 /*mono to stereo*/
     565       31872 :                 if (nb_out==2) {
     566             :                         //layout forced, don't copy
     567           0 :                         if (in_ch_layout && forced_layout) {
     568             :                                 u32 idx = 0;
     569             :                                 while (1) {
     570           0 :                                         in_ch_layout >>= 1;
     571           0 :                                         if (!in_ch_layout) break;
     572           0 :                                         idx++;
     573             :                                 }
     574           0 :                                 if (idx) {
     575             : //                                      inChan[idx] = inChan[0];
     576             : //                                      inChan[0] = 0;
     577           0 :                                         inChan[1] = inChan[0];
     578             :                                 } else {
     579           0 :                                         inChan[1] = inChan[0];
     580             :                                 }
     581             :                         } else {
     582           0 :                                 inChan[1] = inChan[0];
     583             :                         }
     584             :                 }
     585       31872 :                 else if (nb_out>2) {
     586             :                         /*if center channel use it (we assume we always have stereo channels)*/
     587           0 :                         if (out_ch_layout & GF_AUDIO_CH_FRONT_CENTER) {
     588           0 :                                 inChan[2] = inChan[0];
     589           0 :                                 inChan[0] = 0;
     590           0 :                                 for (i=3; i<nb_out; i++) inChan[i] = 0;
     591             :                         } else {
     592             :                                 /*mono to stereo*/
     593           0 :                                 inChan[1] = inChan[0];
     594           0 :                                 for (i=2; i<nb_out; i++) inChan[i] = 0;
     595             :                         }
     596             :                 }
     597     8015063 :         } else if (nb_in==2) {
     598     8015063 :                 if (nb_out==1) {
     599           0 :                         s64 sum = (s64)inChan[0] + (s64) inChan[1];
     600           0 :                         inChan[0] = (s32) (sum/2);
     601             :                 } else {
     602           0 :                         for (i=2; i<nb_out; i++) inChan[i] = 0;
     603             :                 }
     604             :         }
     605             :         /*same output than input channels, nothing to reorder*/
     606             : 
     607             :         /*more output than input channels*/
     608           0 :         else if (nb_in<nb_out) {
     609             :                 s32 bckup[GF_AUDIO_MIXER_MAX_CHANNELS];
     610             :                 u32 pos;
     611             :                 u64 cfg = in_ch_layout;
     612             :                 u32 ch = 0;
     613           0 :                 memcpy(bckup, inChan, sizeof(s32)*nb_in);
     614           0 :                 for (i=0; i<nb_in; i++) {
     615             :                         /*get first in channel*/
     616           0 :                         while (! (cfg & 1)) {
     617           0 :                                 ch++;
     618           0 :                                 cfg>>=1;
     619             :                                 /*done*/
     620           0 :                                 if (ch==10) return;
     621             :                         }
     622           0 :                         pos = get_channel_out_pos((1<<ch), out_ch_layout);
     623             :                         assert(pos != GF_AUDIO_MIXER_MAX_CHANNELS);
     624           0 :                         inChan[pos] = bckup[i];
     625           0 :                         ch++;
     626           0 :                         cfg>>=1;
     627             :                 }
     628           0 :                 for (i=nb_in; i<nb_out; i++) inChan[i] = 0;
     629             :         }
     630             :         /*less output than input channels (eg sound card doesn't support requested format*/
     631           0 :         else if (nb_in>nb_out) {
     632             :                 s32 bckup[GF_AUDIO_MIXER_MAX_CHANNELS];
     633             :                 u32 pos;
     634             :                 u64 cfg = in_ch_layout;
     635             :                 u32 ch = 0;
     636           0 :                 memcpy(bckup, inChan, sizeof(s32)*nb_in);
     637           0 :                 for (i=0; i<nb_in; i++) {
     638             :                         /*get first in channel*/
     639           0 :                         while (! (cfg & 1)) {
     640           0 :                                 ch++;
     641           0 :                                 cfg>>=1;
     642             :                                 /*done*/
     643           0 :                                 if (ch==10) return;
     644             :                         }
     645           0 :                         pos = get_channel_out_pos( (1<<ch), out_ch_layout);
     646             :                         /*this channel is present in output, copy over*/
     647           0 :                         if (pos < GF_AUDIO_MIXER_MAX_CHANNELS) {
     648           0 :                                 inChan[pos] = bckup[i];
     649             :                         } else {
     650             :                                 /*map to stereo (we assume that the driver cannot handle ANY multichannel cfg)*/
     651           0 :                                 switch (1<<ch) {
     652           0 :                                 case GF_AUDIO_CH_FRONT_CENTER:
     653             :                                 case GF_AUDIO_CH_LFE:
     654             :                                 case GF_AUDIO_CH_REAR_CENTER:
     655           0 :                                         inChan[0] += bckup[i]/2;
     656           0 :                                         inChan[1] += bckup[i]/2;
     657           0 :                                         break;
     658           0 :                                 case GF_AUDIO_CH_SURROUND_LEFT:
     659             :                                 case GF_AUDIO_CH_REAR_SURROUND_LEFT:
     660           0 :                                         inChan[0] += bckup[i];
     661           0 :                                         break;
     662           0 :                                 case GF_AUDIO_CH_SURROUND_RIGHT:
     663             :                                 case GF_AUDIO_CH_REAR_SURROUND_RIGHT:
     664           0 :                                         inChan[1] += bckup[i];
     665           0 :                                         break;
     666             :                                 }
     667             :                         }
     668           0 :                         ch++;
     669           0 :                         cfg>>=1;
     670             :                 }
     671             :         }
     672             : }
     673             : 
     674             : #define RESAMPLE_SCALER 1000
     675             : 
     676       42054 : static void gf_mixer_fetch_input(GF_AudioMixer *am, MixerInput *in, u32 audio_delay)
     677             : {
     678             :         u32 j, in_ch, out_ch, prev, next, src_samp, src_size;
     679             :         Bool use_prev;
     680       42054 :         u32 planar_stride=0;
     681             :         s8 *in_data;
     682             :         s32 frac, inChan[GF_AUDIO_MIXER_MAX_CHANNELS], inChanNext[GF_AUDIO_MIXER_MAX_CHANNELS];
     683             : 
     684       42054 :         in_ch = in->src->chan;
     685       42054 :         out_ch = am->nb_channels;
     686       42054 :         use_prev = in->has_prev;
     687             : 
     688       42054 :         in_data = (s8 *) in->src->FetchFrame(in->src->callback, &src_size, &planar_stride, audio_delay);
     689       42054 :         if (!in_data || !src_size) {
     690             :                 //end of stream, flush if needed
     691       28072 :                 if (in->src->is_eos && use_prev) {
     692             : 
     693             :                 } else {
     694             :                         /*done, stop fill*/
     695       28072 :                         in->out_samples_to_write = 0;
     696       56144 :                         return;
     697             :                 }
     698             :         }
     699             : 
     700             :         //config changed, recompute our values
     701       13982 :         if (!in->ratio_aligned) {
     702          66 :                 u32 ratio = (u32) (in->src->samplerate * FIX2INT(255*in->speed) / am->sample_rate);
     703          66 :                 if (ratio % 255) in->ratio_aligned = 2;
     704          43 :                 else in->ratio_aligned = 1;
     705             : 
     706          66 :                 in->in_samples_pos = in->out_samples_pos = 0;
     707          66 :                 in->scaled_sr = FIX2INT(in->src->samplerate * in->speed);
     708             : 
     709          66 :                 in->bytes_p_samp = in->bit_depth * in->src->chan / 8;
     710             :         }
     711       13982 :         src_samp = (u32) (src_size / in->bytes_p_samp);
     712             : 
     713             : 
     714             :         memset(inChan, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
     715             :         memset(inChanNext, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
     716             : 
     717             :         /*while output not full and input data, convert*/
     718             :         next = prev = 0;
     719             :         while (1) {
     720             :                 u64 src_pos, src_pos_unscale, lfrac;
     721     8053182 :                 src_pos_unscale = in->out_samples_pos;
     722     8053182 :                 src_pos_unscale *= in->scaled_sr;
     723             :                 src_pos = src_pos_unscale;
     724     8053182 :                 src_pos /= am->sample_rate;
     725     8053182 :                 lfrac = src_pos_unscale - src_pos * am->sample_rate;
     726     8053182 :                 lfrac *= RESAMPLE_SCALER;
     727     8053182 :                 frac = (s32) (lfrac / am->sample_rate);
     728             : 
     729     8053182 :                 if (src_samp) {
     730     8053182 :                         if (src_pos < in->in_samples_pos) {
     731             :                                 use_prev = GF_TRUE;
     732             :                                 prev = 0;
     733             :                                 next = 0;
     734             :                         } else {
     735     8045246 :                                 prev = (u32) (src_pos - in->in_samples_pos);
     736     8045246 :                                 next = prev+1;
     737             :                         }
     738             : 
     739     8053182 :                         if (prev>=src_samp)
     740             :                                 break;
     741     8052673 :                         if (frac && (next>=src_samp))
     742             :                                 break;
     743             : 
     744     8047641 :                         if (use_prev && prev)
     745             :                                 use_prev = GF_FALSE;
     746             : 
     747             :                 }
     748             :                 //end of stream, no fraction
     749             :                 else {
     750           0 :                         if (!frac || (src_pos >= in->in_samples_pos)) {
     751             :                                 //so that next call will trigger EOS for this stream
     752           0 :                                 in->has_prev = GF_FALSE;
     753           0 :                                 in->in_bytes_used = src_size + 1;
     754           0 :                                 return;
     755             :                         }
     756             :                         frac = 0;
     757             :                 }
     758             : 
     759    24111051 :                 for (j = 0; j < in_ch; j++) {
     760    16063410 :                         inChan[j] = use_prev ? in->last_channels[j] : in->get_sample(in_data, in_ch, prev, j, planar_stride);
     761    16063410 :                         if (frac) {
     762     7954668 :                                 inChanNext[j] = in->get_sample(in_data, in_ch, next, j, planar_stride);
     763     7954668 :                                 inChan[j] = (s32) ( ( ((s64) inChanNext[j])*frac + ((s64)inChan[j])*(RESAMPLE_SCALER-frac)) / RESAMPLE_SCALER );
     764             :                         }
     765             :                         //don't apply pan when forced layout is used
     766    16063410 :                         if (!in->src->forced_layout && (in->pan[j]!=FIX_ONE) ) {
     767     6334460 :                                 inChan[j] = (s32) ( ((s64) inChan[j]) * FIX2INT(100 * in->pan[j]) / 100);
     768             :                         }
     769             :                 }
     770             : 
     771     8047641 :                 if (in->speed <= am->max_speed) {
     772             :                         //map inChannel to the output channel config
     773     8046935 :                         gf_mixer_map_channels(inChan, in_ch, in->src->ch_layout, in->src->forced_layout, out_ch, am->channel_layout);
     774             : 
     775    24108933 :                         for (j=0; j<out_ch ; j++) {
     776    16061998 :                                 *(in->ch_buf[j] + in->out_samples_written) = (s32) inChan[j];
     777             :                         }
     778             :                 } else {
     779        1412 :                         for (j=0; j<out_ch ; j++) {
     780        1412 :                                 *(in->ch_buf[j] + in->out_samples_written) = 0;
     781             :                         }
     782             :                 }
     783             : 
     784     8047641 :                 in->out_samples_written ++;
     785     8047641 :                 in->out_samples_pos ++;
     786     8047641 :                 if (in->out_samples_written == in->out_samples_to_write)
     787             :                         break;
     788             :         }
     789             :         //eos
     790       13982 :         if (!src_samp)
     791             :                 return;
     792             : 
     793       13982 :         if (in->ratio_aligned==1) {
     794        2667 :                 in->has_prev = GF_FALSE;
     795        2667 :                 if (next==src_samp) {
     796        2468 :                         in->in_bytes_used = src_size;
     797             :                 } else {
     798         199 :                         in->in_bytes_used = MIN(src_size, prev * in->bytes_p_samp);
     799             :                 }
     800             :         } else {
     801       11315 :                 in->in_bytes_used = (prev+1) * in->bytes_p_samp;
     802       11315 :                 in->has_prev = GF_TRUE;
     803             : 
     804       11315 :                 if (!src_samp || (in->in_bytes_used >= src_size)) {
     805        5692 :                         in->in_bytes_used = src_size;
     806        5692 :                         for (j=0; j<in_ch; j++) in->last_channels[j] = inChanNext[j];
     807             :                 } else {
     808             :                         u32 idx;
     809        5623 :                         idx = (prev >= src_samp) ? (src_samp-1) : (prev);
     810       16869 :                         for (j=0; j<in_ch; j++) {
     811       11246 :                                 in->last_channels[j] = in->get_sample(in_data, in_ch, idx, j, planar_stride);
     812             :                         }
     813             :                 }
     814             :         }
     815       13982 :         in->in_samples_pos += in->in_bytes_used / in->bytes_p_samp;
     816             : 
     817             :         /*skip full seconds done*/
     818       28145 :         while ((in->in_samples_pos >= in->scaled_sr) && (in->out_samples_pos >= am->sample_rate)) {
     819         181 :                 in->in_samples_pos -= in->scaled_sr;
     820         181 :                 in->out_samples_pos -= am->sample_rate;
     821             :         }
     822             : 
     823             :         /*cf below, make sure we call release*/
     824       13982 :         in->in_bytes_used += 1;
     825             : }
     826             : 
     827             : GF_EXPORT
     828       37121 : u32 gf_mixer_get_output(GF_AudioMixer *am, void *buffer, u32 buffer_size, u32 delay)
     829             : {
     830             :         MixerInput *in, *single_source;
     831             :         Fixed pan[GF_AUDIO_MIXER_MAX_CHANNELS];
     832             :         Bool is_muted, force_mix;
     833             :         u32 i, j, count, size, in_size, nb_samples, nb_written;
     834             :         s32 *out_mix, nb_act_src;
     835             :         char *data, *ptr;
     836             : 
     837       37121 :         am->source_buffering = GF_FALSE;
     838             :         //reset buffer whatever the state of the mixer is
     839       37121 :         memset(buffer, 0, buffer_size);
     840             : 
     841             :         /*the config has changed we don't write to output since settings change*/
     842       37121 :         if (gf_mixer_reconfig(am)) return 0;
     843             : 
     844       37020 :         gf_mixer_lock(am, GF_TRUE);
     845       37020 :         count = gf_list_count(am->sources);
     846       37020 :         if (!count) {
     847           5 :                 gf_mixer_lock(am, GF_FALSE);
     848           5 :                 return 0;
     849             :         }
     850             : 
     851       37015 :         size=0;
     852             :         single_source = NULL;
     853       37015 :         if (count!=1) goto do_mix;
     854       36830 :         if (am->force_channel_out) goto do_mix;
     855       36814 :         single_source = (MixerInput *) gf_list_get(am->sources, 0);
     856             :         /*if cfg changed or unknown, reconfigure the mixer if the audio renderer is attached. Otherwise,  the mixer config never changes internally*/
     857       36814 :         if (!single_source->src->GetConfig(single_source->src, GF_FALSE)) {
     858          47 :                 single_source->ratio_aligned = 0;
     859          47 :                 single_source->bit_depth = 0;
     860          47 :                 if (am->ar) {
     861           5 :                         am->must_reconfig = GF_TRUE;
     862           5 :                         gf_mixer_reconfig(am);
     863           5 :                         gf_mixer_lock(am, GF_FALSE);
     864           5 :                         return 0;
     865             :                 } else {
     866          42 :                         gf_mixer_reconfig(am);
     867          42 :                         gf_mixer_lock(am, GF_FALSE);
     868          42 :                         return 0;
     869             :                 }
     870             :         }
     871             : 
     872       36767 :         single_source->muted = single_source->src->IsMuted(single_source->src->callback);
     873             :         /*this happens if input SR cannot be mapped to output audio hardware*/
     874       36767 :         if (single_source->src->samplerate != am->sample_rate) goto do_mix;
     875             :         /*note we don't check output cfg: if the number of channel is the same then the channel cfg is the
     876             :         same*/
     877        2961 :         if (single_source->src->chan != am->nb_channels) goto do_mix;
     878        2961 :         if (single_source->src->GetSpeed(single_source->src->callback)!=FIX_ONE) goto do_mix;
     879        2922 :         if (single_source->src->GetChannelVolume(single_source->src->callback, pan)) goto do_mix;
     880        2922 :         if (single_source->src->afmt != am->afmt) goto do_mix;
     881             : 
     882         371 : single_source_mix:
     883             : 
     884             :         ptr = (char *)buffer;
     885             :         in_size = buffer_size;
     886         371 :         is_muted = single_source->muted;
     887             : 
     888        1108 :         while (buffer_size) {
     889             :                 u32 planar_stride;
     890         372 :                 size = 0;
     891         372 :                 data = single_source->src->FetchFrame(single_source->src->callback, &size, &planar_stride, delay);
     892         372 :                 if (!data || !size) {
     893           6 :                         am->source_buffering = single_source->src->is_buffering;
     894           6 :                         break;
     895             :                 }
     896             :                 /*don't copy more than possible*/
     897         366 :                 if (size > buffer_size) size = buffer_size;
     898         366 :                 if (!is_muted) {
     899         366 :                         memcpy(ptr, data, size);
     900             :                 }
     901         366 :                 buffer_size -= size;
     902         366 :                 ptr += size;
     903         366 :                 single_source->src->ReleaseFrame(single_source->src->callback, size);
     904         366 :                 delay += size * 8000 / am->bit_depth / am->sample_rate / am->nb_channels;
     905             :         }
     906             : 
     907             :         /*not completely filled*/
     908         371 :         if (!size || !buffer_size) {
     909         371 :                 if (buffer_size) {
     910           6 :                         if (!data) {
     911           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioMixer] not enough input data (%d still to fill)\n", buffer_size));
     912             :                         }
     913             :                 }
     914         371 :                 gf_mixer_lock(am, GF_FALSE);
     915         371 :                 return (in_size - buffer_size);
     916             :         }
     917             : 
     918             :         //otherwise, we do have some data but we had a change in config while writing the sample - fallthrough to full mix mode
     919             :         buffer = ptr;
     920             : 
     921             : 
     922       36597 : do_mix:
     923             :         nb_act_src = 0;
     924       36597 :         nb_samples = buffer_size / (am->nb_channels * am->bit_depth / 8);
     925             :         /*step 1, cfg*/
     926       36597 :         if (am->output_size<buffer_size) {
     927          56 :                 am->output = (s32*)gf_realloc(am->output, sizeof(s32) * buffer_size);
     928          56 :                 am->output_size = buffer_size;
     929             :         }
     930             : 
     931             :         single_source = NULL;
     932             :         force_mix = GF_FALSE;
     933       37152 :         for (i=0; i<count; i++) {
     934             :                 Fixed speed;
     935       37152 :                 in = (MixerInput *)gf_list_get(am->sources, i);
     936       37152 :                 in->muted = in->src->IsMuted(in->src->callback);
     937       37152 :                 if (in->muted) continue;
     938       37120 :                 if (!in->bit_depth) gf_am_configure_source(in);
     939             : 
     940       37120 :                 if (in->buffer_size < nb_samples) {
     941        1488 :                         for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
     942        1488 :                                 in->ch_buf[j] = (s32 *) gf_realloc(in->ch_buf[j], sizeof(s32) * nb_samples);
     943             :                         }
     944          62 :                         in->buffer_size = nb_samples;
     945             :                 }
     946       37120 :                 speed = in->src->GetSpeed(in->src->callback);
     947       37120 :                 if (speed != in->speed) {
     948          66 :                         in->speed = speed;
     949          66 :                         if (in->speed<0) in->speed *= -1;
     950          66 :                         in->ratio_aligned = 0;
     951             :                 }
     952       37120 :                 in->out_samples_written = 0;
     953       37120 :                 in->in_bytes_used = 0;
     954             : 
     955             :                 /*if cfg unknown or changed (AudioBuffer child...) invalidate cfg settings*/
     956       37120 :                 if (!in->src->GetConfig(in->src, GF_FALSE)) {
     957           0 :                         if (am->ar) {
     958           0 :                                 if (!am->must_reconfig) {
     959           0 :                                         am->must_reconfig = GF_TRUE;
     960             :                                         /*if main mixer reconfig asap*/
     961           0 :                                         gf_mixer_reconfig(am);
     962             :                                 }
     963           0 :                                 in->muted = GF_TRUE;
     964           0 :                                 continue;
     965             :                         }
     966             :                         //otherwise fallthrough, mixer keeps the same config
     967             :                         force_mix = GF_TRUE;
     968             :                 }
     969             : 
     970       37120 :                 if (in->speed==0) {
     971         606 :                         in->out_samples_to_write = 0;
     972             :                 } else {
     973             :                         assert(in->src->samplerate);
     974       36514 :                         in->out_samples_to_write = nb_samples;
     975       36514 :                         if (in->src->IsMuted(in->src->callback)) {
     976           0 :                                 memset(in->pan, 0, sizeof(Fixed)*GF_AUDIO_MIXER_MAX_CHANNELS);
     977             :                         } else {
     978       36514 :                                 if (!force_mix  && !in->src->GetChannelVolume(in->src->callback, in->pan)) {
     979             :                                         /*track first active source with same cfg as mixer*/
     980       20161 :                                         if (!single_source && (in->src->samplerate == am->sample_rate)
     981        2590 :                                                 && (in->src->chan == am->nb_channels)
     982        2590 :                                                 && (in->speed == FIX_ONE)
     983        2551 :                                                 && (in->src->afmt == am->afmt)
     984             :                                            )
     985             :                                                 single_source = in;
     986             :                                 }
     987             :                         }
     988       36514 :                         nb_act_src ++;
     989             :                 }
     990             :         }
     991       36597 :         if (!nb_act_src) {
     992         638 :                 gf_mixer_lock(am, GF_FALSE);
     993         638 :                 return 0;
     994             :         }
     995             : 
     996             :         /*if only one active source in native format, process as single source (direct copy)
     997             :         this is needed because mediaControl on an audio object doesn't deactivate it (eg the audio
     998             :         object is still present in the mixer). this opt is typically useful for language selection
     999             :         content (cf mp4menu)*/
    1000       35959 :         if ((nb_act_src==1) && single_source) goto single_source_mix;
    1001             : 
    1002             :         /*step 2, fill all buffers*/
    1003             :         while (1) {
    1004             :                 u32 nb_to_fill = 0;
    1005             :                 /*fill*/
    1006       83078 :                 for (i=0; i<count; i++) {
    1007       42055 :                         in = (MixerInput *)gf_list_get(am->sources, i);
    1008       42055 :                         if (in->muted) {
    1009           0 :                                 in->out_samples_to_write = 0;
    1010           0 :                                 continue;
    1011             :                         }
    1012       42055 :                         if (in->out_samples_to_write > in->out_samples_written) {
    1013       42054 :                                 gf_mixer_fetch_input(am, in, delay /*+ 8000 * i / am->bits_per_sample / am->sample_rate / am->nb_channels*/ );
    1014       42054 :                                 if (in->out_samples_to_write > in->out_samples_written) nb_to_fill++;
    1015             :                         }
    1016             :                 }
    1017             :                 /*release - this is done in 2 steps in case 2 audio object use the same source...*/
    1018       42055 :                 for (i=0; i<count; i++) {
    1019       42055 :                         in = (MixerInput *)gf_list_get(am->sources, i);
    1020       42055 :                         if (in->muted) continue;
    1021       42055 :                         if (in->in_bytes_used>1) in->src->ReleaseFrame(in->src->callback, in->in_bytes_used-1);
    1022       42055 :                         in->in_bytes_used = 0;
    1023             :                 }
    1024       41023 :                 if (!nb_to_fill) break;
    1025             :                 //only resync on the first fill
    1026             :                 delay=0;
    1027             :         }
    1028             :         /*step 3, mix the final buffer*/
    1029       35959 :         memset(am->output, 0, sizeof(s32) * buffer_size);
    1030             : 
    1031             :         nb_written = 0;
    1032       72473 :         for (i=0; i<count; i++) {
    1033             :                 u32 k;
    1034       36514 :                 out_mix = am->output;
    1035       36514 :                 in = (MixerInput *)gf_list_get(am->sources, i);
    1036       36514 :                 if (!in->out_samples_written) continue;
    1037             :                 /*only write what has been filled in the source buffer (may be less than output size)*/
    1038     8047641 :                 for (j = 0; j < in->out_samples_written; j++) {
    1039    16063410 :                         for (k = 0; k < am->nb_channels; k++) {
    1040    16063410 :                                 s64 oval = (*out_mix);
    1041    16063410 :                                 oval += *(in->ch_buf[k] + j);
    1042    16063410 :                                 if (oval>GF_INT_MAX) oval = GF_INT_MAX;
    1043    16063410 :                                 else if (oval<GF_INT_MIN) oval = GF_INT_MIN;
    1044    16063410 :                                 (*out_mix) = (s32) oval;
    1045    16063410 :                                 out_mix += 1;
    1046             :                         }
    1047             :                 }
    1048        8528 :                 if (nb_written < in->out_samples_written) nb_written = in->out_samples_written;
    1049             :         }
    1050             : 
    1051       35959 :         if (!nb_written) {
    1052       27968 :                 gf_mixer_lock(am, GF_FALSE);
    1053       27968 :                 return 0;
    1054             :         }
    1055             : 
    1056             :         //TODO big-endian support (output is assumed to be little endian PCM)
    1057             : 
    1058             :         //we do not re-normalize based on the number of input, this is the author's responsability
    1059        7991 :         out_mix = am->output;
    1060        7991 :         if (am->afmt == GF_AUDIO_FMT_S32) {
    1061             :                 s32 *out_s32 = (s32 *)buffer;
    1062       18432 :                 for (i = 0; i < nb_written; i++) {
    1063       36864 :                         for (j = 0; j < am->nb_channels; j++) {
    1064       36864 :                                 s32 samp = (*out_mix);
    1065       36864 :                                 (*out_s32) = samp;
    1066       36864 :                                 out_s32 += 1;
    1067       36864 :                                 out_mix += 1;
    1068             :                         }
    1069             :                 }
    1070             :         }
    1071        7973 :         else if (am->afmt == GF_AUDIO_FMT_S32P) {
    1072             :                 s32 *out_s32 = (s32 *) buffer;
    1073          36 :                 for (j = 0; j < am->nb_channels; j++) {
    1074          36 :                         out_mix = am->output + j;
    1075       36900 :                         for (i = 0; i < nb_written; i++) {
    1076       36864 :                                 s32 samp = (*out_mix);
    1077       36864 :                                 (*out_s32) = samp;
    1078       36864 :                                 out_s32 += 1;
    1079       36864 :                                 out_mix += am->nb_channels;
    1080             :                         }
    1081             :                 }
    1082             :         }
    1083        7955 :         else if (am->afmt == GF_AUDIO_FMT_FLT) {
    1084             :                 Float *out_flt = (Float *)buffer;
    1085       36864 :                 for (i = 0; i < nb_written; i++) {
    1086       73728 :                         for (j = 0; j < am->nb_channels; j++) {
    1087       73728 :                                 s32 samp = (*out_mix);
    1088       73728 :                                 (*out_flt) = ((Float)samp) / GF_INT_MAX;
    1089       73728 :                                 out_flt += 1;
    1090       73728 :                                 out_mix += 1;
    1091             :                         }
    1092             :                 }
    1093             :         }
    1094        7919 :         else if (am->afmt == GF_AUDIO_FMT_FLTP) {
    1095             :                 Float *out_flt = (Float *)buffer;
    1096        3144 :                 for (j = 0; j < am->nb_channels; j++) {
    1097        3144 :                         out_mix = am->output + j;
    1098     1814088 :                         for (i = 0; i < nb_written; i++) {
    1099     1810944 :                                 s32 samp = (*out_mix);
    1100     1810944 :                                 (*out_flt) = ((Float)samp) / GF_INT_MAX;
    1101     1810944 :                                 out_flt += 1;
    1102     1810944 :                                 out_mix += am->nb_channels;
    1103             :                         }
    1104             :                 }
    1105             :         }
    1106        6347 :         else if (am->afmt == GF_AUDIO_FMT_DBL) {
    1107             :                 Double *out_dbl = (Double *)buffer;
    1108       18432 :                 for (i = 0; i < nb_written; i++) {
    1109       36864 :                         for (j = 0; j < am->nb_channels; j++) {
    1110       36864 :                                 s32 samp = (*out_mix);
    1111       36864 :                                 (*out_dbl) = ((Double)samp) / GF_INT_MAX;
    1112       36864 :                                 out_dbl += 1;
    1113       36864 :                                 out_mix += 1;
    1114             :                         }
    1115             :                 }
    1116             :         }
    1117        6329 :         else if (am->afmt == GF_AUDIO_FMT_DBLP) {
    1118             :                 Double *out_dbl = (Double *)buffer;
    1119          36 :                 for (j = 0; j < am->nb_channels; j++) {
    1120          36 :                         out_mix = am->output + j;
    1121       36900 :                         for (i = 0; i < nb_written; i++) {
    1122       36864 :                                 s32 samp = (*out_mix);
    1123       36864 :                                 (*out_dbl) = ((Double)samp) / GF_INT_MAX;
    1124       36864 :                                 out_dbl += 1;
    1125       36864 :                                 out_mix += am->nb_channels;
    1126             :                         }
    1127             :                 }
    1128             :         }
    1129        6311 :         else if (am->afmt == GF_AUDIO_FMT_S24) {
    1130             :                 s8 *out_s24 = (s8 *)buffer;
    1131       18432 :                 for (i = 0; i<nb_written; i++) {
    1132       36864 :                         for (j = 0; j<am->nb_channels; j++) {
    1133       36864 :                                 s32 samp = (*out_mix);
    1134             : //                              char samp_c[4];
    1135       36864 :                                 samp /= MIX_S24_SCALE;
    1136       36864 :                                 if (samp > GF_S24_MAX) samp = GF_S24_MAX;
    1137       36864 :                                 else if (samp < GF_S24_MIN) samp = GF_S24_MIN;
    1138             : //                              memcpy(samp_c, &samp, 3);
    1139       36864 :                                 out_s24[2] = (samp>>16) & 0xFF;
    1140       36864 :                                 out_s24[1] = (samp>>8) & 0xFF;
    1141       36864 :                                 out_s24[0] = samp & 0xFF;
    1142       36864 :                                 out_s24 += 3;
    1143       36864 :                                 out_mix += 1;
    1144             :                         }
    1145             :                 }
    1146        6293 :         } else if (am->afmt == GF_AUDIO_FMT_S24P) {
    1147             :                 s8 *out_s24 = (s8 *)buffer;
    1148          36 :                 for (j = 0; j<am->nb_channels; j++) {
    1149          36 :                         out_mix = am->output + j;
    1150       36900 :                         for (i = 0; i<nb_written; i++) {
    1151       36864 :                                 s32 samp = (*out_mix);
    1152             :                                 char s16tmp[2];
    1153             :                                 u8 lsb;
    1154       36864 :                                 samp /= MIX_S24_SCALE;
    1155       36864 :                                 if (samp > GF_S24_MAX) samp = GF_S24_MAX;
    1156       36864 :                                 else if (samp < GF_S24_MIN) samp = GF_S24_MIN;
    1157             :                                 lsb = (samp) & 0xFF;
    1158       36864 :                                 samp >>= 8;
    1159             : //                              *((s16 *) (out_s24 +1) ) = (s16)samp;
    1160       36864 :                                 *((s16 *) s16tmp) = (s16)samp;
    1161       36864 :                                 memcpy(out_s24 +1, s16tmp, 2);
    1162       36864 :                                 out_s24[0] = lsb;
    1163       36864 :                                 out_s24 += 3;
    1164       36864 :                                 out_mix += am->nb_channels;
    1165             :                         }
    1166             :                 }
    1167        6275 :         } else if (am->afmt == GF_AUDIO_FMT_S16) {
    1168             :                 s16 *out_s16 = (s16 *)buffer;
    1169     6389529 :                 for (i = 0; i<nb_written; i++) {
    1170    12747186 :                         for (j = 0; j<am->nb_channels; j++) {
    1171    12747186 :                                 s32 samp = (*out_mix);
    1172    12747186 :                                 samp /= MIX_S16_SCALE;
    1173    12747186 :                                 if (samp > GF_SHORT_MAX) samp = GF_SHORT_MAX;
    1174             :                                 else if (samp < GF_SHORT_MIN) samp = GF_SHORT_MIN;
    1175    12747186 :                                 (*out_s16) = samp;
    1176    12747186 :                                 out_s16 += 1;
    1177    12747186 :                                 out_mix += 1;
    1178             :                         }
    1179             :                 }
    1180          54 :         } else if (am->afmt == GF_AUDIO_FMT_S16P) {
    1181             :                 s16 *out_s16 = (s16 *)buffer;
    1182          36 :                 for (j = 0; j<am->nb_channels; j++) {
    1183          36 :                         out_mix = am->output + j;
    1184       36900 :                         for (i = 0; i<nb_written; i++) {
    1185       36864 :                                 s32 samp = (*out_mix);
    1186       36864 :                                 samp /= MIX_S16_SCALE;
    1187       36864 :                                 if (samp > GF_SHORT_MAX) samp = GF_SHORT_MAX;
    1188             :                                 else if (samp < GF_SHORT_MIN) samp = GF_SHORT_MIN;
    1189       36864 :                                 (*out_s16) = samp;
    1190       36864 :                                 out_s16 += 1;
    1191       36864 :                                 out_mix += am->nb_channels;
    1192             :                         }
    1193             :                 }
    1194          36 :         } else if (am->afmt == GF_AUDIO_FMT_U8) {
    1195             :                 u8 *out_u8 = (u8 *) buffer;
    1196       18432 :                 for (i=0; i<nb_written; i++) {
    1197       36864 :                         for (j=0; j<am->nb_channels; j++) {
    1198       36864 :                                 s32 samp = (*out_mix ) / MIX_U8_SCALE;
    1199       36864 :                                 if (samp > 127) samp = 127;
    1200             :                                 else if (samp < -128) samp = -128;
    1201       36864 :                                 samp += 128;
    1202       36864 :                                 (*out_u8) = (u8) samp;
    1203       36864 :                                 out_u8 += 1;
    1204       36864 :                                 out_mix += 1;
    1205             :                         }
    1206             :                 }
    1207          18 :         } else if (am->afmt == GF_AUDIO_FMT_U8P) {
    1208             :                 s8 *out_s8 = (s8 *) buffer;
    1209          36 :                 for (j=0; j<am->nb_channels; j++) {
    1210          36 :                         out_mix = am->output + j;
    1211       36900 :                         for (i=0; i<nb_written; i++) {
    1212       36864 :                                 s32 samp = (*out_mix ) / MIX_U8_SCALE;
    1213       36864 :                                 if (samp > 127) samp = 127;
    1214             :                                 else if (samp < -128) samp = -128;
    1215       36864 :                                 samp += 128;
    1216       36864 :                                 (*out_s8) = samp;
    1217       36864 :                                 out_s8 += 1;
    1218       36864 :                                 out_mix += am->nb_channels;
    1219             :                         }
    1220             :                 }
    1221             :         }
    1222             : 
    1223        7991 :         nb_written *= am->nb_channels * am->bit_depth / 8;
    1224             : 
    1225        7991 :         gf_mixer_lock(am, GF_FALSE);
    1226        7991 :         return nb_written;
    1227             : }
    1228             : 
    1229             : 

Generated by: LCOV version 1.13