From: Carl Hetherington Date: Wed, 7 Nov 2012 13:57:57 +0000 (+0000) Subject: Move deinterleaving of audio into ffmpeg decoder. X-Git-Tag: v2.0.48~1549 X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=f89ef49deefe91e2b1972b54ee07bfc22a22f303;p=dcpomatic.git Move deinterleaving of audio into ffmpeg decoder. --- diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index c9d8f063a..09788cd0c 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -154,77 +154,13 @@ Decoder::go () * @param size Number of bytes of data. */ void -Decoder::process_audio (uint8_t* data, int size) +Decoder::process_audio (shared_ptr audio) { - /* XXX: could this be removed? */ - if (size == 0) { - return; - } - - assert (_film->audio_channels()); - assert (bytes_per_audio_sample()); - - /* Deinterleave and convert to float */ - - assert ((size % (bytes_per_audio_sample() * audio_channels())) == 0); - - int const total_samples = size / bytes_per_audio_sample(); - int const frames = total_samples / _film->audio_channels(); - shared_ptr audio (new AudioBuffers (audio_channels(), frames)); - - switch (audio_sample_format()) { - case AV_SAMPLE_FMT_S16: - { - int16_t* p = (int16_t *) data; - int sample = 0; - int channel = 0; - for (int i = 0; i < total_samples; ++i) { - audio->data(channel)[sample] = float(*p++) / (1 << 15); - - ++channel; - if (channel == _film->audio_channels()) { - channel = 0; - ++sample; - } - } - } - break; - - case AV_SAMPLE_FMT_S32: - { - int32_t* p = (int32_t *) data; - int sample = 0; - int channel = 0; - for (int i = 0; i < total_samples; ++i) { - audio->data(channel)[sample] = float(*p++) / (1 << 31); - - ++channel; - if (channel == _film->audio_channels()) { - channel = 0; - ++sample; - } - } - } - - case AV_SAMPLE_FMT_FLTP: - { - float* p = reinterpret_cast (data); - for (int i = 0; i < _film->audio_channels(); ++i) { - memcpy (audio->data(i), p, frames * sizeof(float)); - p += frames; - } - } - break; - - default: - assert (false); - } - /* Maybe apply gain */ if (_film->audio_gain() != 0) { float const linear_gain = pow (10, _film->audio_gain() / 20); - for (int i = 0; i < _film->audio_channels(); ++i) { - for (int j = 0; j < frames; ++j) { + for (int i = 0; i < audio->channels(); ++i) { + for (int j = 0; j < audio->frames(); ++j) { audio->data(i)[j] *= linear_gain; } } diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 9f47bf425..30b7dd41f 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -107,7 +107,7 @@ protected: virtual PixelFormat pixel_format () const = 0; void process_video (AVFrame *); - void process_audio (uint8_t *, int); + void process_audio (boost::shared_ptr); void process_subtitle (boost::shared_ptr); void repeat_last_video (); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index a2ca739e2..e765d296a 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -250,7 +250,7 @@ FFmpegDecoder::pass () ); assert (_audio_codec_context->channels == _film->audio_channels()); - process_audio (_frame->data[0], data_size); + process_audio (deinterleave_audio (_frame->data[0], data_size)); } } @@ -341,15 +341,9 @@ FFmpegDecoder::pass () ); if (s) { - /* hence bytes */ - int const b = s * audio_channels() * bytes_per_audio_sample(); - - /* XXX: this assumes that it won't be too much, and there are shaky assumptions - that all sound representations are silent with memset()ed zero data. - */ - uint8_t silence[b]; - memset (silence, 0, b); - process_audio (silence, b); + shared_ptr audio (new AudioBuffers (audio_channels(), s)); + audio->make_silent (); + process_audio (audio); } } @@ -358,7 +352,7 @@ FFmpegDecoder::pass () ); assert (_audio_codec_context->channels == _film->audio_channels()); - process_audio (_frame->data[0], data_size); + process_audio (deinterleave_audio (_frame->data[0], data_size)); } } @@ -383,6 +377,71 @@ FFmpegDecoder::pass () return false; } +shared_ptr +FFmpegDecoder::deinterleave_audio (uint8_t* data, int size) +{ + assert (_film->audio_channels()); + assert (bytes_per_audio_sample()); + + /* Deinterleave and convert to float */ + + assert ((size % (bytes_per_audio_sample() * audio_channels())) == 0); + + int const total_samples = size / bytes_per_audio_sample(); + int const frames = total_samples / _film->audio_channels(); + shared_ptr audio (new AudioBuffers (audio_channels(), frames)); + + switch (audio_sample_format()) { + case AV_SAMPLE_FMT_S16: + { + int16_t* p = (int16_t *) data; + int sample = 0; + int channel = 0; + for (int i = 0; i < total_samples; ++i) { + audio->data(channel)[sample] = float(*p++) / (1 << 15); + + ++channel; + if (channel == _film->audio_channels()) { + channel = 0; + ++sample; + } + } + } + break; + + case AV_SAMPLE_FMT_S32: + { + int32_t* p = (int32_t *) data; + int sample = 0; + int channel = 0; + for (int i = 0; i < total_samples; ++i) { + audio->data(channel)[sample] = float(*p++) / (1 << 31); + + ++channel; + if (channel == _film->audio_channels()) { + channel = 0; + ++sample; + } + } + } + + case AV_SAMPLE_FMT_FLTP: + { + float* p = reinterpret_cast (data); + for (int i = 0; i < _film->audio_channels(); ++i) { + memcpy (audio->data(i), p, frames * sizeof(float)); + p += frames; + } + } + break; + + default: + assert (false); + } + + return audio; +} + float FFmpegDecoder::frames_per_second () const { diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 0265f7478..5d278ea0d 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -82,6 +82,7 @@ private: void setup_subtitle (); void maybe_add_subtitle (); + boost::shared_ptr deinterleave_audio (uint8_t* data, int size); std::string stream_name (AVStream* s) const;