Bug 1502488 - Fix opus mapping 2 channels count check. r=padenot
authorJean-Yves Avenard <jyavenard@mozilla.com>
Mon, 29 Oct 2018 09:44:18 +0000
changeset 443306 4a85f19e21f4a4a437d4c10c1784fdcbe8788686
parent 443305 deb0260b33c1b57a0a98c409d2f839a74596985a
child 443307 a78e285cc06f6b98cbe0f2d090871c00f68823b5
push id71881
push userjyavenard@mozilla.com
push dateMon, 29 Oct 2018 09:57:18 +0000
treeherderautoland@4a85f19e21f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1502488
milestone65.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 1502488 - Fix opus mapping 2 channels count check. r=padenot Add gtest Differential Revision: https://phabricator.services.mozilla.com/D9943
dom/media/gtest/TestOpusParser.cpp
dom/media/gtest/moz.build
dom/media/ogg/OpusParser.cpp
dom/media/ogg/OpusParser.h
new file mode 100644
--- /dev/null
+++ b/dom/media/gtest/TestOpusParser.cpp
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "gtest/gtest.h"
+#include "OpusParser.h"
+#include <algorithm>
+
+TEST(OpusParser, Mapping2)
+{
+  uint8_t validChannels[] = {
+    1,  3,  4,  6,   9,   11,  16,  18,  25,  27,  36,  38,  49,  51,  64,
+    66, 81, 83, 100, 102, 121, 123, 144, 146, 169, 171, 196, 198, 225, 227
+  };
+  for (uint8_t channels = 0; channels < 255; channels++) {
+    bool found = OpusParser::IsValidMapping2ChannelsCount(channels);
+    bool foundTable =
+      std::find(std::begin(validChannels), std::end(validChannels), channels) !=
+      std::end(validChannels);
+    EXPECT_EQ(found, foundTable);
+  }
+}
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -28,16 +28,17 @@ UNIFIED_SOURCES += [
     'TestGMPRemoveAndDelete.cpp',
     'TestGMPUtils.cpp',
     'TestIntervalSet.cpp',
     'TestMediaDataDecoder.cpp',
     'TestMediaEventSource.cpp',
     'TestMediaMIMETypes.cpp',
     'TestMP3Demuxer.cpp',
     'TestMP4Demuxer.cpp',
+    'TestOpusParser.cpp',
     'TestRust.cpp',
     'TestVideoSegment.cpp',
     'TestVideoUtils.cpp',
     'TestVPXDecoding.cpp',
     'TestWebMBuffered.cpp',
 ]
 
 if CONFIG['MOZ_WEBM_ENCODER']:
--- a/dom/media/ogg/OpusParser.cpp
+++ b/dom/media/ogg/OpusParser.cpp
@@ -88,37 +88,19 @@ bool OpusParser::DecodeHeader(unsigned c
       if (mChannelMapping == 1 && mChannels > 8) {
         OPUS_LOG(LogLevel::Debug,
                  ("Invalid Opus file: too many channels (%d) for"
                   " mapping family 1.",
                   mChannels));
         return false;
       }
       if (mChannelMapping == 2) {
-        // https://tools.ietf.org/html/draft-ietf-codec-ambisonics-08#page-3
-        // For both channel mapping family 2 and family 3, the allowed numbers
-        // of channels: (1 + n)^2 + 2j for n = 0, 1, ..., 14 and j = 0 or 1,
-        // where n denotes the (highest) ambisonic order and j denotes whether
-        // or not there is a separate non-diegetic stereo stream Explicitly the
-        // allowed number of channels are 1, 3, 4, 6, 9, 11, 16, 18, 25, 27, 36,
-        // 38, 49, 51, 64, 66, 81, 83, 100, 102, 121, 123, 144, 146, 169, 171,
-        // 196, 198, 225, and 227.
-
-        // We use the property that int(sqrt(n)) == int(sqrt(n+2)) for n != 3
-        // which is handled by the test n^2 + 2 != channel
-        double val = sqrt(mChannels);
-        if (val == 0 || val > 15) {
+        if (!IsValidMapping2ChannelsCount(mChannels)) {
           return false;
         }
-        if (val != int32_t(val)) {
-          if (val * val + 2 != mChannels) {
-            // Not a valid channel count.
-            return false;
-          }
-        }
       }
       if (aLength > static_cast<unsigned>(20 + mChannels)) {
         mStreams = aData[19];
         mCoupledStreams = aData[20];
         int i;
         for (i = 0; i < mChannels; i++) {
           mMappingTable[i] = aData[21 + i];
         }
@@ -210,9 +192,31 @@ bool OpusParser::DecodeTags(unsigned cha
   OPUS_LOG(LogLevel::Debug, ("  vendor: %s", mVendorString.get()));
   for (uint32_t i = 0; i < mTags.Length(); i++) {
     OPUS_LOG(LogLevel::Debug, (" %s", mTags[i].get()));
   }
 #endif
   return true;
 }
 
+/* static */ bool
+OpusParser::IsValidMapping2ChannelsCount(uint8_t aChannels)
+{
+  // https://tools.ietf.org/html/draft-ietf-codec-ambisonics-08#page-4
+  // For both channel mapping family 2 and family 3, the allowed numbers
+  // of channels: (1 + n)^2 + 2j for n = 0, 1, ..., 14 and j = 0 or 1,
+  // where n denotes the (highest) ambisonic order and j denotes whether
+  // or not there is a separate non-diegetic stereo stream Explicitly the
+  // allowed number of channels are 1, 3, 4, 6, 9, 11, 16, 18, 25, 27, 36,
+  // 38, 49, 51, 64, 66, 81, 83, 100, 102, 121, 123, 144, 146, 169, 171,
+  // 196, 198, 225, and 227.
+
+  // We use the property that int(sqrt(n)) == int(sqrt(n+2)) for n != 3
+  // which is handled by the test n^2 + 2 != channel
+  if (aChannels < 1 || aChannels > 227) {
+    return false;
+  }
+  double val = sqrt(aChannels);
+  int32_t valInt = int32_t(val);
+  return val == valInt || valInt * valInt + 2 == aChannels;
+}
+
 } // namespace mozilla
--- a/dom/media/ogg/OpusParser.h
+++ b/dom/media/ogg/OpusParser.h
@@ -13,16 +13,17 @@ namespace mozilla {
 
 class OpusParser
 {
 public:
   OpusParser();
 
   bool DecodeHeader(unsigned char* aData, size_t aLength);
   bool DecodeTags(unsigned char* aData, size_t aLength);
+  static bool IsValidMapping2ChannelsCount(uint8_t aChannels);
 
   // Various fields from the Ogg Opus header.
   int mRate;        // Sample rate the decoder uses (always 48 kHz).
   uint32_t mNominalRate; // Original sample rate of the data (informational).
   int mChannels;    // Number of channels the stream encodes.
   uint16_t mPreSkip; // Number of samples to strip after decoder reset.
 #ifdef MOZ_SAMPLE_TYPE_FLOAT32
   float mGain;      // Gain to apply to decoder output.