Bug 1097849 - Enforce sane audio sample rates in MediaEncoder. r=derf
authorRalph Giles <giles@mozilla.com>
Wed, 12 Nov 2014 11:03:00 -0800
changeset 239777 4f9e282d1adbe59d69c5513d5d4a3cd09628a1c9
parent 239776 4819ef5bb24531ac1179fd5ef8d0ba72836cb57b
child 239778 a095f2eaec4d837ce6471ab0404cea8c405c5398
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersderf
bugs1097849
milestone36.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 1097849 - Enforce sane audio sample rates in MediaEncoder. r=derf We believe the rate is constrained by the audio driver in practice, but want to verify this assumption. The valid range 8-192 kHz covers all sample rates in general use for audio data. Note we must use an error return instead of an assertion since these bounds are verified by unit tests, which do not catch MOZ_ASSERT().
dom/media/encoder/OpusTrackEncoder.cpp
dom/media/encoder/VorbisTrackEncoder.cpp
dom/media/gtest/TestTrackEncoder.cpp
dom/media/gtest/TestVorbisTrackEncoder.cpp
--- a/dom/media/encoder/OpusTrackEncoder.cpp
+++ b/dom/media/encoder/OpusTrackEncoder.cpp
@@ -153,16 +153,20 @@ OpusTrackEncoder::Init(int aChannels, in
   NS_ENSURE_TRUE((aChannels <= MAX_SUPPORTED_AUDIO_CHANNELS) && (aChannels > 0),
                  NS_ERROR_FAILURE);
 
   // This version of encoder API only support 1 or 2 channels,
   // So set the mChannels less or equal 2 and
   // let InterleaveTrackData downmix pcm data.
   mChannels = aChannels > MAX_CHANNELS ? MAX_CHANNELS : aChannels;
 
+  // Reject non-audio sample rates.
+  NS_ENSURE_TRUE(aSamplingRate >= 8000, NS_ERROR_INVALID_ARG);
+  NS_ENSURE_TRUE(aSamplingRate <= 192000, NS_ERROR_INVALID_ARG);
+
   // According to www.opus-codec.org, creating an opus encoder requires the
   // sampling rate of source signal be one of 8000, 12000, 16000, 24000, or
   // 48000. If this constraint is not satisfied, we resample the input to 48kHz.
   nsTArray<int> supportedSamplingRates;
   supportedSamplingRates.AppendElements(kOpusSupportedInputSamplingRates,
                          ArrayLength(kOpusSupportedInputSamplingRates));
   if (!supportedSamplingRates.Contains(aSamplingRate)) {
     int error;
--- a/dom/media/encoder/VorbisTrackEncoder.cpp
+++ b/dom/media/encoder/VorbisTrackEncoder.cpp
@@ -44,20 +44,20 @@ VorbisTrackEncoder::~VorbisTrackEncoder(
     vorbis_dsp_clear(&mVorbisDsp);
     vorbis_info_clear(&mVorbisInfo);
   }
 }
 
 nsresult
 VorbisTrackEncoder::Init(int aChannels, int aSamplingRate)
 {
-  if (aChannels <= 0 || aChannels > 8) {
-    VORBISLOG("aChannels <= 0 || aChannels > 8");
-    return NS_ERROR_INVALID_ARG;
-  }
+  NS_ENSURE_TRUE(aChannels > 0, NS_ERROR_INVALID_ARG);
+  NS_ENSURE_TRUE(aChannels <= 8, NS_ERROR_INVALID_ARG);
+  NS_ENSURE_TRUE(aSamplingRate >= 8000, NS_ERROR_INVALID_ARG);
+  NS_ENSURE_TRUE(aSamplingRate <= 192000, NS_ERROR_INVALID_ARG);
 
   // This monitor is used to wake up other methods that are waiting for encoder
   // to be completely initialized.
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   mChannels = aChannels;
   mSamplingRate = aSamplingRate;
 
   int ret = 0;
--- a/dom/media/gtest/TestTrackEncoder.cpp
+++ b/dom/media/gtest/TestTrackEncoder.cpp
@@ -61,16 +61,25 @@ TEST(Media, OpusEncoder_Init)
   // Should accept channels within valid range.
   for (int i = 1; i <= 8; i++) {
     EXPECT_TRUE(TestOpusInit(i, 16000));
   }
 
   // Expect false with 0 or negative sampling rate of input signal.
   EXPECT_FALSE(TestOpusInit(1, 0));
   EXPECT_FALSE(TestOpusInit(1, -1));
+
+  // Verify sample rate bounds checking.
+  EXPECT_FALSE(TestOpusInit(2, 2000));
+  EXPECT_FALSE(TestOpusInit(2, 4000));
+  EXPECT_FALSE(TestOpusInit(2, 7999));
+  EXPECT_TRUE(TestOpusInit(2, 8000));
+  EXPECT_TRUE(TestOpusInit(2, 192000));
+  EXPECT_FALSE(TestOpusInit(2, 192001));
+  EXPECT_FALSE(TestOpusInit(2, 200000));
 }
 
 TEST(Media, OpusEncoder_Resample)
 {
   // Sampling rates of data to be fed to Opus encoder, should remain unchanged
   // if it is one of Opus supported rates (8000, 12000, 16000, 24000 and 48000
   // (kHz)) at initialization.
   EXPECT_TRUE(TestOpusResampler(1, 8000) == 8000);
--- a/dom/media/gtest/TestVorbisTrackEncoder.cpp
+++ b/dom/media/gtest/TestVorbisTrackEncoder.cpp
@@ -125,24 +125,29 @@ TEST(VorbisTrackEncoder, Init)
   // Expect false with 0 or negative channels of input signal.
   EXPECT_FALSE(TestVorbisInit(0, 16000));
   EXPECT_FALSE(TestVorbisInit(-1, 16000));
   EXPECT_FALSE(TestVorbisInit(8 + 1, 16000));
 
   // Sample rate and channel range test.
   for (int i = 1; i <= 8; i++) {
     EXPECT_FALSE(TestVorbisInit(i, -1));
+    EXPECT_FALSE(TestVorbisInit(i, 2000));
+    EXPECT_FALSE(TestVorbisInit(i, 4000));
+    EXPECT_FALSE(TestVorbisInit(i, 7999));
     EXPECT_TRUE(TestVorbisInit(i, 8000));
     EXPECT_TRUE(TestVorbisInit(i, 11000));
     EXPECT_TRUE(TestVorbisInit(i, 16000));
     EXPECT_TRUE(TestVorbisInit(i, 22050));
     EXPECT_TRUE(TestVorbisInit(i, 32000));
     EXPECT_TRUE(TestVorbisInit(i, 44100));
     EXPECT_TRUE(TestVorbisInit(i, 48000));
     EXPECT_TRUE(TestVorbisInit(i, 96000));
+    EXPECT_TRUE(TestVorbisInit(i, 192000));
+    EXPECT_FALSE(TestVorbisInit(i, 192001));
     EXPECT_FALSE(TestVorbisInit(i, 200000 + 1));
   }
 }
 
 // Test metadata
 TEST(VorbisTrackEncoder, Metadata)
 {
   // Initiate vorbis encoder.