+ // We require signed 16-bit ints for the output format. If
+ // we got something different convert it.
+ if ( context->sample_fmt != SAMPLE_FMT_S16 )
+ {
+ // Note: av_audio_convert seems to be a work-in-progress but
+ // looks like it will eventually handle general audio
+ // mixdowns which would allow us much more flexibility
+ // in handling multichannel audio in HB. If we were doing
+ // anything more complicated than a one-for-one format
+ // conversion we'd probably want to cache the converter
+ // context in the pv.
+ int isamp = av_get_bits_per_sample_format( context->sample_fmt ) / 8;
+ AVAudioConvert *ctx = av_audio_convert_alloc( SAMPLE_FMT_S16, 1,
+ context->sample_fmt, 1,
+ NULL, 0 );
+ // get output buffer size (in 2-byte samples) then malloc a buffer
+ nsamples = out_size / isamp;
+ buffer = av_malloc( nsamples * 2 );
+
+ // we're doing straight sample format conversion which behaves as if
+ // there were only one channel.
+ const void * const ibuf[6] = { pv->buffer };
+ void * const obuf[6] = { buffer };
+ const int istride[6] = { isamp };
+ const int ostride[6] = { 2 };
+
+ av_audio_convert( ctx, obuf, ostride, ibuf, istride, nsamples );
+ av_audio_convert_free( ctx );
+ }
+ else
+ {
+ nsamples = out_size / 2;
+ }
+
+ hb_buffer_t * buf;
+
+ if ( pv->downmix )
+ {
+ pv->downmix_buffer = realloc(pv->downmix_buffer, nsamples * sizeof(hb_sample_t));
+
+ int i;
+ for( i = 0; i < nsamples; ++i )
+ {
+ pv->downmix_buffer[i] = buffer[i];
+ }
+
+ int n_ch_samples = nsamples / context->channels;
+ int channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
+
+ buf = hb_buffer_init( n_ch_samples * channels * sizeof(float) );
+ hb_sample_t *samples = (hb_sample_t *)buf->data;
+ hb_downmix(pv->downmix, samples, pv->downmix_buffer, n_ch_samples);
+ }
+ else
+ {
+ buf = hb_buffer_init( nsamples * sizeof(float) );
+ float *fl32 = (float *)buf->data;
+ int i;
+ for( i = 0; i < nsamples; ++i )
+ {
+ fl32[i] = buffer[i];
+ }
+ int n_ch_samples = nsamples / context->channels;
+ hb_layout_remap( &hb_smpte_chan_map, &hb_qt_chan_map,
+ audio->config.in.channel_layout,
+ fl32, n_ch_samples );
+ }