Bug 1393087 - P3: Retry backward to find keyframe. r=kinetik

When we seek in a webm containing an alpha channel, the first frame of a cluster may not be a keyframe for both channels. So seek backward until we find one.

We limit such operation on video with an alpha channel to prevent potential regression (even though thoses files would technically be invalid)

MozReview-Commit-ID: 14ETazkQ0AG

--HG--
extra : rebase_source : 8e106a382605c23769da5a8da5b88d107833cc6e
This commit is contained in:
Jean-Yves Avenard 2017-09-25 16:47:08 +02:00
parent f219b74756
commit ac1d631264

View File

@ -1097,23 +1097,48 @@ WebMTrackDemuxer::Seek(const TimeUnit& aTime)
// actual time seeked to. Typically the random access point time
auto seekTime = aTime;
mSamples.Reset();
mParent->SeekInternal(mType, aTime);
nsresult rv = mParent->GetNextPacket(mType, &mSamples);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
// Ignore the error for now, the next GetSample will be rejected with EOS.
return SeekPromise::CreateAndResolve(TimeUnit::Zero(), __func__);
}
return SeekPromise::CreateAndReject(rv, __func__);
}
bool keyframe = false;
mNeedKeyframe = true;
// Check what time we actually seeked to.
if (mSamples.GetSize() > 0) {
const RefPtr<MediaRawData>& sample = mSamples.First();
seekTime = sample->mTime;
}
do {
mSamples.Reset();
mParent->SeekInternal(mType, seekTime);
nsresult rv = mParent->GetNextPacket(mType, &mSamples);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
// Ignore the error for now, the next GetSample will be rejected with EOS.
return SeekPromise::CreateAndResolve(TimeUnit::Zero(), __func__);
}
return SeekPromise::CreateAndReject(rv, __func__);
}
// Check what time we actually seeked to.
if (mSamples.GetSize() == 0) {
// We can't determine if the seek succeeded at this stage, so break the
// loop.
break;
}
for (const auto& sample : mSamples) {
seekTime = sample->mTime;
keyframe = sample->mKeyframe;
if (keyframe) {
break;
}
}
if (mType == TrackInfo::kVideoTrack &&
!mInfo->GetAsVideoInfo()->HasAlpha()) {
// We only perform a search for a keyframe on videos with alpha layer to
// prevent potential regression for normal video (even though invalid)
break;
}
if (!keyframe) {
// We didn't find any keyframe, attempt to seek to the previous cluster.
seekTime = mSamples.First()->mTime - TimeUnit::FromMicroseconds(1);
}
} while (!keyframe && seekTime >= TimeUnit::Zero());
SetNextKeyFrameTime();
return SeekPromise::CreateAndResolve(seekTime, __func__);