summaryrefslogtreecommitdiff
path: root/src/lib/ffmpeg_decoder.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-11-07 13:57:57 +0000
committerCarl Hetherington <cth@carlh.net>2012-11-07 13:57:57 +0000
commitf89ef49deefe91e2b1972b54ee07bfc22a22f303 (patch)
treea786f6141ce48811a355d24c1da00a09f985d6b3 /src/lib/ffmpeg_decoder.cc
parent563de0fe1f15ca087abe45c2d259b02fcc5c0f81 (diff)
Move deinterleaving of audio into ffmpeg decoder.
Diffstat (limited to 'src/lib/ffmpeg_decoder.cc')
-rw-r--r--src/lib/ffmpeg_decoder.cc81
1 files changed, 70 insertions, 11 deletions
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<AudioBuffers> 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<AudioBuffers>
+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<AudioBuffers> 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<float*> (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
{