Bug 1295886 - P7. Add support for S16 decoded output. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 01 Nov 2017 11:33:06 +0100
changeset 692018 f8aaecf06a6928dda8186d068c2a2eb74828cce4
parent 692017 a86688ec70dfff3ea190cd24c38b89bd856ccab6
child 692019 9c46a698fccf2ee25579eaa54b67b1c1006084e2
push id87364
push userbmo:jyavenard@mozilla.com
push dateThu, 02 Nov 2017 09:52:27 +0000
reviewersgerald
bugs1295886
milestone58.0a1
Bug 1295886 - P7. Add support for S16 decoded output. r?gerald Android audio backend only supports S16 audio sample, so configure ffmpeg audio decoder to output 16 bits audio by default. Adding format conversions as necessary. MozReview-Commit-ID: J6N4rbMZ3Ug
dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
--- a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
@@ -43,30 +43,90 @@ FFmpegAudioDecoder<LIBAV_VER>::InitCodec
   MOZ_ASSERT(mCodecContext);
   // We do not want to set this value to 0 as FFmpeg by default will
   // use the number of cores, which with our mozlibavutil get_cpu_count
   // isn't implemented.
   mCodecContext->thread_count = 1;
   // FFmpeg takes this as a suggestion for what format to use for audio samples.
   // LibAV 0.8 produces rubbish float interleaved samples, request 16 bits
   // audio.
+#ifdef MOZ_SAMPLE_TYPE_S16
+  mCodecContext->request_sample_fmt = AV_SAMPLE_FMT_S16;
+#else
   mCodecContext->request_sample_fmt =
     (mLib->mVersion == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
+#endif
 }
 
 static AlignedAudioBuffer
 CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames)
 {
   MOZ_ASSERT(aNumChannels <= MAX_CHANNELS);
 
   AlignedAudioBuffer audio(aNumChannels * aNumAFrames);
   if (!audio) {
     return audio;
   }
 
+#ifdef MOZ_SAMPLE_TYPE_S16
+  if (aFrame->format == AV_SAMPLE_FMT_FLT) {
+    // Audio data already packed. Need to convert from 32 bits Float to S16
+    AudioDataValue* tmp = audio.get();
+    float* data = reinterpret_cast<float**>(aFrame->data)[0];
+    for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
+      for (uint32_t channel = 0; channel < aNumChannels; channel++) {
+        *tmp++ = FloatToAudioSample<int16_t>(*data++);
+      }
+    }
+  } else if (aFrame->format == AV_SAMPLE_FMT_FLTP) {
+    // Planar audio data. Convert it from 32 bits float to S16
+    // and pack it into something we can understand.
+    AudioDataValue* tmp = audio.get();
+    float** data = reinterpret_cast<float**>(aFrame->data);
+    for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
+      for (uint32_t channel = 0; channel < aNumChannels; channel++) {
+        *tmp++ = FloatToAudioSample<int16_t>(data[channel][frame]);
+      }
+    }
+  } else if (aFrame->format == AV_SAMPLE_FMT_S16) {
+    // Audio data already packed. No need to do anything other than copy it
+    // into a buffer we own.
+    memcpy(audio.get(),
+           aFrame->data[0],
+           aNumChannels * aNumAFrames * sizeof(AudioDataValue));
+  } else if (aFrame->format == AV_SAMPLE_FMT_S16P) {
+    // Planar audio data. Pack it into something we can understand.
+    AudioDataValue* tmp = audio.get();
+    AudioDataValue** data = reinterpret_cast<AudioDataValue**>(aFrame->data);
+    for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
+      for (uint32_t channel = 0; channel < aNumChannels; channel++) {
+        *tmp++ = data[channel][frame];
+      }
+    }
+  } else if (aFrame->format == AV_SAMPLE_FMT_S32) {
+    // Audio data already packed. Need to convert from S32 to S16
+    AudioDataValue* tmp = audio.get();
+    int32_t* data = reinterpret_cast<int32_t**>(aFrame->data)[0];
+    for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
+      for (uint32_t channel = 0; channel < aNumChannels; channel++) {
+        *tmp++ = *data++ / (1U<<16);
+      }
+    }
+  } else if (aFrame->format == AV_SAMPLE_FMT_S32P) {
+    // Planar audio data. Convert it from S32 to S16
+    // and pack it into something we can understand.
+    AudioDataValue* tmp = audio.get();
+    int32_t** data = reinterpret_cast<int32_t**>(aFrame->data);
+    for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
+      for (uint32_t channel = 0; channel < aNumChannels; channel++) {
+        *tmp++ = data[channel][frame] / (1U<<16);
+      }
+    }
+  }
+#else
   if (aFrame->format == AV_SAMPLE_FMT_FLT) {
     // Audio data already packed. No need to do anything other than copy it
     // into a buffer we own.
     memcpy(audio.get(), aFrame->data[0],
            aNumChannels * aNumAFrames * sizeof(AudioDataValue));
   } else if (aFrame->format == AV_SAMPLE_FMT_FLTP) {
     // Planar audio data. Pack it into something we can understand.
     AudioDataValue* tmp = audio.get();
@@ -110,16 +170,17 @@ CopyAndPackAudio(AVFrame* aFrame, uint32
     AudioDataValue* tmp = audio.get();
     int32_t** data = reinterpret_cast<int32_t**>(aFrame->data);
     for (uint32_t frame = 0; frame < aNumAFrames; frame++) {
       for (uint32_t channel = 0; channel < aNumChannels; channel++) {
         *tmp++ = AudioSampleToFloat(data[channel][frame]);
       }
     }
   }
+#endif
 
   return audio;
 }
 
 MediaResult
 FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
                                         uint8_t* aData,
                                         int aSize,