Bug 1248861: P10. Ensure opus decoder channel layout is always in SMPTE order. r=rillian
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 05 Apr 2016 23:35:31 +1000
changeset 330582 3e1ffa75a042d7cab3d00a472e6811df216ee152
parent 330581 cce16017b59d6edbc0b080cba59b9f12526880be
child 330583 a15ba02878040db7fd4332fa81f66bdbac0a30c0
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrillian
bugs1248861
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1248861: P10. Ensure opus decoder channel layout is always in SMPTE order. r=rillian MozReview-Commit-ID: BDZ25pXJQWa
dom/media/platforms/agnostic/OpusDecoder.cpp
dom/media/platforms/agnostic/OpusDecoder.h
--- a/dom/media/platforms/agnostic/OpusDecoder.cpp
+++ b/dom/media/platforms/agnostic/OpusDecoder.cpp
@@ -2,17 +2,19 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "OpusDecoder.h"
 #include "TimeUnits.h"
 #include "VorbisUtils.h"
+#include "VorbisDecoder.h" // For VorbisLayout
 #include "mozilla/Endian.h"
+#include "mozilla/PodOperations.h"
 
 #include <stdint.h>
 #include <inttypes.h>  // For PRId64
 
 extern mozilla::LogModule* GetPDMLog();
 #define OPUS_DEBUG(arg, ...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, \
     ("OpusDataDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
@@ -61,17 +63,17 @@ OpusDataDecoder::Init()
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   int r;
   mOpusDecoder = opus_multistream_decoder_create(mOpusParser->mRate,
                                                  mOpusParser->mChannels,
                                                  mOpusParser->mStreams,
                                                  mOpusParser->mCoupledStreams,
-                                                 mOpusParser->mMappingTable,
+                                                 mMappingTable,
                                                  &r);
   mSkip = mOpusParser->mPreSkip;
   mPaddingDiscarded = false;
 
   if (codecDelay != FramesToUsecs(mOpusParser->mPreSkip,
                                   mOpusParser->mRate).value()) {
     NS_WARNING("Invalid Opus header: CodecDelay and pre-skip do not match!");
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
@@ -95,23 +97,40 @@ OpusDataDecoder::DecodeHeader(const unsi
   MOZ_ASSERT(!mOpusDecoder);
   MOZ_ASSERT(!mDecodedHeader);
   mDecodedHeader = true;
 
   mOpusParser = new OpusParser;
   if (!mOpusParser->DecodeHeader(const_cast<unsigned char*>(aData), aLength)) {
     return NS_ERROR_FAILURE;
   }
+  int channels = mOpusParser->mChannels;
   // No channel mapping for more than 8 channels.
-  if (mOpusParser->mChannels > 8) {
+  if (channels > 8) {
     OPUS_DEBUG("No channel mapping for more than 8 channels. Source is %d channels",
-               mOpusParser->mChannels);
+               channels);
     return NS_ERROR_FAILURE;
   }
 
+  AudioConfig::ChannelLayout vorbisLayout(
+    channels, VorbisDataDecoder::VorbisLayout(channels));
+  AudioConfig::ChannelLayout smpteLayout(channels);
+  static_assert(sizeof(mOpusParser->mMappingTable) / sizeof(mOpusParser->mMappingTable[0]) >= MAX_AUDIO_CHANNELS,
+                       "Invalid size set");
+  uint8_t map[sizeof(mOpusParser->mMappingTable) / sizeof(mOpusParser->mMappingTable[0])];
+  if (vorbisLayout.MappingTable(smpteLayout, map)) {
+    for (int i = 0; i < channels; i++) {
+      mMappingTable[i] = mOpusParser->mMappingTable[map[i]];
+    }
+  } else {
+    // Should never get here as vorbis layout is always convertible to SMPTE
+    // default layout.
+    PodCopy(mMappingTable, mOpusParser->mMappingTable, MAX_AUDIO_CHANNELS);
+  }
+
   return NS_OK;
 }
 
 nsresult
 OpusDataDecoder::Input(MediaRawData* aSample)
 {
   nsCOMPtr<nsIRunnable> runnable(
     NS_NewRunnableMethodWithArg<RefPtr<MediaRawData>>(
--- a/dom/media/platforms/agnostic/OpusDecoder.h
+++ b/dom/media/platforms/agnostic/OpusDecoder.h
@@ -54,12 +54,13 @@ private:
   bool mDecodedHeader;
 
   // Opus padding should only be discarded on the final packet.  Once this
   // is set to true, if the reader attempts to decode any further packets it
   // will raise an error so we can indicate that the file is invalid.
   bool mPaddingDiscarded;
   int64_t mFrames;
   Maybe<int64_t> mLastFrameTime;
+  uint8_t mMappingTable[MAX_AUDIO_CHANNELS]; // Channel mapping table.
 };
 
 } // namespace mozilla
 #endif