Bug 650157 - Push nsBuiltinDecoderReader::mDataOffset down into nsOggReader. r=doublec
authorChris Pearce <chris@pearce.org.nz>
Fri, 15 Apr 2011 13:29:54 +1200
changeset 68151 24505fa656f3cd03fc599a11bf0ab30a7409aa80
parent 68150 fa4889ad04e29da0145cd0153ef72806d0b31a59
child 68152 29ea31633ac69c8d7219bb7a741bb8ae182da4d6
push idunknown
push userunknown
push dateunknown
reviewersdoublec
bugs650157
milestone6.0a1
Bug 650157 - Push nsBuiltinDecoderReader::mDataOffset down into nsOggReader. r=doublec
content/media/nsBuiltinDecoderReader.cpp
content/media/nsBuiltinDecoderReader.h
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/ogg/nsOggReader.cpp
content/media/ogg/nsOggReader.h
content/media/raw/nsRawReader.h
content/media/wave/nsWaveReader.cpp
content/media/webm/nsWebMReader.cpp
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -203,18 +203,17 @@ VideoData* VideoData::Create(nsVideoInfo
   data.mStereoMode = aInfo.mStereoMode;
 
   videoImage->SetData(data); // Copies buffer
   return v.forget();
 }
 
 nsBuiltinDecoderReader::nsBuiltinDecoderReader(nsBuiltinDecoder* aDecoder)
   : mMonitor("media.decoderreader"),
-    mDecoder(aDecoder),
-    mDataOffset(0)
+    mDecoder(aDecoder)
 {
   MOZ_COUNT_CTOR(nsBuiltinDecoderReader);
 }
 
 nsBuiltinDecoderReader::~nsBuiltinDecoderReader()
 {
   ResetDecode();
   MOZ_COUNT_DTOR(nsBuiltinDecoderReader);
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -87,20 +87,16 @@ public:
 
   // The picture region inside the video frame to be displayed.
   nsIntRect mPicture;
 
   // Display size of the video frame. The picture region will be scaled
   // to and displayed at this size.
   nsIntSize mDisplay;
 
-  // The offset of the first non-header page in the file, in bytes.
-  // Used to seek to the start of the media.
-  PRInt64 mDataOffset;
-
   // Indicates the frame layout for single track stereo videos.
   mozilla::layers::StereoMode mStereoMode;
 
   // PR_TRUE if we have an active audio bitstream.
   PRPackedBool mHasAudio;
 
   // PR_TRUE if we have an active video bitstream.
   PRPackedBool mHasVideo;
@@ -508,18 +504,14 @@ protected:
   // The lock which we hold whenever we read or decode. This ensures the thread
   // safety of the reader and its data fields.
   Monitor mMonitor;
 
   // Reference to the owning decoder object. Do not hold the
   // reader's monitor when accessing this.
   nsBuiltinDecoder* mDecoder;
 
-  // The offset of the start of the first non-header page in the file.
-  // Used to seek to media start time.
-  PRInt64 mDataOffset;
-
   // Stores presentation info required for playback. The reader's monitor
   // must be held when accessing this.
   nsVideoInfo mInfo;
 };
 
 #endif
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1552,20 +1552,19 @@ void nsBuiltinDecoderStateMachine::Wait(
 
 VideoData* nsBuiltinDecoderStateMachine::FindStartTime()
 {
   NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread), "Should be on state machine thread.");
   mDecoder->GetMonitor().AssertCurrentThreadIn();
   PRInt64 startTime = 0;
   mStartTime = 0;
   VideoData* v = nsnull;
-  PRInt64 dataOffset = mInfo.mDataOffset;
   {
     MonitorAutoExit exitMon(mDecoder->GetMonitor());
-    v = mReader->FindStartTime(dataOffset, startTime);
+    v = mReader->FindStartTime(0, startTime);
   }
   if (startTime != 0) {
     mStartTime = startTime;
     if (mGotDurationFromMetaData) {
       NS_ASSERTION(mEndTime != -1,
                    "We should have mEndTime as supplied duration here");
       // We were specified a duration from a Content-Duration HTTP header.
       // Adjust mEndTime so that mEndTime-mStartTime matches the specified
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -102,17 +102,18 @@ nsOggReader::nsOggReader(nsBuiltinDecode
   : nsBuiltinDecoderReader(aDecoder),
     mTheoraState(nsnull),
     mVorbisState(nsnull),
     mSkeletonState(nsnull),
     mVorbisSerial(0),
     mTheoraSerial(0),
     mPageOffset(0),
     mTheoraGranulepos(-1),
-    mVorbisGranulepos(-1)
+    mVorbisGranulepos(-1),
+    mDataOffset(0)
 {
   MOZ_COUNT_CTOR(nsOggReader);
 }
 
 nsOggReader::~nsOggReader()
 {
   ogg_sync_clear(&mOggState);
   MOZ_COUNT_DTOR(nsOggReader);
@@ -319,17 +320,16 @@ nsresult nsOggReader::ReadMetadata(nsVid
                                mTheoraState->mInfo.pic_y,
                                mTheoraState->mInfo.pic_width,
                                mTheoraState->mInfo.pic_height);
     mInfo.mFrame = nsIntSize(mTheoraState->mInfo.frame_width,
                              mTheoraState->mInfo.frame_height);
     mInfo.mDisplay = nsIntSize(mInfo.mPicture.width,
                                mInfo.mPicture.height);
   }
-  mInfo.mDataOffset = mDataOffset;
 
   if (mSkeletonState && mSkeletonState->HasIndex()) {
     // Extract the duration info out of the index, so we don't need to seek to
     // the end of stream to get it.
     nsAutoTArray<PRUint32, 2> tracks;
     if (HasVideo()) {
       tracks.AppendElement(mTheoraState->mSerial);
     }
@@ -901,29 +901,34 @@ GetChecksum(ogg_page* page)
 
 VideoData* nsOggReader::FindStartTime(PRInt64 aOffset,
                                       PRInt64& aOutStartTime)
 {
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ENSURE_TRUE(stream != nsnull, nsnull);
-  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
+  // Ensure aOffset is after mDataOffset, the offset of the first non-header page.
+  // This prevents us from trying to parse header pages as content pages.
+  NS_ASSERTION(mDataOffset > 0, "Must know mDataOffset by now");
+  PRInt64 offset = NS_MAX(mDataOffset, aOffset);
+  nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
   NS_ENSURE_SUCCESS(res, nsnull);
-  return nsBuiltinDecoderReader::FindStartTime(aOffset, aOutStartTime);
+  return nsBuiltinDecoderReader::FindStartTime(offset, aOutStartTime);
 }
 
 PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset)
 {
   MonitorAutoEnter mon(mMonitor);
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   NS_ASSERTION(mDataOffset > 0,
                "Should have offset of first non-header page");
-  PRInt64 endTime = FindEndTime(mDataOffset, aEndOffset, PR_FALSE, &mOggState);
+  PRInt64 offset = NS_MAX(mDataOffset, aEndOffset);
+  PRInt64 endTime = FindEndTime(mDataOffset, offset, PR_FALSE, &mOggState);
   // Reset read head to start of media data.
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ENSURE_TRUE(stream != nsnull, -1);
   nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset);
   NS_ENSURE_SUCCESS(res, -1);
   return endTime;
 }
 
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -277,11 +277,16 @@ private:
   // the page we're about to read.
   PRInt64 mPageOffset;
 
   // The granulepos of the last decoded Theora frame.
   PRInt64 mTheoraGranulepos;
 
   // The granulepos of the last decoded Vorbis sample.
   PRInt64 mVorbisGranulepos;
+
+  // The offset of the first non-header page in the file, in bytes.
+  // Used to seek to the start of the media, and to prevent us trying to
+  // decode pages before this offset (the header pages) as content pages.
+  PRInt64 mDataOffset;
 };
 
 #endif
--- a/content/media/raw/nsRawReader.h
+++ b/content/media/raw/nsRawReader.h
@@ -107,17 +107,16 @@ public:
 
   virtual PRBool HasVideo()
   {
     return PR_TRUE;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
-  virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
   PRBool ReadFromStream(nsMediaStream *aStream, PRUint8 *aBuf,
                         PRUint32 aLength);
 
   nsRawVideoHeader mMetadata;
   PRUint32 mCurrentFrame;
--- a/content/media/wave/nsWaveReader.cpp
+++ b/content/media/wave/nsWaveReader.cpp
@@ -159,17 +159,16 @@ nsresult nsWaveReader::ReadMetadata(nsVi
   if (!loaded) {
     return NS_ERROR_FAILURE;
   }
 
   mInfo.mHasAudio = PR_TRUE;
   mInfo.mHasVideo = PR_FALSE;
   mInfo.mAudioRate = mSampleRate;
   mInfo.mAudioChannels = mChannels;
-  mInfo.mDataOffset = -1;
 
   *aInfo = mInfo;
 
   MonitorAutoExit exitReaderMon(mMonitor);
   MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
 
   mDecoder->GetStateMachine()->SetDuration(
     static_cast<PRInt64>(BytesToTime(GetDataLength()) * USECS_PER_S));
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -325,21 +325,16 @@ nsresult nsWebMReader::ReadMetadata(nsVi
           break;
         case 4:
           mInfo.mStereoMode = STEREO_MODE_BOTTOM_TOP;
           break;
         default:
           mInfo.mStereoMode = STEREO_MODE_MONO;
         }
       }
-
-      // mDataOffset is not used by the WebM backend.
-      // See bug 566779 for a suggestion to refactor
-      // and remove it.
-      mInfo.mDataOffset = -1;
     }
     else if (!mHasAudio && type == NESTEGG_TRACK_AUDIO) {
       nestegg_audio_params params;
       r = nestegg_track_audio_params(mContext, track, &params);
       if (r == -1) {
         Cleanup();
         return NS_ERROR_FAILURE;
       }