Bug 1262727: [webm] Ensure first frame returned after seek is a keyframe. r?kinetik draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 07 Apr 2016 17:40:16 +1000
changeset 348314 0e3234520658fb79873998adbcd1ebeec2eefef6
parent 348287 8318a3ba3d3878632f2a865159223cf9ff9eb1a6
child 517831 8b573bfd32972f1dc9c71e29f9c21d68a77c5b6e
push id14806
push userbmo:jyavenard@mozilla.com
push dateThu, 07 Apr 2016 07:40:41 +0000
reviewerskinetik
bugs1262727
milestone48.0a1
Bug 1262727: [webm] Ensure first frame returned after seek is a keyframe. r?kinetik Same after a reset or the first frame ever returned by the demuxer. MozReview-Commit-ID: 6b7XlIk5GE4
dom/media/webm/WebMDemuxer.cpp
dom/media/webm/WebMDemuxer.h
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -809,16 +809,17 @@ bool WebMDemuxer::GetOffsetForTime(uint6
 
 
 //WebMTrackDemuxer
 WebMTrackDemuxer::WebMTrackDemuxer(WebMDemuxer* aParent,
                                    TrackInfo::TrackType aType,
                                    uint32_t aTrackNumber)
   : mParent(aParent)
   , mType(aType)
+  , mNeedKeyframe(true)
 {
   mInfo = mParent->GetTrackInfo(aType, aTrackNumber);
   MOZ_ASSERT(mInfo);
 }
 
 WebMTrackDemuxer::~WebMTrackDemuxer()
 {
   mSamples.Reset();
@@ -835,16 +836,17 @@ WebMTrackDemuxer::Seek(media::TimeUnit a
 {
   // Seeks to aTime. Upon success, SeekPromise will be resolved with the
   // actual time seeked to. Typically the random access point time
 
   media::TimeUnit seekTime = aTime;
   mSamples.Reset();
   mParent->SeekInternal(aTime);
   mParent->GetNextPacket(mType, &mSamples);
+  mNeedKeyframe = true;
 
   // Check what time we actually seeked to.
   if (mSamples.GetSize() > 0) {
     const RefPtr<MediaRawData>& sample = mSamples.First();
     seekTime = media::TimeUnit::FromMicroseconds(sample->mTime);
   }
   SetNextKeyFrameTime();
 
@@ -870,16 +872,20 @@ WebMTrackDemuxer::GetSamples(int32_t aNu
     return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
   }
 
   while (aNumSamples) {
     RefPtr<MediaRawData> sample(NextSample());
     if (!sample) {
       break;
     }
+    if (mNeedKeyframe && !sample->mKeyframe) {
+      continue;
+    }
+    mNeedKeyframe = false;
     samples->mSamples.AppendElement(sample);
     aNumSamples--;
   }
 
   if (samples->mSamples.IsEmpty()) {
     return SamplesPromise::CreateAndReject(DemuxerFailureReason::END_OF_STREAM, __func__);
   } else {
     UpdateSamples(samples->mSamples);
@@ -946,16 +952,17 @@ WebMTrackDemuxer::SetNextKeyFrameTime()
   }
 }
 
 void
 WebMTrackDemuxer::Reset()
 {
   mSamples.Reset();
   media::TimeIntervals buffered = GetBuffered();
+  mNeedKeyframe = true;
   if (buffered.Length()) {
     WEBM_DEBUG("Seek to start point: %f", buffered.Start(0).ToSeconds());
     mParent->SeekInternal(buffered.Start(0));
     SetNextKeyFrameTime();
   } else {
     mNextKeyframeTime.reset();
   }
 }
--- a/dom/media/webm/WebMDemuxer.h
+++ b/dom/media/webm/WebMDemuxer.h
@@ -237,16 +237,17 @@ private:
   ~WebMTrackDemuxer();
   void UpdateSamples(nsTArray<RefPtr<MediaRawData>>& aSamples);
   void SetNextKeyFrameTime();
   RefPtr<MediaRawData> NextSample ();
   RefPtr<WebMDemuxer> mParent;
   TrackInfo::TrackType mType;
   UniquePtr<TrackInfo> mInfo;
   Maybe<media::TimeUnit> mNextKeyframeTime;
+  bool mNeedKeyframe;
 
   // Queued samples extracted by the demuxer, but not yet returned.
   MediaRawDataQueue mSamples;
 };
 
 } // namespace mozilla
 
 #endif