Bug 1282722: add seek target threshold for VPX decoder. r?jwwang
MozReview-Commit-ID: FGLhKRH8j3u
--- a/dom/media/platforms/agnostic/VPXDecoder.cpp
+++ b/dom/media/platforms/agnostic/VPXDecoder.cpp
@@ -88,17 +88,17 @@ VPXDecoder::Init()
}
nsresult
VPXDecoder::Flush()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
mIsFlushing = true;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([this] () {
- // nothing to do for now.
+ this->mSeekTargetThreshold.reset();
});
SyncRunnable::DispatchToThread(mTaskQueue, r);
mIsFlushing = false;
return NS_OK;
}
int
VPXDecoder::DoDecode(MediaRawData* aSample)
@@ -125,16 +125,25 @@ VPXDecoder::DoDecode(MediaRawData* aSamp
vpx_codec_iter_t iter = nullptr;
vpx_image_t *img;
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 ||
img->fmt == VPX_IMG_FMT_I444,
"WebM image format not I420 or I444");
+ if (mSeekTargetThreshold) {
+ if ((aSample->mTime + aSample->mDuration) < mSeekTargetThreshold.ref().ToMicroseconds()) {
+ LOG("VPX Decode drops frame with pts %lld, duration: %lld",
+ aSample->mTime, aSample->mDuration);
+ continue;
+ }
+ mSeekTargetThreshold.reset();
+ }
+
// Chroma shifts are rounded down as per the decoding examples in the SDK
VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = img->planes[0];
b.mPlanes[0].mStride = img->stride[0];
b.mPlanes[0].mHeight = img->d_h;
b.mPlanes[0].mWidth = img->d_w;
b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
@@ -220,16 +229,27 @@ nsresult
VPXDecoder::Drain()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
mTaskQueue->Dispatch(NewRunnableMethod(this, &VPXDecoder::ProcessDrain));
return NS_OK;
}
+void
+VPXDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ RefPtr<VPXDecoder> self = this;
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aTime] () {
+ self->mSeekTargetThreshold = Some(aTime);
+ });
+ mTaskQueue->Dispatch(r.forget());
+}
+
/* static */
bool
VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask)
{
return ((aCodecMask & VPXDecoder::VP8) &&
aMimeType.EqualsLiteral("video/webm; codecs=vp8")) ||
((aCodecMask & VPXDecoder::VP9) &&
aMimeType.EqualsLiteral("video/webm; codecs=vp9"));
--- a/dom/media/platforms/agnostic/VPXDecoder.h
+++ b/dom/media/platforms/agnostic/VPXDecoder.h
@@ -32,16 +32,17 @@ public:
nsresult Input(MediaRawData* aSample) override;
nsresult Flush() override;
nsresult Drain() override;
nsresult Shutdown() override;
const char* GetDescriptionName() const override
{
return "libvpx video decoder";
}
+ void SetSeekThreshold(const media::TimeUnit& aTime) override;
enum Codec: uint8_t {
VP8 = 1 << 0,
VP9 = 1 << 1
};
// Return true if mimetype is a VPX codec of given types.
static bool IsVPX(const nsACString& aMimeType, uint8_t aCodecMask=VP8|VP9);
@@ -50,16 +51,18 @@ private:
void ProcessDecode(MediaRawData* aSample);
int DoDecode(MediaRawData* aSample);
void ProcessDrain();
const RefPtr<ImageContainer> mImageContainer;
const RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
Atomic<bool> mIsFlushing;
+ // mSeekTargetThreshold is accessed in mTaskQueue.
+ Maybe<media::TimeUnit> mSeekTargetThreshold;
// VPx decoder state
vpx_codec_ctx_t mVPX;
const VideoInfo& mInfo;
const int mCodec;
};