Bug 1062101 - Compute WebM frame duration from Δt of last frame. r=cajbir
authorMatthew Gregan <kinetik@flim.org>
Wed, 03 Sep 2014 17:26:19 +1200
changeset 203248 b83d8447aaaa7581ef3228857aa0eaa82f289b92
parent 203247 f9ecc7e716891d3a79c1072699c0cb7afaeaa363
child 203249 c01b953e1f537e16ec3be5a792c898d5a13ac5a2
push id48629
push usermgregan@mozilla.com
push dateWed, 03 Sep 2014 13:42:21 +0000
treeherdermozilla-inbound@b83d8447aaaa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1062101
milestone35.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 1062101 - Compute WebM frame duration from Δt of last frame. r=cajbir
content/media/AbstractMediaDecoder.h
content/media/MediaDecoder.cpp
content/media/MediaDecoder.h
content/media/MediaDecoderStateMachine.h
content/media/mediasource/SourceBufferDecoder.cpp
content/media/mediasource/SourceBufferDecoder.h
content/media/webaudio/BufferDecoder.cpp
content/media/webaudio/BufferDecoder.h
content/media/webm/WebMReader.cpp
content/media/webm/WebMReader.h
--- a/content/media/AbstractMediaDecoder.h
+++ b/content/media/AbstractMediaDecoder.h
@@ -60,21 +60,16 @@ public:
   // Called by the decode thread to keep track of the number of bytes read
   // from the resource.
   virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) = 0;
 
   // Increments the parsed and decoded frame counters by the passed in counts.
   // Can be called on any thread.
   virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) = 0;
 
-  // Returns the end time of the last sample in the media. Note that a media
-  // can have a non-zero start time, so the end time may not necessarily be
-  // the same as the duration (i.e. duration is (end_time - start_time)).
-  virtual int64_t GetEndMediaTime() const = 0;
-
   // Return the duration of the media in microseconds.
   virtual int64_t GetMediaDuration() = 0;
 
   // Set the duration of the media in microseconds.
   virtual void SetMediaDuration(int64_t aDuration) = 0;
 
   // Sets the duration of the media in microseconds. The MediaDecoder
   // fires a durationchange event to its owner (e.g., an HTML audio
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -1547,21 +1547,16 @@ MediaDecoder::NotifyWaitingForResourcesS
   }
 }
 
 bool MediaDecoder::IsShutdown() const {
   NS_ENSURE_TRUE(GetStateMachine(), true);
   return GetStateMachine()->IsShutdown();
 }
 
-int64_t MediaDecoder::GetEndMediaTime() const {
-  NS_ENSURE_TRUE(GetStateMachine(), -1);
-  return GetStateMachine()->GetEndMediaTime();
-}
-
 // Drop reference to state machine.  Only called during shutdown dance.
 void MediaDecoder::BreakCycles() {
   mDecoderStateMachine = nullptr;
 }
 
 MediaDecoderOwner* MediaDecoder::GetMediaOwner() const
 {
   return mOwner;
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -576,18 +576,16 @@ public:
   // changed. Called on main thread only.
   virtual void NotifyPrincipalChanged();
 
   // Called by the MediaResource to keep track of the number of bytes read
   // from the resource. Called on the main by an event runner dispatched
   // by the MediaResource read functions.
   void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
 
-  int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
-
   // Return true if we are currently seeking in the media resource.
   // Call on the main thread only.
   virtual bool IsSeeking() const;
 
   // Return true if the decoder has reached the end of playback.
   // Call on the main thread only.
   virtual bool IsEnded() const;
 
--- a/content/media/MediaDecoderStateMachine.h
+++ b/content/media/MediaDecoderStateMachine.h
@@ -270,21 +270,16 @@ public:
     if (mReader) {
       return mReader->SizeOfAudioQueueInBytes();
     }
     return 0;
   }
 
   void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
 
-  int64_t GetEndMediaTime() const {
-    AssertCurrentThreadInMonitor();
-    return mEndTime;
-  }
-
   // Returns the shared state machine thread.
   nsIEventTarget* GetStateMachineThread() const;
 
   // Calls ScheduleStateMachine() after taking the decoder lock. Also
   // notifies the decoder thread in case it's waiting on the decoder lock.
   void ScheduleStateMachineWithLockAndWakeDecoder();
 
   // Schedules the shared state machine thread to run the state machine
--- a/content/media/mediasource/SourceBufferDecoder.cpp
+++ b/content/media/mediasource/SourceBufferDecoder.cpp
@@ -58,22 +58,16 @@ SourceBufferDecoder::IsShutdown() const
 
 void
 SourceBufferDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::NotifyBytesConsumed UNIMPLEMENTED", this);
 }
 
 int64_t
-SourceBufferDecoder::GetEndMediaTime() const
-{
-  return mMediaDuration;
-}
-
-int64_t
 SourceBufferDecoder::GetMediaDuration()
 {
   return mMediaDuration;
 }
 
 VideoFrameContainer*
 SourceBufferDecoder::GetVideoFrameContainer()
 {
--- a/content/media/mediasource/SourceBufferDecoder.h
+++ b/content/media/mediasource/SourceBufferDecoder.h
@@ -33,17 +33,16 @@ public:
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
   virtual bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
   virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE;
   virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE;
   virtual bool OnStateMachineThread() const MOZ_FINAL MOZ_OVERRIDE;
-  virtual int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
   virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
   virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE;
   virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
   virtual SourceBufferResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
   virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
   virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
   virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
   virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
--- a/content/media/webaudio/BufferDecoder.cpp
+++ b/content/media/webaudio/BufferDecoder.cpp
@@ -84,23 +84,16 @@ BufferDecoder::NotifyBytesConsumed(int64
 
 void
 BufferDecoder::NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded)
 {
   // ignore
 }
 
 int64_t
-BufferDecoder::GetEndMediaTime() const
-{
-  // unknown
-  return -1;
-}
-
-int64_t
 BufferDecoder::GetMediaDuration()
 {
   // unknown
   return -1;
 }
 
 void
 BufferDecoder::SetMediaDuration(int64_t aDuration)
--- a/content/media/webaudio/BufferDecoder.h
+++ b/content/media/webaudio/BufferDecoder.h
@@ -38,18 +38,16 @@ public:
   virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE;
 
   virtual MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
-
   virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
 
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -152,16 +152,17 @@ WebMReader::WebMReader(AbstractMediaDeco
   mOpusDecoder(nullptr),
   mSkip(0),
   mSeekPreroll(0),
 #endif
   mVideoTrack(0),
   mAudioTrack(0),
   mAudioStartUsec(-1),
   mAudioFrames(0),
+  mLastVideoFrameTime(0),
   mAudioCodec(-1),
   mVideoCodec(-1),
   mHasVideo(false),
   mHasAudio(false)
 {
   MOZ_COUNT_CTOR(WebMReader);
 #ifdef PR_LOGGING
   if (!gNesteggLog) {
@@ -859,36 +860,33 @@ bool WebMReader::DecodeVideoFrame(bool &
     return false;
   }
 
   uint64_t tstamp = 0;
   r = nestegg_packet_tstamp(packet, &tstamp);
   if (r == -1) {
     return false;
   }
+  mLastVideoFrameTime = tstamp;
 
   // The end time of this frame is the start time of the next frame.  Fetch
   // the timestamp of the next packet for this track.  If we've reached the
   // end of the resource, use the file's duration as the end time of this
   // video frame.
   uint64_t next_tstamp = 0;
   nsAutoRef<NesteggPacketHolder> next_holder(NextPacket(VIDEO));
   if (next_holder) {
     r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp);
     if (r == -1) {
       return false;
     }
     PushVideoPacket(next_holder.disown());
   } else {
-    ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
-    int64_t endTime = mDecoder->GetEndMediaTime();
-    if (endTime == -1) {
-      return false;
-    }
-    next_tstamp = endTime * NS_PER_USEC;
+    next_tstamp = tstamp;
+    next_tstamp += tstamp - mLastVideoFrameTime;
   }
 
   int64_t tstamp_usecs = tstamp / NS_PER_USEC;
   for (uint32_t i = 0; i < count; ++i) {
     unsigned char* data;
     size_t length;
     r = nestegg_packet_data(packet, i, &data, &length);
     if (r == -1) {
--- a/content/media/webm/WebMReader.h
+++ b/content/media/webm/WebMReader.h
@@ -219,16 +219,20 @@ private:
   int64_t mAudioStartUsec;
 
   // Number of audio frames we've decoded since decoding began at mAudioStartMs.
   uint64_t mAudioFrames;
 
   // Number of microseconds that must be discarded from the start of the Stream.
   uint64_t mCodecDelay;
 
+  // Calculate the frame duration from the last decodeable frame using the
+  // previous frame's timestamp.  In NS.
+  uint64_t mLastVideoFrameTime;
+
   // 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.
   nsIntSize mInitialFrame;