зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
cdb1a3d36f
Коммит
be902c66f8
|
@ -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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче