Bug 1261900: [webm] P1. Use block duration if known. r?kinetik draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 21 Apr 2016 21:07:54 +1000
changeset 356311 b1196186b5ff01b564bf9d93e7ab421fd230466f
parent 356253 cfc7ebe592937ad937cebe04fdad4213eee72fae
child 356312 99c70883427cbcf5f9c85bb3f267ad31bb5497c8
push id16492
push userbmo:jyavenard@mozilla.com
push dateTue, 26 Apr 2016 06:48:07 +0000
reviewerskinetik
bugs1261900
milestone49.0a1
Bug 1261900: [webm] P1. Use block duration if known. r?kinetik The duration returned however appears to always be zero. MozReview-Commit-ID: 8llqDhAqNmk
dom/media/webm/NesteggPacketHolder.h
dom/media/webm/WebMDemuxer.cpp
--- a/dom/media/webm/NesteggPacketHolder.h
+++ b/dom/media/webm/NesteggPacketHolder.h
@@ -14,39 +14,49 @@ namespace mozilla {
 
 // Holds a nestegg_packet, and its file offset. This is needed so we
 // know the offset in the file we've played up to, in order to calculate
 // whether it's likely we can play through to the end without needing
 // to stop to buffer, given the current download rate.
 class NesteggPacketHolder {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NesteggPacketHolder)
-  NesteggPacketHolder() : mPacket(nullptr), mOffset(-1), mTimestamp(-1), mIsKeyframe(false) {}
+  NesteggPacketHolder()
+    : mPacket(nullptr)
+    , mOffset(-1)
+    , mTimestamp(-1)
+    , mDuration(-1)
+    , mIsKeyframe(false) {}
 
   bool Init(nestegg_packet* aPacket, int64_t aOffset, unsigned aTrack, bool aIsKeyframe)
   {
     uint64_t timestamp_ns;
     if (nestegg_packet_tstamp(aPacket, &timestamp_ns) == -1) {
       return false;
     }
 
     // We store the timestamp as signed microseconds so that it's easily
     // comparable to other timestamps we have in the system.
     mTimestamp = timestamp_ns / 1000;
     mPacket = aPacket;
     mOffset = aOffset;
     mTrack = aTrack;
     mIsKeyframe = aIsKeyframe;
 
+    uint64_t duration_ns;
+    if (!nestegg_packet_duration(aPacket, &duration_ns)) {
+      mDuration = duration_ns / 1000;
+    }
     return true;
   }
 
   nestegg_packet* Packet() { MOZ_ASSERT(IsInitialized()); return mPacket; }
   int64_t Offset() { MOZ_ASSERT(IsInitialized()); return mOffset; }
   int64_t Timestamp() { MOZ_ASSERT(IsInitialized()); return mTimestamp; }
+  int64_t Duration() { MOZ_ASSERT(IsInitialized()); return mDuration; }
   unsigned Track() { MOZ_ASSERT(IsInitialized()); return mTrack; }
   bool IsKeyframe() { MOZ_ASSERT(IsInitialized()); return mIsKeyframe; }
 
 private:
   ~NesteggPacketHolder()
   {
     nestegg_free_packet(mPacket);
   }
@@ -57,16 +67,19 @@ private:
 
   // Offset in bytes. This is the offset of the end of the Block
   // which contains the packet.
   int64_t mOffset;
 
   // Packet presentation timestamp in microseconds.
   int64_t mTimestamp;
 
+  // Packet duration in microseconds; -1 if unknown or retrieval failed.
+  int64_t mDuration;
+
   // Track ID.
   unsigned mTrack;
 
   // Does this packet contain a keyframe?
   bool mIsKeyframe;
 
   // Copy constructor and assignment operator not implemented. Don't use them!
   NesteggPacketHolder(const NesteggPacketHolder &aOther);
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -506,40 +506,45 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
 
   int r = 0;
   unsigned int count = 0;
   r = nestegg_packet_count(holder->Packet(), &count);
   if (r == -1) {
     return false;
   }
   int64_t tstamp = holder->Timestamp();
+  int64_t duration = holder->Duration();
 
-  // The end time of this frame is the start time of the next frame.  Fetch
+  // 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.
   int64_t next_tstamp = INT64_MIN;
   if (aType == TrackInfo::kAudioTrack) {
     RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
     if (next_holder) {
       next_tstamp = next_holder->Timestamp();
       PushAudioPacket(next_holder);
+    } else if (duration >= 0) {
+      next_tstamp = tstamp + duration;
     } else if (!mIsMediaSource ||
                (mIsMediaSource && mLastAudioFrameTime.isSome())) {
       next_tstamp = tstamp;
       next_tstamp += tstamp - mLastAudioFrameTime.refOr(0);
     } else {
       PushAudioPacket(holder);
     }
     mLastAudioFrameTime = Some(tstamp);
   } else if (aType == TrackInfo::kVideoTrack) {
     RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
     if (next_holder) {
       next_tstamp = next_holder->Timestamp();
       PushVideoPacket(next_holder);
+    } else if (duration >= 0) {
+      next_tstamp = tstamp + duration;
     } else if (!mIsMediaSource ||
                (mIsMediaSource && mLastVideoFrameTime.isSome())) {
       next_tstamp = tstamp;
       next_tstamp += tstamp - mLastVideoFrameTime.refOr(0);
     } else {
       PushVideoPacket(holder);
     }
     mLastVideoFrameTime = Some(tstamp);