Bug 1319987: P7. Re-implement handling for WaitingForKey in MFR. r=cpearce,gerald

MozReview-Commit-ID: FCiAO54oiH3

--HG--
extra : rebase_source : 898e175742ae4db13c48cf75463a9775968b0030
This commit is contained in:
Jean-Yves Avenard 2017-01-27 11:48:00 +01:00
Родитель 5e2e07649c
Коммит e2abc1a523
9 изменённых файлов: 116 добавлений и 24 удалений

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

@ -243,6 +243,18 @@ public:
return mOnMediaNotSeekable; return mOnMediaNotSeekable;
} }
// Notified if the reader can't decode a sample due to a missing decryption
// key.
MediaEventSource<TrackInfo::TrackType>& OnTrackWaitingForKey()
{
return mOnTrackWaitingForKey;
}
MediaEventProducer<TrackInfo::TrackType>& OnTrackWaitingForKeyProducer()
{
return mOnTrackWaitingForKey;
}
// Switch the video decoder to BlankDecoderModule. It might takes effective // Switch the video decoder to BlankDecoderModule. It might takes effective
// since a few samples later depends on how much demuxed samples are already // since a few samples later depends on how much demuxed samples are already
// queued in the original video decoder. // queued in the original video decoder.
@ -306,6 +318,9 @@ protected:
// Notify if this media is not seekable. // Notify if this media is not seekable.
MediaEventProducer<void> mOnMediaNotSeekable; MediaEventProducer<void> mOnMediaNotSeekable;
// Notify if we are waiting for a decryption key.
MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
private: private:
virtual nsresult InitInternal() { return NS_OK; } virtual nsresult InitInternal() { return NS_OK; }

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

@ -389,7 +389,9 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
ownerData.mTaskQueue, ownerData.mTaskQueue,
mOwner->mCrashHelper, mOwner->mCrashHelper,
ownerData.mIsBlankDecode, ownerData.mIsBlankDecode,
&result &result,
aTrack,
&mOwner->OnTrackWaitingForKeyProducer()
}); });
break; break;
} }
@ -406,7 +408,9 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
mOwner->GetImageContainer(), mOwner->GetImageContainer(),
mOwner->mCrashHelper, mOwner->mCrashHelper,
ownerData.mIsBlankDecode, ownerData.mIsBlankDecode,
&result &result,
aTrack,
&mOwner->OnTrackWaitingForKeyProducer()
}); });
break; break;
} }
@ -847,6 +851,8 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
aDecoder->CompositorUpdatedEvent()->Connect( aDecoder->CompositorUpdatedEvent()->Connect(
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated); mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
} }
mOnTrackWaitingForKeyListener = OnTrackWaitingForKey().Connect(
mTaskQueue, this, &MediaFormatReader::NotifyWaitingForKey);
} }
MediaFormatReader::~MediaFormatReader() MediaFormatReader::~MediaFormatReader()
@ -895,6 +901,7 @@ MediaFormatReader::Shutdown()
mDemuxer = nullptr; mDemuxer = nullptr;
mCompositorUpdatedListener.DisconnectIfExists(); mCompositorUpdatedListener.DisconnectIfExists();
mOnTrackWaitingForKeyListener.Disconnect();
RefPtr<ShutdownPromise> p = mShutdownPromise.Ensure(__func__); RefPtr<ShutdownPromise> p = mShutdownPromise.Ensure(__func__);
ShutdownPromise::All(OwnerThread(), promises) ShutdownPromise::All(OwnerThread(), promises)
@ -1523,6 +1530,21 @@ MediaFormatReader::NotifyWaitingForData(TrackType aTrack)
ScheduleUpdate(aTrack); ScheduleUpdate(aTrack);
} }
void
MediaFormatReader::NotifyWaitingForKey(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
if (mDecoder) {
mDecoder->NotifyWaitingForKey();
}
if (!decoder.mDecodeRequest.Exists()) {
LOGV("WaitingForKey received while no pending decode. Ignoring");
}
decoder.mWaitingForKey = true;
ScheduleUpdate(aTrack);
}
void void
MediaFormatReader::NotifyEndOfStream(TrackType aTrack) MediaFormatReader::NotifyEndOfStream(TrackType aTrack)
{ {
@ -2013,6 +2035,10 @@ MediaFormatReader::Update(TrackType aTrack)
// EOS state. We can immediately reject the data promise. // EOS state. We can immediately reject the data promise.
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack)); LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__); decoder.RejectPromise(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
} else if (decoder.mWaitingForKey) {
LOG("Rejecting %s promise: WAITING_FOR_DATA due to waiting for key",
TrackTypeToStr(aTrack));
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, __func__);
} }
} }
@ -2054,13 +2080,23 @@ MediaFormatReader::Update(TrackType aTrack)
decoder.mWaitingForData, decoder.HasPromise(), decoder.mWaitingForData, decoder.HasPromise(),
decoder.mLastStreamSourceID); decoder.mLastStreamSourceID);
if ((decoder.mWaitingForData && if ((decoder.mWaitingForData
(!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting))) { && (!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting))
|| (decoder.mWaitingForKey && decoder.mDecodeRequest.Exists())) {
// Nothing more we can do at present. // Nothing more we can do at present.
LOGV("Still waiting for data or key."); LOGV("Still waiting for data or key.");
return; return;
} }
if (decoder.mWaitingForKey) {
decoder.mWaitingForKey = false;
if (decoder.HasWaitingPromise() && !decoder.IsWaiting()) {
LOGV("No longer waiting for key. Resolving waiting promise");
decoder.mWaitingPromise.Resolve(decoder.mType, __func__);
return;
}
}
if (!needInput) { if (!needInput) {
LOGV("No need for additional input (pending:%u)", LOGV("No need for additional input (pending:%u)",
uint32_t(decoder.mOutput.Length())); uint32_t(decoder.mOutput.Length()));

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

@ -141,6 +141,7 @@ private:
void NotifyDrainComplete(TrackType aTrack); void NotifyDrainComplete(TrackType aTrack);
void NotifyError(TrackType aTrack, const MediaResult& aError); void NotifyError(TrackType aTrack, const MediaResult& aError);
void NotifyWaitingForData(TrackType aTrack); void NotifyWaitingForData(TrackType aTrack);
void NotifyWaitingForKey(TrackType aTrack);
void NotifyEndOfStream(TrackType aTrack); void NotifyEndOfStream(TrackType aTrack);
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData); void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
@ -170,6 +171,7 @@ private:
, mUpdateScheduled(false) , mUpdateScheduled(false)
, mDemuxEOS(false) , mDemuxEOS(false)
, mWaitingForData(false) , mWaitingForData(false)
, mWaitingForKey(false)
, mReceivedNewData(false) , mReceivedNewData(false)
, mNeedDraining(false) , mNeedDraining(false)
, mDraining(false) , mDraining(false)
@ -226,6 +228,7 @@ private:
bool mUpdateScheduled; bool mUpdateScheduled;
bool mDemuxEOS; bool mDemuxEOS;
bool mWaitingForData; bool mWaitingForData;
bool mWaitingForKey;
bool mReceivedNewData; bool mReceivedNewData;
// Pending seek. // Pending seek.
@ -245,7 +248,7 @@ private:
bool IsWaiting() const bool IsWaiting() const
{ {
MOZ_ASSERT(mOwner->OnTaskQueue()); MOZ_ASSERT(mOwner->OnTaskQueue());
return mWaitingForData; return mWaitingForData || mWaitingForKey;
} }
// MediaDataDecoder handler's variables. // MediaDataDecoder handler's variables.
@ -373,6 +376,7 @@ private:
MOZ_ASSERT(mOwner->OnTaskQueue()); MOZ_ASSERT(mOwner->OnTaskQueue());
mDemuxEOS = false; mDemuxEOS = false;
mWaitingForData = false; mWaitingForData = false;
mWaitingForKey = false;
mQueuedSamples.Clear(); mQueuedSamples.Clear();
mNeedDraining = false; mNeedDraining = false;
mDecodeRequest.DisconnectIfExists(); mDecodeRequest.DisconnectIfExists();
@ -560,6 +564,7 @@ private:
UniquePtr<DecoderFactory> mDecoderFactory; UniquePtr<DecoderFactory> mDecoderFactory;
MediaEventListener mCompositorUpdatedListener; MediaEventListener mCompositorUpdatedListener;
MediaEventListener mOnTrackWaitingForKeyListener;
void OnFirstDemuxCompleted(TrackInfo::TrackType aType, void OnFirstDemuxCompleted(TrackInfo::TrackType aType,
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples); RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);

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

@ -81,6 +81,8 @@ struct MOZ_STACK_CLASS CreateDecoderParams final
RefPtr<layers::KnowsCompositor> mKnowsCompositor; RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<GMPCrashHelper> mCrashHelper; RefPtr<GMPCrashHelper> mCrashHelper;
bool mUseBlankDecoder = false; bool mUseBlankDecoder = false;
TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
private: private:
void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; } void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
@ -99,6 +101,14 @@ private:
{ {
mKnowsCompositor = aKnowsCompositor; mKnowsCompositor = aKnowsCompositor;
} }
void Set(TrackInfo::TrackType aType)
{
mType = aType;
}
void Set(MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
{
mOnWaitingForKeyEvent = aOnWaitingForKey;
}
template <typename T1, typename T2, typename... Ts> template <typename T1, typename T2, typename... Ts>
void Set(T1&& a1, T2&& a2, Ts&&... args) void Set(T1&& a1, T2&& a2, Ts&&... args)
{ {

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

@ -27,13 +27,14 @@ extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
class EMEDecryptor : public MediaDataDecoder class EMEDecryptor : public MediaDataDecoder
{ {
public: public:
EMEDecryptor(MediaDataDecoder* aDecoder, EMEDecryptor(MediaDataDecoder* aDecoder, CDMProxy* aProxy,
CDMProxy* aProxy, TaskQueue* aDecodeTaskQueue, TrackInfo::TrackType aType,
TaskQueue* aDecodeTaskQueue) MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
: mDecoder(aDecoder) : mDecoder(aDecoder)
, mTaskQueue(aDecodeTaskQueue) , mTaskQueue(aDecodeTaskQueue)
, mProxy(aProxy) , mProxy(aProxy)
, mSamplesWaitingForKey(new SamplesWaitingForKey(mProxy)) , mSamplesWaitingForKey(
new SamplesWaitingForKey(mProxy, aType, aOnWaitingForKey))
, mIsShutdown(false) , mIsShutdown(false)
{ {
} }
@ -204,12 +205,15 @@ private:
class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy
{ {
public: public:
EMEMediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread, EMEMediaDataDecoderProxy(
CDMProxy* aProxy) already_AddRefed<AbstractThread> aProxyThread, CDMProxy* aProxy,
: MediaDataDecoderProxy(Move(aProxyThread)) TrackInfo::TrackType aType,
, mTaskQueue(AbstractThread::GetCurrent()->AsTaskQueue()) MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
, mSamplesWaitingForKey(new SamplesWaitingForKey(aProxy)) : MediaDataDecoderProxy(Move(aProxyThread))
, mProxy(aProxy) , mTaskQueue(AbstractThread::GetCurrent()->AsTaskQueue())
, mSamplesWaitingForKey(
new SamplesWaitingForKey(aProxy, aType, aOnWaitingForKey))
, mProxy(aProxy)
{ {
} }
@ -289,7 +293,7 @@ EMEDecoderModule::~EMEDecoderModule()
} }
static already_AddRefed<MediaDataDecoderProxy> static already_AddRefed<MediaDataDecoderProxy>
CreateDecoderWrapper(CDMProxy* aProxy) CreateDecoderWrapper(CDMProxy* aProxy, const CreateDecoderParams& aParams)
{ {
RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService());
if (!s) { if (!s) {
@ -299,8 +303,8 @@ CreateDecoderWrapper(CDMProxy* aProxy)
if (!thread) { if (!thread) {
return nullptr; return nullptr;
} }
RefPtr<MediaDataDecoderProxy> decoder( RefPtr<MediaDataDecoderProxy> decoder(new EMEMediaDataDecoderProxy(
new EMEMediaDataDecoderProxy(thread.forget(), aProxy)); thread.forget(), aProxy, aParams.mType, aParams.mOnWaitingForKeyEvent));
return decoder.forget(); return decoder.forget();
} }
@ -317,7 +321,8 @@ EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) { if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) {
// GMP decodes. Assume that means it can decrypt too. // GMP decodes. Assume that means it can decrypt too.
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(mProxy); RefPtr<MediaDataDecoderProxy> wrapper =
CreateDecoderWrapper(mProxy, aParams);
auto params = GMPVideoDecoderParams(aParams); auto params = GMPVideoDecoderParams(aParams);
wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, params)); wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, params));
return wrapper.forget(); return wrapper.forget();
@ -330,7 +335,8 @@ EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
} }
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor( RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue())); decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue(),
aParams.mType, aParams.mOnWaitingForKeyEvent));
return emeDecoder.forget(); return emeDecoder.forget();
} }
@ -355,7 +361,8 @@ EMEDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
} }
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor( RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue())); decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue(),
aParams.mType, aParams.mOnWaitingForKeyEvent));
return emeDecoder.forget(); return emeDecoder.forget();
} }

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

@ -8,13 +8,18 @@
#include "mozilla/CDMCaps.h" #include "mozilla/CDMCaps.h"
#include "mozilla/TaskQueue.h" #include "mozilla/TaskQueue.h"
#include "MediaData.h" #include "MediaData.h"
#include "MediaEventSource.h"
#include "SamplesWaitingForKey.h" #include "SamplesWaitingForKey.h"
namespace mozilla { namespace mozilla {
SamplesWaitingForKey::SamplesWaitingForKey(CDMProxy* aProxy) SamplesWaitingForKey::SamplesWaitingForKey(
CDMProxy* aProxy, TrackInfo::TrackType aType,
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
: mMutex("SamplesWaitingForKey") : mMutex("SamplesWaitingForKey")
, mProxy(aProxy) , mProxy(aProxy)
, mType(aType)
, mOnWaitingForKeyEvent(aOnWaitingForKey)
{ {
} }
@ -41,6 +46,9 @@ SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample)
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
mSamples.AppendElement(Move(entry)); mSamples.AppendElement(Move(entry));
} }
if (mOnWaitingForKeyEvent) {
mOnWaitingForKeyEvent->Notify(mType);
}
caps.NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this); caps.NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this);
return p; return p;
} }

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

@ -10,12 +10,14 @@
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "MediaInfo.h"
namespace mozilla { namespace mozilla {
typedef nsTArray<uint8_t> CencKeyId; typedef nsTArray<uint8_t> CencKeyId;
class CDMProxy; class CDMProxy;
template <typename... Es> class MediaEventProducer;
class MediaRawData; class MediaRawData;
// Encapsulates the task of waiting for the CDMProxy to have the necessary // Encapsulates the task of waiting for the CDMProxy to have the necessary
@ -28,7 +30,8 @@ public:
typedef MozPromise<RefPtr<MediaRawData>, bool, /* IsExclusive = */ true> typedef MozPromise<RefPtr<MediaRawData>, bool, /* IsExclusive = */ true>
WaitForKeyPromise; WaitForKeyPromise;
explicit SamplesWaitingForKey(CDMProxy* aProxy); SamplesWaitingForKey(CDMProxy* aProxy, TrackInfo::TrackType aType,
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey);
// Returns a promise that will be resolved if or when a key for decoding the // Returns a promise that will be resolved if or when a key for decoding the
// sample becomes usable. // sample becomes usable.
@ -50,6 +53,8 @@ private:
MozPromiseHolder<WaitForKeyPromise> mPromise; MozPromiseHolder<WaitForKeyPromise> mPromise;
}; };
nsTArray<SampleEntry> mSamples; nsTArray<SampleEntry> mSamples;
const TrackInfo::TrackType mType;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
}; };
} // namespace mozilla } // namespace mozilla

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

@ -28,6 +28,8 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM,
, mNeedAVCC(aPDM->DecoderNeedsConversion(aParams.mConfig) , mNeedAVCC(aPDM->DecoderNeedsConversion(aParams.mConfig)
== PlatformDecoderModule::ConversionRequired::kNeedAVCC) == PlatformDecoderModule::ConversionRequired::kNeedAVCC)
, mLastError(NS_OK) , mLastError(NS_OK)
, mType(aParams.mType)
, mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent)
{ {
CreateDecoder(aParams.mDiagnostics); CreateDecoder(aParams.mDiagnostics);
} }
@ -194,7 +196,9 @@ H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics)
aDiagnostics, aDiagnostics,
mImageContainer, mImageContainer,
mKnowsCompositor, mKnowsCompositor,
mGMPCrashHelper mGMPCrashHelper,
mType,
mOnWaitingForKeyEvent
}); });
if (!mDecoder) { if (!mDecoder) {

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

@ -76,6 +76,8 @@ private:
bool mNeedAVCC; bool mNeedAVCC;
nsresult mLastError; nsresult mLastError;
bool mNeedKeyframe = true; bool mNeedKeyframe = true;
const TrackInfo::TrackType mType;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
}; };
} // namespace mozilla } // namespace mozilla