Bug 951770 - Reject invalid Opus pre-skip in WebM. r=doublec, a=sledru
authorRalph Giles <giles@mozilla.com>
Sun, 02 Feb 2014 19:39:00 -0800
changeset 176947 dd51a2464396d1de5c730cb810456d52f5b08c8c
parent 176946 4e675e7857d82e7e2eb03c627dcca5c971426beb
child 176948 c90044c11e4e43b58577074c90d881dcd5534baf
push id5214
push userryanvm@gmail.com
push dateMon, 10 Feb 2014 17:18:35 +0000
treeherdermozilla-aurora@dd3253032193 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec, sledru
bugs951770
milestone29.0a2
Bug 951770 - Reject invalid Opus pre-skip in WebM. r=doublec, a=sledru The 'pre-skip' value representing encoder delay in the Opus format is recorded once in the .opus representation, but for WebM it's in the file both in the CodecDelay element and in the CodecPrivate data. We now reject files where these two fields don't match. Our detodos.webm file was exactly this sort of mismatched file. It has been renamed and added to the invalid file list to verify we now reject it. A new detodos.webm replaces it, remuxed from detodos.opus with a bugfixed mkvmerge. Based on a patch by Jan Gerber.
content/media/test/detodos.webm
content/media/test/invalid-preskip.webm
content/media/test/manifest.js
content/media/test/mochitest.ini
content/media/webm/WebMReader.cpp
content/media/webm/WebMReader.h
index 99b4f2ca71707b499ad1297f97448d27d29c5750..39cfa7f537aa168155dd8d2f51f3ef06aabacb02
GIT binary patch
literal 11701
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
b;WX3-Fg#>(eF(03cyr9(A#l$D9Pj8qY(S-g
copy from content/media/test/detodos.webm
copy to content/media/test/invalid-preskip.webm
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -228,16 +228,17 @@ var gInvalidTests = [
   { name:"invalid-m1c0.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-m1c9.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-m2c0.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-m2c1.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-cmap-short.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-cmap-s0c0.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-cmap-s0c2.opus", type:"audio/ogg; codecs=opus"},
   { name:"invalid-cmap-s1c2.opus", type:"audio/ogg; codecs=opus"},
+  { name:"invalid-preskip.webm", type:"audio/webm; codecs=opus"},
 ];
 
 // Converts a path/filename to a file:// URI which we can load from disk.
 // Optionally checks whether the file actually exists on disk at the location
 // we've specified.
 function fileUriToSrc(path, mustExist) {
   // android mochitest doesn't support file://
   if (navigator.appVersion.indexOf("Android") != -1 || SpecialPowers.Services.appinfo.name == "B2G")
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -105,16 +105,17 @@ support-files =
   invalid-cmap-s1c2.opus
   invalid-cmap-short.opus
   invalid-m0c0.opus
   invalid-m0c3.opus
   invalid-m1c0.opus
   invalid-m1c9.opus
   invalid-m2c0.opus
   invalid-m2c1.opus
+  invalid-preskip.webm
   long.vtt
   manifest.js
   multiple-bos.ogg
   no-cues.webm
   noContentLength.sjs
   notags.mp3
   owl-funnier-id3.mp3
   owl-funny-id3.mp3
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -367,17 +367,17 @@ nsresult WebMReader::ReadMetadata(MediaI
         Cleanup();
         return NS_ERROR_FAILURE;
       }
 
       mAudioTrack = track;
       mHasAudio = true;
       mInfo.mAudio.mHasAudio = true;
       mAudioCodec = nestegg_track_codec_id(mContext, track);
-      mCodecDelay = params.codec_delay;
+      mCodecDelay = params.codec_delay / NS_PER_USEC;
 
       if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
         // Get the Vorbis header data
         unsigned int nheaders = 0;
         r = nestegg_track_codec_data_count(mContext, track, &nheaders);
         if (r == -1 || nheaders != 3) {
           Cleanup();
           return NS_ERROR_FAILURE;
@@ -434,16 +434,23 @@ nsresult WebMReader::ReadMetadata(MediaI
           return NS_ERROR_FAILURE;
         }
 
         if (!InitOpusDecoder()) {
           Cleanup();
           return NS_ERROR_FAILURE;
         }
 
+        if (static_cast<int64_t>(mCodecDelay) != FramesToUsecs(mOpusParser->mPreSkip, mOpusParser->mRate).value()) {
+          LOG(PR_LOG_WARNING,
+              ("Invalid Opus header: CodecDelay and pre-skip do not match!\n"));
+          Cleanup();
+          return NS_ERROR_FAILURE;
+        }
+
         mInfo.mAudio.mRate = mOpusParser->mRate;
 
         mInfo.mAudio.mChannels = mOpusParser->mChannels;
         mChannels = mInfo.mAudio.mChannels;
         mSeekPreroll = params.seek_preroll;
 #endif
       } else {
         Cleanup();
@@ -713,17 +720,17 @@ bool WebMReader::DecodeAudioPacket(neste
         return false;
       }
 
       CheckedInt64 duration = FramesToUsecs(frames, rate);
       if (!duration.isValid()) {
         NS_WARNING("Int overflow converting WebM audio duration");
         return false;
       }
-      CheckedInt64 time = startTime - (mCodecDelay / NS_PER_USEC);
+      CheckedInt64 time = startTime - mCodecDelay;
       if (!time.isValid()) {
         NS_WARNING("Int overflow shifting tstamp by codec delay");
         nestegg_free_packet(aPacket);
         return false;
       };
       AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
                                      time.value(),
                                      duration.value(),
--- a/content/media/webm/WebMReader.h
+++ b/content/media/webm/WebMReader.h
@@ -210,17 +210,17 @@ private:
   uint32_t mAudioTrack;
 
   // Time in microseconds of the start of the first audio frame we've decoded.
   int64_t mAudioStartUsec;
 
   // Number of audio frames we've decoded since decoding began at mAudioStartMs.
   uint64_t mAudioFrames;
 
-  // Number of nanoseconds that must be discarded from the start of the Stream.
+  // Number of microseconds that must be discarded from the start of the Stream.
   uint64_t mCodecDelay;
 
   // Parser state and computed offset-time mappings.  Shared by multiple
   // readers when decoder has been cloned.  Main thread only.
   nsRefPtr<WebMBufferedState> mBufferedState;
 
   // Size of the frame initially present in the stream. The picture region
   // is defined as a ratio relative to this.