Bug 757600 - Update the Opus version field parser. r=cpearce
authorRalph Giles <giles@mozilla.com>
Tue, 22 May 2012 20:21:46 -0400
changeset 94650 f93a650e8a8cc243f1fe2739d10f007b90df2c8d
parent 94649 5814957f9225a36b9b47011ae870643cd43c5de8
child 94651 99878dcae029c1ef815b0246a2719476ea2f4bde
push id22732
push useremorley@mozilla.com
push dateWed, 23 May 2012 09:43:13 +0000
treeherdermozilla-central@aa2b52bd0374 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs757600
milestone15.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 757600 - Update the Opus version field parser. r=cpearce On 2012 May 10, the Ogg encapsulation spec for Opus at https://wiki.xiph.org/OggOpus bumped the version number from zero to one. The one-byte field is also now notionally split into major and minor subfields, with incompatible changes signalled by the major field. We update nsOpusState::DecodeHeader to parse the version field separately from the stream identification and reject any stream where the high four bits of the version field is non-zero. The opus-tools repo was updated 2012 May 22 to set with version = 1. This commit enables playback of those files.
content/media/ogg/nsOggCodecState.cpp
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -813,24 +813,32 @@ bool nsOpusState::DecodeHeader(ogg_packe
   // Try parsing as the metadata header.
   if (!memcmp(aPacket->packet, "OpusTags", 8)) {
     mDoneReadingHeaders = true; // This is the last Opus header.
     mActive = true;
     return true;
   }
 
   // Otherwise, parse as the id header.
-  if (aPacket->bytes < 19 || memcmp(aPacket->packet, "OpusHead\0", 9)) {
+  if (aPacket->bytes < 19 || memcmp(aPacket->packet, "OpusHead", 8)) {
     LOG(PR_LOG_DEBUG, ("Invalid Opus file: unrecognized header"));
     mActive = false;
     return true;
   }
 
   mRate = 48000; // The Opus decoder runs at 48 kHz regardless.
 
+  int version = aPacket->packet[8];
+  // Accept file format versions 0.x.
+  if ((version & 0xf0) != 0) {
+    LOG(PR_LOG_DEBUG, ("Rejecting unknown Opus file version %d", version));
+    mActive = false;
+    return true;
+  }
+
   mChannels= aPacket->packet[9];
   mPreSkip = LEUint16(aPacket->packet + 10);
   mNominalRate = LEUint32(aPacket->packet + 12);
   mGain = (float)LEUint16(aPacket->packet + 16) / 256.0;
   mChannelMapping = aPacket->packet[18];
 
   if (mChannelMapping == 0) {
     mStreams = 1;
@@ -855,17 +863,17 @@ PRInt64 nsOpusState::Time(PRInt64 granul
   // Ogg Opus always runs at a granule rate of 48 kHz.
   CheckedInt64 t = CheckedInt64(granulepos - mPreSkip) * USECS_PER_S;
   return t.isValid() ? t.value() / mRate : -1;
 }
 
 bool nsOpusState::IsHeader(ogg_packet* aPacket)
 {
   return aPacket->bytes >= 16 &&
-         (!memcmp(aPacket->packet, "OpusHead\0", 9) ||
+         (!memcmp(aPacket->packet, "OpusHead", 8) ||
           !memcmp(aPacket->packet, "OpusTags", 8));
 }
 
 nsresult nsOpusState::PageIn(ogg_page* aPage)
 {
   if (!mActive)
     return NS_OK;
   NS_ASSERTION(static_cast<PRUint32>(ogg_page_serialno(aPage)) == mSerial,