Bug 1346120 part 1 - Extract BlankMediaDataDecoder so it can be shared; r=jwwang

Change name to 'Dummy' to signify it's base for decoders that don't decode.
And we will implement a new NullDecoderModule in the next patch which will utilize the DummyMediaDataDecoder.
MozReview-Commit-ID: LPsczoztgx3

--HG--
extra : rebase_source : 413345139ba060065217cfd7718665091f8f6166
extra : intermediate-source : 12d022e15b7a3a91867293fd2e71510fa084ff02
extra : source : dec60f61cc8809ebe6dd65cb16a325f2272b3ce2
This commit is contained in:
Kaku Kuo 2017-03-09 15:33:53 +08:00
Родитель cdb1a3d36f
Коммит be902c66f8
4 изменённых файлов: 186 добавлений и 129 удалений

Просмотреть файл

@ -4,114 +4,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/CheckedInt.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/RefPtr.h"
#include "nsRect.h"
#include "nsSize.h"
#include "DummyMediaDataDecoder.h"
#include "ImageContainer.h"
#include "MP4Decoder.h"
#include "MediaDecoderReader.h"
#include "MediaData.h"
#include "MediaInfo.h"
#include "PlatformDecoderModule.h"
#include "ReorderQueue.h"
#include "TimeUnits.h"
#include "VideoUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/mozalloc.h" // for operator new, and new (fallible)
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
#include "nsAutoPtr.h"
#include "nsRect.h"
namespace mozilla {
// Decoder that uses a passed in object's Create function to create blank
// MediaData objects.
template<class BlankMediaDataCreator>
class BlankMediaDataDecoder : public MediaDataDecoder
{
public:
BlankMediaDataDecoder(BlankMediaDataCreator* aCreator,
const CreateDecoderParams& aParams)
: mCreator(aCreator)
, mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
, mMaxRefFrames(
mIsH264
? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
? mp4_demuxer::H264::ComputeMaxRefFrames(
aParams.VideoConfig().mExtraData)
: 16
: 0)
, mType(aParams.mConfig.GetType())
{
}
RefPtr<InitPromise> Init() override
{
return InitPromise::CreateAndResolve(mType, __func__);
}
RefPtr<ShutdownPromise> Shutdown() override
{
return ShutdownPromise::CreateAndResolve(true, __func__);
}
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override
{
RefPtr<MediaData> data =
mCreator->Create(media::TimeUnit::FromMicroseconds(aSample->mTime),
media::TimeUnit::FromMicroseconds(aSample->mDuration),
aSample->mOffset);
if (!data) {
return DecodePromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
}
// Frames come out in DTS order but we need to output them in PTS order.
mReorderQueue.Push(data);
if (mReorderQueue.Length() > mMaxRefFrames) {
return DecodePromise::CreateAndResolve(
DecodedData{ mReorderQueue.Pop().get() }, __func__);
}
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
}
RefPtr<DecodePromise> Drain() override
{
DecodedData samples;
while (!mReorderQueue.IsEmpty()) {
samples.AppendElement(mReorderQueue.Pop().get());
}
return DecodePromise::CreateAndResolve(samples, __func__);
}
RefPtr<FlushPromise> Flush() override
{
mReorderQueue.Clear();
return FlushPromise::CreateAndResolve(true, __func__);
}
const char* GetDescriptionName() const override
{
return "blank media data decoder";
}
ConversionRequired NeedsConversion() const override
{
return mIsH264
? ConversionRequired::kNeedAVCC
: ConversionRequired::kNeedNone;
}
private:
nsAutoPtr<BlankMediaDataCreator> mCreator;
const bool mIsH264;
const uint32_t mMaxRefFrames;
ReorderQueue mReorderQueue;
TrackInfo::TrackType mType;
};
class BlankVideoDataCreator
{
class BlankVideoDataCreator : public DummyDataCreator {
public:
BlankVideoDataCreator(uint32_t aFrameWidth,
uint32_t aFrameHeight,
@ -124,9 +31,7 @@ public:
mPicture = gfx::IntRect(0, 0, mFrameWidth, mFrameHeight);
}
already_AddRefed<MediaData> Create(const media::TimeUnit& aDTS,
const media::TimeUnit& aDuration,
int64_t aOffsetInStream)
already_AddRefed<MediaData> Create(MediaRawData* aSample) override
{
// Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane,
// with a U and V plane that are half the size of the Y plane, i.e 8 bit,
@ -166,12 +71,12 @@ public:
return VideoData::CreateAndCopyData(mInfo,
mImageContainer,
aOffsetInStream,
aDTS.ToMicroseconds(),
aDuration.ToMicroseconds(),
aSample->mOffset,
aSample->mTime,
aSample->mDuration,
buffer,
true,
aDTS.ToMicroseconds(),
aSample->mKeyframe,
aSample->mTime,
mPicture);
}
@ -183,7 +88,7 @@ private:
RefPtr<layers::ImageContainer> mImageContainer;
};
class BlankAudioDataCreator
class BlankAudioDataCreator : public DummyDataCreator
{
public:
BlankAudioDataCreator(uint32_t aChannelCount, uint32_t aSampleRate)
@ -191,14 +96,11 @@ public:
{
}
MediaData* Create(const media::TimeUnit& aDTS,
const media::TimeUnit& aDuration,
int64_t aOffsetInStream)
already_AddRefed<MediaData> Create(MediaRawData* aSample) override
{
// Convert duration to frames. We add 1 to duration to account for
// rounding errors, so we get a consistent tone.
CheckedInt64 frames =
UsecsToFrames(aDuration.ToMicroseconds()+1, mSampleRate);
CheckedInt64 frames = UsecsToFrames(aSample->mDuration+1, mSampleRate);
if (!frames.isValid()
|| !mChannelCount
|| !mSampleRate
@ -219,13 +121,14 @@ public:
}
mFrameSum++;
}
return new AudioData(aOffsetInStream,
aDTS.ToMicroseconds(),
aDuration.ToMicroseconds(),
uint32_t(frames.value()),
Move(samples),
mChannelCount,
mSampleRate);
RefPtr<AudioData> data(new AudioData(aSample->mOffset,
aSample->mTime,
aSample->mDuration,
uint32_t(frames.value()),
Move(samples),
mChannelCount,
mSampleRate));
return data.forget();
}
private:
@ -243,10 +146,10 @@ public:
CreateVideoDecoder(const CreateDecoderParams& aParams) override
{
const VideoInfo& config = aParams.VideoConfig();
BlankVideoDataCreator* creator = new BlankVideoDataCreator(
config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer);
UniquePtr<DummyDataCreator> creator =
MakeUnique<BlankVideoDataCreator>(config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankVideoDataCreator>(creator, aParams);
new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
return decoder.forget();
}
@ -255,11 +158,10 @@ public:
CreateAudioDecoder(const CreateDecoderParams& aParams) override
{
const AudioInfo& config = aParams.AudioConfig();
BlankAudioDataCreator* creator = new BlankAudioDataCreator(
config.mChannels, config.mRate);
UniquePtr<DummyDataCreator> creator =
MakeUnique<BlankAudioDataCreator>(config.mChannels, config.mRate);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankAudioDataCreator>(creator, aParams);
new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
return decoder.forget();
}

Просмотреть файл

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DummyMediaDataDecoder.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
namespace mozilla {
DummyDataCreator::~DummyDataCreator() {}
DummyMediaDataDecoder::DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
const char* aDescription,
const CreateDecoderParams& aParams)
: mCreator(Move(aCreator))
, mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
, mMaxRefFrames(
mIsH264
? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
? mp4_demuxer::H264::ComputeMaxRefFrames(aParams.VideoConfig().mExtraData)
: 16
: 0)
, mType(aParams.mConfig.GetType())
, mDescription(aDescription)
{
}
RefPtr<MediaDataDecoder::InitPromise>
DummyMediaDataDecoder::Init()
{
return InitPromise::CreateAndResolve(mType, __func__);
}
RefPtr<ShutdownPromise>
DummyMediaDataDecoder::Shutdown()
{
return ShutdownPromise::CreateAndResolve(true, __func__);
}
RefPtr<MediaDataDecoder::DecodePromise>
DummyMediaDataDecoder::Decode(MediaRawData* aSample)
{
RefPtr<MediaData> data = mCreator->Create(aSample);
if (!data) {
return DecodePromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
}
// Frames come out in DTS order but we need to output them in PTS order.
mReorderQueue.Push(data);
if (mReorderQueue.Length() > mMaxRefFrames) {
return DecodePromise::CreateAndResolve(
DecodedData{ mReorderQueue.Pop().get() }, __func__);
}
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
}
RefPtr<MediaDataDecoder::DecodePromise>
DummyMediaDataDecoder::Drain()
{
DecodedData samples;
while (!mReorderQueue.IsEmpty()) {
samples.AppendElement(mReorderQueue.Pop().get());
}
return DecodePromise::CreateAndResolve(samples, __func__);
}
RefPtr<MediaDataDecoder::FlushPromise>
DummyMediaDataDecoder::Flush()
{
mReorderQueue.Clear();
return FlushPromise::CreateAndResolve(true, __func__);
}
const char*
DummyMediaDataDecoder::GetDescriptionName() const
{
return "blank media data decoder";
}
MediaDataDecoder::ConversionRequired
DummyMediaDataDecoder::NeedsConversion() const
{
return mIsH264
? ConversionRequired::kNeedAVCC
: ConversionRequired::kNeedNone;
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(DummyMediaDataDecoder_h_)
#define DummyMediaDataDecoder_h_
#include "MediaInfo.h"
#include "mozilla/UniquePtr.h"
#include "PlatformDecoderModule.h"
#include "ReorderQueue.h"
namespace mozilla {
class MediaRawData;
class DummyDataCreator
{
public:
virtual ~DummyDataCreator();
virtual already_AddRefed<MediaData> Create(MediaRawData* aSample) = 0;
};
// Decoder that uses a passed in object's Create function to create Null
// MediaData objects.
class DummyMediaDataDecoder : public MediaDataDecoder
{
public:
DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
const char* aDescription,
const CreateDecoderParams& aParams);
RefPtr<InitPromise> Init() override;
RefPtr<ShutdownPromise> Shutdown() override;
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
RefPtr<DecodePromise> Drain() override;
RefPtr<FlushPromise> Flush() override;
const char* GetDescriptionName() const override;
ConversionRequired NeedsConversion() const override;
private:
UniquePtr<DummyDataCreator> mCreator;
const bool mIsH264;
const uint32_t mMaxRefFrames;
ReorderQueue mReorderQueue;
TrackInfo::TrackType mType;
nsCString mDescription;
};
} // namespace mozilla
#endif // !defined(DummyMediaDataDecoder_h_)

Просмотреть файл

@ -6,6 +6,7 @@
EXPORTS += [
'agnostic/AgnosticDecoderModule.h',
'agnostic/DummyMediaDataDecoder.h',
'agnostic/OpusDecoder.h',
'agnostic/TheoraDecoder.h',
'agnostic/VorbisDecoder.h',
@ -22,6 +23,7 @@ EXPORTS += [
UNIFIED_SOURCES += [
'agnostic/AgnosticDecoderModule.cpp',
'agnostic/BlankDecoderModule.cpp',
'agnostic/DummyMediaDataDecoder.cpp',
'agnostic/OpusDecoder.cpp',
'agnostic/TheoraDecoder.cpp',
'agnostic/VorbisDecoder.cpp',