Bug 1145926: Part1. Refactor AVCC wrapper. r=cpearce

Add support for future handling of audio remuxing before conversion.
This commit is contained in:
Jean-Yves Avenard 2015-04-07 20:33:17 +10:00
parent 4070c89446
commit b5bb225e58
28 changed files with 582 additions and 519 deletions

View File

@ -1,319 +0,0 @@
/* -*- 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 "AVCCDecoderModule.h"
#include "ImageContainer.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
namespace mozilla
{
class AVCCMediaDataDecoder : public MediaDataDecoder {
public:
AVCCMediaDataDecoder(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback);
virtual ~AVCCMediaDataDecoder();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsWaitingMediaResources() override;
virtual bool IsDormantNeeded() override;
virtual void AllocateMediaResources() override;
virtual void ReleaseMediaResources() override;
virtual bool IsHardwareAccelerated() const override;
private:
// Will create the required MediaDataDecoder if we have a AVC SPS.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
void UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;
layers::LayersBackend mLayersBackend;
nsRefPtr<layers::ImageContainer> mImageContainer;
nsRefPtr<FlushableMediaTaskQueue> mVideoTaskQueue;
MediaDataDecoderCallback* mCallback;
nsRefPtr<MediaDataDecoder> mDecoder;
nsresult mLastError;
};
AVCCMediaDataDecoder::AVCCMediaDataDecoder(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
: mPDM(aPDM)
, mCurrentConfig(aConfig)
, mLayersBackend(aLayersBackend)
, mImageContainer(aImageContainer)
, mVideoTaskQueue(aVideoTaskQueue)
, mCallback(aCallback)
, mDecoder(nullptr)
, mLastError(NS_OK)
{
CreateDecoder();
}
AVCCMediaDataDecoder::~AVCCMediaDataDecoder()
{
}
nsresult
AVCCMediaDataDecoder::Init()
{
if (mDecoder) {
return mDecoder->Init();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
{
if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) {
return NS_ERROR_FAILURE;
}
nsresult rv;
if (!mDecoder) {
// It is not possible to create an AVCC H264 decoder without SPS.
// As such, creation will fail if the extra_data just extracted doesn't
// contain a SPS.
rv = CreateDecoderAndInit(aSample);
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required SPS to create the decoder.
// Ignore for the time being, the MP4Sample will be dropped.
return NS_OK;
}
} else {
rv = CheckForSPSChange(aSample);
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
return mDecoder->Input(aSample);
}
nsresult
AVCCMediaDataDecoder::Flush()
{
if (mDecoder) {
return mDecoder->Flush();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Drain()
{
if (mDecoder) {
return mDecoder->Drain();
}
return mLastError;
}
nsresult
AVCCMediaDataDecoder::Shutdown()
{
if (mDecoder) {
nsresult rv = mDecoder->Shutdown();
mDecoder = nullptr;
return rv;
}
return NS_OK;
}
bool
AVCCMediaDataDecoder::IsWaitingMediaResources()
{
if (mDecoder) {
return mDecoder->IsWaitingMediaResources();
}
return MediaDataDecoder::IsWaitingMediaResources();
}
bool
AVCCMediaDataDecoder::IsDormantNeeded()
{
return true;
}
void
AVCCMediaDataDecoder::AllocateMediaResources()
{
// Nothing to do, decoder will be allocated on the fly when required.
}
void
AVCCMediaDataDecoder::ReleaseMediaResources()
{
Shutdown();
}
nsresult
AVCCMediaDataDecoder::CreateDecoder()
{
if (!mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.extra_data)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(mCurrentConfig.extra_data);
mDecoder = mPDM->CreateVideoDecoder(mCurrentConfig,
mLayersBackend,
mImageContainer,
mVideoTaskQueue,
mCallback);
if (!mDecoder) {
mLastError = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
AVCCMediaDataDecoder::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(extra_data);
nsresult rv = CreateDecoder();
NS_ENSURE_SUCCESS(rv, rv);
return Init();
}
bool
AVCCMediaDataDecoder::IsHardwareAccelerated() const
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated();
}
return MediaDataDecoder::IsHardwareAccelerated();
}
nsresult
AVCCMediaDataDecoder::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.extra_data)) {
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
mDecoder->Flush();
ReleaseMediaResources();
return CreateDecoderAndInit(aSample);
}
void
AVCCMediaDataDecoder::UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&
spsdata.pic_width > 0 && spsdata.pic_height > 0) {
mp4_demuxer::H264::EnsureSPSIsSane(spsdata);
mCurrentConfig.image_width = spsdata.pic_width;
mCurrentConfig.image_height = spsdata.pic_height;
mCurrentConfig.display_width = spsdata.display_width;
mCurrentConfig.display_height = spsdata.display_height;
}
mCurrentConfig.extra_data = aExtraData;
}
// AVCCDecoderModule
AVCCDecoderModule::AVCCDecoderModule(PlatformDecoderModule* aPDM)
: mPDM(aPDM)
{
MOZ_ASSERT(aPDM);
}
AVCCDecoderModule::~AVCCDecoderModule()
{
}
nsresult
AVCCDecoderModule::Startup()
{
return mPDM->Startup();
}
already_AddRefed<MediaDataDecoder>
AVCCDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder;
if ((!aConfig.mime_type.EqualsLiteral("video/avc") &&
!aConfig.mime_type.EqualsLiteral("video/mp4")) ||
!mPDM->DecoderNeedsAVCC(aConfig)) {
// There is no need for an AVCC wrapper for non-AVC content.
decoder = mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback);
} else {
decoder = new AVCCMediaDataDecoder(mPDM,
aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback);
}
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
AVCCDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return mPDM->CreateAudioDecoder(aConfig,
aAudioTaskQueue,
aCallback);
}
bool
AVCCDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
{
return mPDM->SupportsAudioMimeType(aMimeType);
}
bool
AVCCDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
{
return mPDM->SupportsVideoMimeType(aMimeType);
}
} // namespace mozilla

View File

@ -1,53 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_AVCCDecoderModule_h
#define mozilla_AVCCDecoderModule_h
#include "PlatformDecoderModule.h"
namespace mozilla {
class AVCCMediaDataDecoder;
// AVCCDecoderModule is a PlatformDecoderModule wrapper used to ensure that
// only AVCC format is fed to the underlying PlatformDecoderModule.
// The AVCCDecoderModule allows playback of content where the SPS NAL may not be
// provided in the init segment (e.g. AVC3 or Annex B)
// AVCCDecoderModule will monitor the input data, and will delay creation of the
// MediaDataDecoder until a SPS and PPS NALs have been extracted.
//
// AVCC-only decoder modules are AppleVideoDecoder and EMEH264Decoder.
class AVCCDecoderModule : public PlatformDecoderModule {
public:
explicit AVCCDecoderModule(PlatformDecoderModule* aPDM);
virtual ~AVCCDecoderModule();
virtual nsresult Startup() override;
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool SupportsVideoMimeType(const nsACString& aMimeType) override;
private:
nsRefPtr<PlatformDecoderModule> mPDM;
};
} // namespace mozilla
#endif // mozilla_AVCCDecoderModule_h

View File

@ -238,11 +238,17 @@ public:
}
virtual bool
SupportsAudioMimeType(const nsACString& aMimeType) override
SupportsMimeType(const nsACString& aMimeType) override
{
return true;
}
ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return kNeedNone;
}
};
already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule()

View File

@ -344,7 +344,7 @@ MP4Reader::IsSupportedAudioMimeType(const nsACString& aMimeType)
{
return (aMimeType.EqualsLiteral("audio/mpeg") ||
aMimeType.EqualsLiteral("audio/mp4a-latm")) &&
mPlatform->SupportsAudioMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
bool
@ -353,7 +353,7 @@ MP4Reader::IsSupportedVideoMimeType(const nsACString& aMimeType)
return (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/x-vnd.on2.vp6")) &&
mPlatform->SupportsVideoMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
void
@ -514,9 +514,10 @@ MP4Reader::EnsureDecodersSetup()
NS_ENSURE_TRUE(IsSupportedAudioMimeType(mDemuxer->AudioConfig().mime_type),
false);
mAudio.mDecoder = mPlatform->CreateAudioDecoder(mDemuxer->AudioConfig(),
mAudio.mTaskQueue,
mAudio.mCallback);
mAudio.mDecoder =
mPlatform->CreateDecoder(mDemuxer->AudioConfig(),
mAudio.mTaskQueue,
mAudio.mCallback);
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, false);
nsresult rv = mAudio.mDecoder->Init();
NS_ENSURE_SUCCESS(rv, false);
@ -535,11 +536,12 @@ MP4Reader::EnsureDecodersSetup()
mVideo.mTaskQueue,
mVideo.mCallback);
} else {
mVideo.mDecoder = mPlatform->CreateVideoDecoder(mDemuxer->VideoConfig(),
mLayersBackendType,
mDecoder->GetImageContainer(),
mVideo.mTaskQueue,
mVideo.mCallback);
mVideo.mDecoder =
mPlatform->CreateDecoder(mDemuxer->VideoConfig(),
mVideo.mTaskQueue,
mVideo.mCallback,
mLayersBackendType,
mDecoder->GetImageContainer());
}
NS_ENSURE_TRUE(mVideo.mDecoder != nullptr, false);
nsresult rv = mVideo.mDecoder->Init();

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PlatformDecoderModule.h"
#include "AVCCDecoderModule.h"
#ifdef XP_WIN
#include "WMFDecoderModule.h"
@ -32,6 +31,9 @@
#include "SharedThreadPool.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "H264Converter.h"
namespace mozilla {
extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
@ -107,10 +109,7 @@ PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
}
nsRefPtr<PlatformDecoderModule> emepdm(
new AVCCDecoderModule(new EMEDecoderModule(aProxy,
pdm,
cdmDecodesAudio,
cdmDecodesVideo)));
new EMEDecoderModule(aProxy, pdm, cdmDecodesAudio, cdmDecodesVideo));
return emepdm.forget();
}
#endif
@ -151,13 +150,12 @@ PlatformDecoderModule::CreatePDM()
if (sFFmpegDecoderEnabled) {
nsRefPtr<PlatformDecoderModule> m = FFmpegRuntimeLinker::CreateDecoderModule();
if (m) {
nsRefPtr<PlatformDecoderModule> m2(new AVCCDecoderModule(m));
return m2.forget();
return m.forget();
}
}
#endif
#ifdef MOZ_APPLEMEDIA
nsRefPtr<PlatformDecoderModule> m(new AVCCDecoderModule(new AppleDecoderModule()));
nsRefPtr<PlatformDecoderModule> m(new AppleDecoderModule());
return m.forget();
#endif
#ifdef MOZ_GONK_MEDIACODEC
@ -173,28 +171,55 @@ PlatformDecoderModule::CreatePDM()
}
#endif
if (sGMPDecoderEnabled) {
nsRefPtr<PlatformDecoderModule> m(new AVCCDecoderModule(new GMPDecoderModule()));
nsRefPtr<PlatformDecoderModule> m(new GMPDecoderModule());
return m.forget();
}
return nullptr;
}
bool
PlatformDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
already_AddRefed<MediaDataDecoder>
PlatformDecoderModule::CreateDecoder(const mp4_demuxer::TrackConfig& aConfig,
FlushableMediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer)
{
return aMimeType.EqualsLiteral("audio/mp4a-latm");
nsRefPtr<MediaDataDecoder> m;
if (aConfig.IsAudioConfig()) {
m = CreateAudioDecoder(static_cast<const mp4_demuxer::AudioDecoderConfig&>(aConfig),
aTaskQueue,
aCallback);
return m.forget();
}
if (!aConfig.IsVideoConfig()) {
return nullptr;
}
if (H264Converter::IsH264(aConfig)) {
m = new H264Converter(this,
static_cast<const mp4_demuxer::VideoDecoderConfig&>(aConfig),
aLayersBackend,
aImageContainer,
aTaskQueue,
aCallback);
} else {
m = CreateVideoDecoder(static_cast<const mp4_demuxer::VideoDecoderConfig&>(aConfig),
aLayersBackend,
aImageContainer,
aTaskQueue,
aCallback);
}
return m.forget();
}
bool
PlatformDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
PlatformDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") || aMimeType.EqualsLiteral("video/avc");
}
bool
PlatformDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
{
return false;
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc");
}
} // namespace mozilla

View File

@ -14,6 +14,7 @@
#include <queue>
namespace mp4_demuxer {
class TrackConfig;
class VideoDecoderConfig;
class AudioDecoderConfig;
class MP4Sample;
@ -86,7 +87,44 @@ public:
bool aHasVideo);
#endif
// Creates an H.264 decoder. The layers backend is passed in so that
// Creates a decoder.
// See CreateVideoDecoder and CreateAudioDecoder for implementation details.
virtual already_AddRefed<MediaDataDecoder>
CreateDecoder(const mp4_demuxer::TrackConfig& aConfig,
FlushableMediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE,
layers::ImageContainer* aImageContainer = nullptr);
// An audio decoder module must support AAC by default.
// A video decoder must support H264 by default.
// If more codecs are to be supported, SupportsMimeType will have
// to be extended
virtual bool SupportsMimeType(const nsACString& aMimeType);
enum ConversionRequired {
kNeedNone,
kNeedAVCC,
kNeedAnnexB,
};
// Indicates that the decoder requires a specific format.
// The PlatformDecoderModule will convert the demuxed data accordingly before
// feeding it to MediaDataDecoder::Input.
virtual ConversionRequired DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const = 0;
virtual void DisableHardwareAcceleration() {}
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const {
return true;
}
protected:
PlatformDecoderModule() {}
virtual ~PlatformDecoderModule() {}
friend class H264Converter;
// Creates a Video decoder. The layers backend is passed in so that
// decoders can determine whether hardware accelerated decoding can be used.
// Asynchronous decoding of video should be done in runnables dispatched
// to aVideoTaskQueue. If the task queue isn't needed, the decoder should
@ -99,10 +137,10 @@ public:
// This is called on the decode task queue.
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// Creates an Audio decoder with the specified properties.
// Asynchronous decoding of audio should be done in runnables dispatched to
@ -119,24 +157,6 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// An audio decoder module must support AAC by default.
// If more audio codec is to be supported, SupportsAudioMimeType will have
// to be extended
virtual bool SupportsAudioMimeType(const nsACString& aMimeType);
virtual bool SupportsVideoMimeType(const nsACString& aMimeType);
// Indicates if the video decoder requires AVCC format.
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig);
virtual void DisableHardwareAcceleration() {}
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const {
return true;
}
protected:
PlatformDecoderModule() {}
virtual ~PlatformDecoderModule() {}
// Caches pref media.fragmented-mp4.use-blank-decoder
static bool sUseBlankDecoder;
static bool sFFmpegDecoderEnabled;
@ -213,7 +233,6 @@ public:
// The MP4Reader will not call Input() while it's calling Flush().
virtual nsresult Flush() = 0;
// Causes all complete samples in the pipeline that can be decoded to be
// output. If the decoder can't produce samples from the current output,
// it drops the input samples. The decoder may be holding onto samples
@ -244,6 +263,15 @@ public:
virtual void AllocateMediaResources() {}
virtual void ReleaseMediaResources() {}
virtual bool IsHardwareAccelerated() const { return false; }
// ConfigurationChanged will be called to inform the video or audio decoder
// that the format of the next input sample is about to change.
// If video decoder, aConfig will be a VideoDecoderConfig object.
// If audio decoder, aConfig will be a AudioDecoderConfig object.
virtual nsresult ConfigurationChanged(const mp4_demuxer::TrackConfig& aConfig)
{
return NS_OK;
}
};
} // namespace mozilla

View File

@ -87,11 +87,12 @@ SharedDecoderManager::CreateVideoDecoder(
// passed in, so that none of the objects sharing the decoder can shutdown
// the task queue while we're potentially still using it for a *different*
// object also sharing the decoder.
mDecoder = aPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
mTaskQueue,
mCallback);
mDecoder =
aPDM->CreateDecoder(aConfig,
mTaskQueue,
mCallback,
aLayersBackend,
aImageContainer);
if (!mDecoder) {
mPDM = nullptr;
return nullptr;
@ -119,11 +120,11 @@ SharedDecoderManager::Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig,
{
mDecoder->Flush();
mDecoder->Shutdown();
mDecoder = mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
mTaskQueue,
mCallback);
mDecoder = mPDM->CreateDecoder(aConfig,
mTaskQueue,
mCallback,
aLayersBackend,
aImageContainer);
if (!mDecoder) {
return false;
}

View File

@ -63,10 +63,6 @@ public:
}
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override {
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return MediaCodecDataDecoder::Input(aSample);
}
@ -248,8 +244,13 @@ public:
};
bool AndroidDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType) {
return static_cast<bool>(CreateDecoder(aMimeType));
bool AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
if (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc")) {
return true;
}
return static_cast<bool>(mozilla::CreateDecoder(aMimeType));
}
already_AddRefed<MediaDataDecoder>
@ -296,6 +297,16 @@ AndroidDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig&
}
PlatformDecoderModule::ConversionRequired
AndroidDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
if (aConfig.IsVideoConfig()) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
const nsACString& aMimeType,
MediaFormat::Param aFormat,

View File

@ -35,7 +35,10 @@ public:
AndroidDecoderModule() {}
virtual ~AndroidDecoderModule() {}
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool SupportsMimeType(const nsACString& aMimeType) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
class MediaCodecDataDecoder : public MediaDataDecoder {

View File

@ -192,15 +192,20 @@ AppleDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aC
}
bool
AppleDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("audio/mp4a-latm") || aMimeType.EqualsLiteral("audio/mpeg");
return aMimeType.EqualsLiteral("audio/mpeg") ||
PlatformDecoderModule::SupportsMimeType(aMimeType);
}
bool
AppleDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
AppleDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return true;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -32,9 +32,10 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override;
virtual bool
DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual bool SupportsMimeType(const nsACString& aMimeType) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
static void Init();
static nsresult CanDecode();

View File

@ -253,11 +253,12 @@ EMEDecoderModule::CreateVideoDecoder(const VideoDecoderConfig& aConfig,
return wrapper.forget();
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateVideoDecoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(
mPDM->CreateDecoder(aConfig,
aVideoTaskQueue,
aCallback,
aLayersBackend,
aImageContainer));
if (!decoder) {
return nullptr;
}
@ -286,9 +287,8 @@ EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
return wrapper.forget();
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAudioDecoder(aConfig,
aAudioTaskQueue,
aCallback));
nsRefPtr<MediaDataDecoder> decoder(
mPDM->CreateDecoder(aConfig, aAudioTaskQueue, aCallback));
if (!decoder) {
return nullptr;
}
@ -303,10 +303,14 @@ EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
return emeDecoder.forget();
}
bool
EMEDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
EMEDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return mCDMDecodesVideo && aConfig.crypto.valid;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -42,8 +42,8 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool
DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
private:
nsRefPtr<CDMProxy> mProxy;

View File

@ -51,19 +51,22 @@ public:
return decoder.forget();
}
virtual bool SupportsAudioMimeType(const nsACString& aMimeType) override
virtual bool SupportsMimeType(const nsACString& aMimeType) override
{
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE ||
FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
}
virtual bool SupportsVideoMimeType(const nsACString& aMimeType) override
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override
{
return FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
}
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override
{
return true;
if (aConfig.IsVideoConfig() &&
(aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4"))) {
return PlatformDecoderModule::kNeedAVCC;
} else {
return kNeedNone;
}
}
};

View File

@ -75,11 +75,15 @@ GMPDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aCon
return wrapper.forget();
}
bool
GMPDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig)
PlatformDecoderModule::ConversionRequired
GMPDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
// GMPVideoCodecType::kGMPVideoCodecH264 specifies that encoded frames must be in AVCC format.
return true;
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -31,7 +31,8 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
virtual bool DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
} // namespace mozilla

View File

@ -51,4 +51,14 @@ GonkDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aCo
return decoder.forget();
}
PlatformDecoderModule::ConversionRequired
GonkDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
if (aConfig.IsVideoConfig()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
} // namespace mozilla

View File

@ -31,6 +31,9 @@ public:
MediaDataDecoderCallback* aCallback) override;
static void Init();
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
};
} // namespace mozilla

View File

@ -452,20 +452,6 @@ GonkVideoDecoderManager::SendSampleToOMX(mp4_demuxer::MP4Sample* aSample)
0);
}
bool
GonkVideoDecoderManager::PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample)
{
if (aSample != nullptr) {
// We must prepare samples in AVC Annex B.
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
GVDM_LOG("Failed to convert sample to annex B!");
return false;
}
}
return true;
}
void
GonkVideoDecoderManager::ClearQueueFrameTime()
{

View File

@ -58,8 +58,6 @@ public:
static void RecycleCallback(TextureClient* aClient, void* aClosure);
protected:
virtual bool PerformFormatSpecificProcess(mp4_demuxer::MP4Sample* aSample) override;
virtual android::status_t SendSampleToOMX(mp4_demuxer::MP4Sample* aSample) override;
private:

View File

@ -5,21 +5,21 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'AVCCDecoderModule.h',
'MP4Decoder.h',
'MP4Reader.h',
'MP4Stream.h',
'PlatformDecoderModule.h',
'SharedDecoderManager.h',
'wrappers/H264Converter.h'
]
UNIFIED_SOURCES += [
'AVCCDecoderModule.cpp',
'BlankDecoderModule.cpp',
'MP4Decoder.cpp',
'MP4Stream.cpp',
'PlatformDecoderModule.cpp',
'SharedDecoderManager.cpp',
'wrappers/H264Converter.cpp'
]
SOURCES += [

View File

@ -121,19 +121,26 @@ WMFDecoderModule::SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig&
}
bool
WMFDecoderModule::SupportsVideoMimeType(const nsACString& aMimeType)
WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp8") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp9");
aMimeType.EqualsLiteral("video/webm; codecs=vp9") ||
aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mpeg");
}
bool
WMFDecoderModule::SupportsAudioMimeType(const nsACString& aMimeType)
PlatformDecoderModule::ConversionRequired
WMFDecoderModule::DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const
{
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mpeg");
if (aConfig.IsVideoConfig() &&
(aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4"))) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
static bool

View File

@ -31,8 +31,7 @@ public:
FlushableMediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) override;
bool SupportsVideoMimeType(const nsACString& aMimeType) override;
bool SupportsAudioMimeType(const nsACString& aMimeType) override;
bool SupportsMimeType(const nsACString& aMimeType) override;
virtual void DisableHardwareAcceleration() override
{
@ -41,6 +40,9 @@ public:
virtual bool SupportsSharedDecoders(const mp4_demuxer::VideoDecoderConfig& aConfig) const override;
virtual ConversionRequired
DecoderNeedsConversion(const mp4_demuxer::TrackConfig& aConfig) const override;
// Accessors that report whether we have the required MFTs available
// on the system to play various codecs. Windows Vista doesn't have the
// H.264/AAC decoders if the "Platform Update Supplement for Windows Vista"

View File

@ -241,12 +241,6 @@ WMFVideoMFTManager::Input(mp4_demuxer::MP4Sample* aSample)
// This can happen during shutdown.
return E_FAIL;
}
if (mStreamType != VP8 && mStreamType != VP9) {
// We must prepare samples in AVC Annex B.
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return E_FAIL;
}
}
// Forward sample data to the decoder.
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;

View File

@ -0,0 +1,249 @@
/* -*- 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 "H264Converter.h"
#include "ImageContainer.h"
#include "MediaTaskQueue.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
namespace mozilla
{
// H264 AnnexB or AVCC handler
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
H264Converter::H264Converter(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
: mPDM(aPDM)
, mCurrentConfig(aConfig)
, mLayersBackend(aLayersBackend)
, mImageContainer(aImageContainer)
, mVideoTaskQueue(aVideoTaskQueue)
, mCallback(aCallback)
, mDecoder(nullptr)
, mNeedAVCC(aPDM->DecoderNeedsConversion(aConfig) == PlatformDecoderModule::kNeedAVCC)
, mLastError(NS_OK)
{
CreateDecoder();
}
H264Converter::~H264Converter()
{
}
nsresult
H264Converter::Init()
{
if (mDecoder) {
return mDecoder->Init();
}
return mLastError;
}
nsresult
H264Converter::Input(mp4_demuxer::MP4Sample* aSample)
{
if (!mNeedAVCC) {
if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
return NS_ERROR_FAILURE;
}
} else {
if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) {
return NS_ERROR_FAILURE;
}
}
nsresult rv;
if (!mDecoder) {
// It is not possible to create an AVCC H264 decoder without SPS.
// As such, creation will fail if the extra_data just extracted doesn't
// contain a SPS.
rv = CreateDecoderAndInit(aSample);
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required SPS to create the decoder.
// Ignore for the time being, the MP4Sample will be dropped.
return NS_OK;
}
} else {
rv = CheckForSPSChange(aSample);
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
return mDecoder->Input(aSample);
}
nsresult
H264Converter::Flush()
{
if (mDecoder) {
return mDecoder->Flush();
}
return mLastError;
}
nsresult
H264Converter::Drain()
{
if (mDecoder) {
return mDecoder->Drain();
}
return mLastError;
}
nsresult
H264Converter::Shutdown()
{
if (mDecoder) {
nsresult rv = mDecoder->Shutdown();
mDecoder = nullptr;
return rv;
}
return NS_OK;
}
bool
H264Converter::IsWaitingMediaResources()
{
if (mDecoder) {
return mDecoder->IsWaitingMediaResources();
}
return MediaDataDecoder::IsWaitingMediaResources();
}
bool
H264Converter::IsDormantNeeded()
{
if (mNeedAVCC) {
return true;
}
return mDecoder ?
mDecoder->IsDormantNeeded() : MediaDataDecoder::IsDormantNeeded();
}
void
H264Converter::AllocateMediaResources()
{
if (mNeedAVCC) {
// Nothing to do, decoder will be allocated on the fly when required.
return;
}
if (mDecoder) {
mDecoder->AllocateMediaResources();
}
}
void
H264Converter::ReleaseMediaResources()
{
if (mNeedAVCC) {
Shutdown();
return;
}
if (mDecoder) {
mDecoder->ReleaseMediaResources();
}
}
bool
H264Converter::IsHardwareAccelerated() const
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated();
}
return MediaDataDecoder::IsHardwareAccelerated();
}
nsresult
H264Converter::CreateDecoder()
{
if (mNeedAVCC && !mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.extra_data)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(mCurrentConfig.extra_data);
mDecoder = mPDM->CreateVideoDecoder(mCurrentConfig,
mLayersBackend,
mImageContainer,
mVideoTaskQueue,
mCallback);
if (!mDecoder) {
mLastError = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
H264Converter::CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(extra_data);
nsresult rv = CreateDecoder();
NS_ENSURE_SUCCESS(rv, rv);
return Init();
}
nsresult
H264Converter::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.extra_data)) {
return NS_OK;
}
if (!mNeedAVCC) {
UpdateConfigFromExtraData(extra_data);
mDecoder->ConfigurationChanged(mCurrentConfig);
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
mDecoder->Flush();
ReleaseMediaResources();
return CreateDecoderAndInit(aSample);
}
void
H264Converter::UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata) &&
spsdata.pic_width > 0 && spsdata.pic_height > 0) {
mp4_demuxer::H264::EnsureSPSIsSane(spsdata);
mCurrentConfig.image_width = spsdata.pic_width;
mCurrentConfig.image_height = spsdata.pic_height;
mCurrentConfig.display_width = spsdata.display_width;
mCurrentConfig.display_height = spsdata.display_height;
}
mCurrentConfig.extra_data = aExtraData;
}
/* static */
bool
H264Converter::IsH264(const mp4_demuxer::TrackConfig& aConfig)
{
return aConfig.mime_type.EqualsLiteral("video/avc") ||
aConfig.mime_type.EqualsLiteral("video/mp4");
}
} // namespace mozilla

View File

@ -0,0 +1,68 @@
/* -*- 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/. */
#ifndef mozilla_H264Converter_h
#define mozilla_H264Converter_h
#include "PlatformDecoderModule.h"
namespace mozilla {
// H264Converter is a MediaDataDecoder wrapper used to ensure that
// only AVCC or AnnexB is fed to the underlying MediaDataDecoder.
// The H264Converter allows playback of content where the SPS NAL may not be
// provided in the init segment (e.g. AVC3 or Annex B)
// H264Converter will monitor the input data, and will delay creation of the
// MediaDataDecoder until a SPS and PPS NALs have been extracted.
class H264Converter : public MediaDataDecoder {
public:
H264Converter(PlatformDecoderModule* aPDM,
const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableMediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback);
virtual ~H264Converter();
virtual nsresult Init() override;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override;
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsWaitingMediaResources() override;
virtual bool IsDormantNeeded() override;
virtual void AllocateMediaResources() override;
virtual void ReleaseMediaResources() override;
virtual bool IsHardwareAccelerated() const override;
// Return true if mimetype is H.264.
static bool IsH264(const mp4_demuxer::TrackConfig& aConfig);
private:
// Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
void UpdateConfigFromExtraData(mp4_demuxer::ByteBuffer* aExtraData);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;
layers::LayersBackend mLayersBackend;
nsRefPtr<layers::ImageContainer> mImageContainer;
nsRefPtr<FlushableMediaTaskQueue> mVideoTaskQueue;
MediaDataDecoderCallback* mCallback;
nsRefPtr<MediaDataDecoder> mDecoder;
bool mNeedAVCC;
nsresult mLastError;
};
} // namespace mozilla
#endif // mozilla_H264Converter_h

View File

@ -116,7 +116,7 @@ IntelWebMVideoDecoder::IsSupportedVideoMimeType(const nsACString& aMimeType)
{
return (aMimeType.EqualsLiteral("video/webm; codecs=vp8") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp9")) &&
mPlatform->SupportsVideoMimeType(aMimeType);
mPlatform->SupportsMimeType(aMimeType);
}
nsresult
@ -147,11 +147,12 @@ IntelWebMVideoDecoder::Init(unsigned int aWidth, unsigned int aHeight)
if (!IsSupportedVideoMimeType(video.mime_type)) {
return NS_ERROR_FAILURE;
}
mMediaDataDecoder = mPlatform->CreateVideoDecoder(video,
mReader->GetLayersBackendType(),
mReader->GetDecoder()->GetImageContainer(),
mTaskQueue,
this);
mMediaDataDecoder =
mPlatform->CreateDecoder(video,
mTaskQueue,
this,
mReader->GetLayersBackendType(),
mReader->GetDecoder()->GetImageContainer());
if (!mMediaDataDecoder) {
return NS_ERROR_FAILURE;
}

View File

@ -91,13 +91,34 @@ public:
class TrackConfig
{
public:
TrackConfig() : mTrackId(0), duration(0), media_time(0) {}
enum TrackType {
kUndefinedTrack,
kAudioTrack,
kVideoTrack,
};
explicit TrackConfig(TrackType aType)
: mTrackId(0)
, duration(0)
, media_time(0)
, mType(aType)
{
}
nsAutoCString mime_type;
uint32_t mTrackId;
int64_t duration;
int64_t media_time;
CryptoTrack crypto;
TrackType mType;
bool IsAudioConfig() const
{
return mType == kAudioTrack;
}
bool IsVideoConfig() const
{
return mType == kVideoTrack;
}
void Update(stagefright::sp<stagefright::MetaData>& aMetaData,
const char* aMimeType);
};
@ -106,7 +127,8 @@ class AudioDecoderConfig : public TrackConfig
{
public:
AudioDecoderConfig()
: channel_count(0)
: TrackConfig(kAudioTrack)
, channel_count(0)
, bits_per_sample(0)
, samples_per_second(0)
, frequency_index(0)
@ -138,7 +160,8 @@ class VideoDecoderConfig : public TrackConfig
{
public:
VideoDecoderConfig()
: display_width(0)
: TrackConfig(kVideoTrack)
, display_width(0)
, display_height(0)
, image_width(0)
, image_height(0)