зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5e2e07649c
Коммит
e2abc1a523
|
@ -243,6 +243,18 @@ public:
|
|||
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
|
||||
// since a few samples later depends on how much demuxed samples are already
|
||||
// queued in the original video decoder.
|
||||
|
@ -306,6 +318,9 @@ protected:
|
|||
// Notify if this media is not seekable.
|
||||
MediaEventProducer<void> mOnMediaNotSeekable;
|
||||
|
||||
// Notify if we are waiting for a decryption key.
|
||||
MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
|
||||
|
||||
private:
|
||||
virtual nsresult InitInternal() { return NS_OK; }
|
||||
|
||||
|
|
|
@ -389,7 +389,9 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
|
|||
ownerData.mTaskQueue,
|
||||
mOwner->mCrashHelper,
|
||||
ownerData.mIsBlankDecode,
|
||||
&result
|
||||
&result,
|
||||
aTrack,
|
||||
&mOwner->OnTrackWaitingForKeyProducer()
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -406,7 +408,9 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
|
|||
mOwner->GetImageContainer(),
|
||||
mOwner->mCrashHelper,
|
||||
ownerData.mIsBlankDecode,
|
||||
&result
|
||||
&result,
|
||||
aTrack,
|
||||
&mOwner->OnTrackWaitingForKeyProducer()
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -847,6 +851,8 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
|
|||
aDecoder->CompositorUpdatedEvent()->Connect(
|
||||
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
|
||||
}
|
||||
mOnTrackWaitingForKeyListener = OnTrackWaitingForKey().Connect(
|
||||
mTaskQueue, this, &MediaFormatReader::NotifyWaitingForKey);
|
||||
}
|
||||
|
||||
MediaFormatReader::~MediaFormatReader()
|
||||
|
@ -895,6 +901,7 @@ MediaFormatReader::Shutdown()
|
|||
mDemuxer = nullptr;
|
||||
|
||||
mCompositorUpdatedListener.DisconnectIfExists();
|
||||
mOnTrackWaitingForKeyListener.Disconnect();
|
||||
|
||||
RefPtr<ShutdownPromise> p = mShutdownPromise.Ensure(__func__);
|
||||
ShutdownPromise::All(OwnerThread(), promises)
|
||||
|
@ -1523,6 +1530,21 @@ MediaFormatReader::NotifyWaitingForData(TrackType 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
|
||||
MediaFormatReader::NotifyEndOfStream(TrackType aTrack)
|
||||
{
|
||||
|
@ -2013,6 +2035,10 @@ MediaFormatReader::Update(TrackType aTrack)
|
|||
// EOS state. We can immediately reject the data promise.
|
||||
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
|
||||
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.mLastStreamSourceID);
|
||||
|
||||
if ((decoder.mWaitingForData &&
|
||||
(!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting))) {
|
||||
if ((decoder.mWaitingForData
|
||||
&& (!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting))
|
||||
|| (decoder.mWaitingForKey && decoder.mDecodeRequest.Exists())) {
|
||||
// Nothing more we can do at present.
|
||||
LOGV("Still waiting for data or key.");
|
||||
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) {
|
||||
LOGV("No need for additional input (pending:%u)",
|
||||
uint32_t(decoder.mOutput.Length()));
|
||||
|
|
|
@ -141,6 +141,7 @@ private:
|
|||
void NotifyDrainComplete(TrackType aTrack);
|
||||
void NotifyError(TrackType aTrack, const MediaResult& aError);
|
||||
void NotifyWaitingForData(TrackType aTrack);
|
||||
void NotifyWaitingForKey(TrackType aTrack);
|
||||
void NotifyEndOfStream(TrackType aTrack);
|
||||
|
||||
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
|
||||
|
@ -170,6 +171,7 @@ private:
|
|||
, mUpdateScheduled(false)
|
||||
, mDemuxEOS(false)
|
||||
, mWaitingForData(false)
|
||||
, mWaitingForKey(false)
|
||||
, mReceivedNewData(false)
|
||||
, mNeedDraining(false)
|
||||
, mDraining(false)
|
||||
|
@ -226,6 +228,7 @@ private:
|
|||
bool mUpdateScheduled;
|
||||
bool mDemuxEOS;
|
||||
bool mWaitingForData;
|
||||
bool mWaitingForKey;
|
||||
bool mReceivedNewData;
|
||||
|
||||
// Pending seek.
|
||||
|
@ -245,7 +248,7 @@ private:
|
|||
bool IsWaiting() const
|
||||
{
|
||||
MOZ_ASSERT(mOwner->OnTaskQueue());
|
||||
return mWaitingForData;
|
||||
return mWaitingForData || mWaitingForKey;
|
||||
}
|
||||
|
||||
// MediaDataDecoder handler's variables.
|
||||
|
@ -373,6 +376,7 @@ private:
|
|||
MOZ_ASSERT(mOwner->OnTaskQueue());
|
||||
mDemuxEOS = false;
|
||||
mWaitingForData = false;
|
||||
mWaitingForKey = false;
|
||||
mQueuedSamples.Clear();
|
||||
mNeedDraining = false;
|
||||
mDecodeRequest.DisconnectIfExists();
|
||||
|
@ -560,6 +564,7 @@ private:
|
|||
UniquePtr<DecoderFactory> mDecoderFactory;
|
||||
|
||||
MediaEventListener mCompositorUpdatedListener;
|
||||
MediaEventListener mOnTrackWaitingForKeyListener;
|
||||
|
||||
void OnFirstDemuxCompleted(TrackInfo::TrackType aType,
|
||||
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
|
||||
|
|
|
@ -81,6 +81,8 @@ struct MOZ_STACK_CLASS CreateDecoderParams final
|
|||
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
|
||||
RefPtr<GMPCrashHelper> mCrashHelper;
|
||||
bool mUseBlankDecoder = false;
|
||||
TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
|
||||
MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
|
||||
|
||||
private:
|
||||
void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
|
||||
|
@ -99,6 +101,14 @@ private:
|
|||
{
|
||||
mKnowsCompositor = aKnowsCompositor;
|
||||
}
|
||||
void Set(TrackInfo::TrackType aType)
|
||||
{
|
||||
mType = aType;
|
||||
}
|
||||
void Set(MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
|
||||
{
|
||||
mOnWaitingForKeyEvent = aOnWaitingForKey;
|
||||
}
|
||||
template <typename T1, typename T2, typename... Ts>
|
||||
void Set(T1&& a1, T2&& a2, Ts&&... args)
|
||||
{
|
||||
|
|
|
@ -27,13 +27,14 @@ extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
|
|||
class EMEDecryptor : public MediaDataDecoder
|
||||
{
|
||||
public:
|
||||
EMEDecryptor(MediaDataDecoder* aDecoder,
|
||||
CDMProxy* aProxy,
|
||||
TaskQueue* aDecodeTaskQueue)
|
||||
EMEDecryptor(MediaDataDecoder* aDecoder, CDMProxy* aProxy,
|
||||
TaskQueue* aDecodeTaskQueue, TrackInfo::TrackType aType,
|
||||
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
|
||||
: mDecoder(aDecoder)
|
||||
, mTaskQueue(aDecodeTaskQueue)
|
||||
, mProxy(aProxy)
|
||||
, mSamplesWaitingForKey(new SamplesWaitingForKey(mProxy))
|
||||
, mSamplesWaitingForKey(
|
||||
new SamplesWaitingForKey(mProxy, aType, aOnWaitingForKey))
|
||||
, mIsShutdown(false)
|
||||
{
|
||||
}
|
||||
|
@ -204,12 +205,15 @@ private:
|
|||
class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy
|
||||
{
|
||||
public:
|
||||
EMEMediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread,
|
||||
CDMProxy* aProxy)
|
||||
: MediaDataDecoderProxy(Move(aProxyThread))
|
||||
, mTaskQueue(AbstractThread::GetCurrent()->AsTaskQueue())
|
||||
, mSamplesWaitingForKey(new SamplesWaitingForKey(aProxy))
|
||||
, mProxy(aProxy)
|
||||
EMEMediaDataDecoderProxy(
|
||||
already_AddRefed<AbstractThread> aProxyThread, CDMProxy* aProxy,
|
||||
TrackInfo::TrackType aType,
|
||||
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
|
||||
: MediaDataDecoderProxy(Move(aProxyThread))
|
||||
, mTaskQueue(AbstractThread::GetCurrent()->AsTaskQueue())
|
||||
, mSamplesWaitingForKey(
|
||||
new SamplesWaitingForKey(aProxy, aType, aOnWaitingForKey))
|
||||
, mProxy(aProxy)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -289,7 +293,7 @@ EMEDecoderModule::~EMEDecoderModule()
|
|||
}
|
||||
|
||||
static already_AddRefed<MediaDataDecoderProxy>
|
||||
CreateDecoderWrapper(CDMProxy* aProxy)
|
||||
CreateDecoderWrapper(CDMProxy* aProxy, const CreateDecoderParams& aParams)
|
||||
{
|
||||
RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService());
|
||||
if (!s) {
|
||||
|
@ -299,8 +303,8 @@ CreateDecoderWrapper(CDMProxy* aProxy)
|
|||
if (!thread) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<MediaDataDecoderProxy> decoder(
|
||||
new EMEMediaDataDecoderProxy(thread.forget(), aProxy));
|
||||
RefPtr<MediaDataDecoderProxy> decoder(new EMEMediaDataDecoderProxy(
|
||||
thread.forget(), aProxy, aParams.mType, aParams.mOnWaitingForKeyEvent));
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
|
@ -317,7 +321,8 @@ EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
|||
|
||||
if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) {
|
||||
// GMP decodes. Assume that means it can decrypt too.
|
||||
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(mProxy);
|
||||
RefPtr<MediaDataDecoderProxy> wrapper =
|
||||
CreateDecoderWrapper(mProxy, aParams);
|
||||
auto params = GMPVideoDecoderParams(aParams);
|
||||
wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, params));
|
||||
return wrapper.forget();
|
||||
|
@ -330,7 +335,8 @@ EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
|||
}
|
||||
|
||||
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
|
||||
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue()));
|
||||
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue(),
|
||||
aParams.mType, aParams.mOnWaitingForKeyEvent));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
|
||||
|
@ -355,7 +361,8 @@ EMEDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
|
|||
}
|
||||
|
||||
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
|
||||
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue()));
|
||||
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue(),
|
||||
aParams.mType, aParams.mOnWaitingForKeyEvent));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,18 @@
|
|||
#include "mozilla/CDMCaps.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaEventSource.h"
|
||||
#include "SamplesWaitingForKey.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
SamplesWaitingForKey::SamplesWaitingForKey(CDMProxy* aProxy)
|
||||
SamplesWaitingForKey::SamplesWaitingForKey(
|
||||
CDMProxy* aProxy, TrackInfo::TrackType aType,
|
||||
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
|
||||
: mMutex("SamplesWaitingForKey")
|
||||
, mProxy(aProxy)
|
||||
, mType(aType)
|
||||
, mOnWaitingForKeyEvent(aOnWaitingForKey)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,6 +46,9 @@ SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample)
|
|||
MutexAutoLock lock(mMutex);
|
||||
mSamples.AppendElement(Move(entry));
|
||||
}
|
||||
if (mOnWaitingForKeyEvent) {
|
||||
mOnWaitingForKeyEvent->Notify(mType);
|
||||
}
|
||||
caps.NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this);
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,14 @@
|
|||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "MediaInfo.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef nsTArray<uint8_t> CencKeyId;
|
||||
|
||||
class CDMProxy;
|
||||
template <typename... Es> class MediaEventProducer;
|
||||
class MediaRawData;
|
||||
|
||||
// Encapsulates the task of waiting for the CDMProxy to have the necessary
|
||||
|
@ -28,7 +30,8 @@ public:
|
|||
typedef MozPromise<RefPtr<MediaRawData>, bool, /* IsExclusive = */ true>
|
||||
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
|
||||
// sample becomes usable.
|
||||
|
@ -50,6 +53,8 @@ private:
|
|||
MozPromiseHolder<WaitForKeyPromise> mPromise;
|
||||
};
|
||||
nsTArray<SampleEntry> mSamples;
|
||||
const TrackInfo::TrackType mType;
|
||||
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -28,6 +28,8 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM,
|
|||
, mNeedAVCC(aPDM->DecoderNeedsConversion(aParams.mConfig)
|
||||
== PlatformDecoderModule::ConversionRequired::kNeedAVCC)
|
||||
, mLastError(NS_OK)
|
||||
, mType(aParams.mType)
|
||||
, mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent)
|
||||
{
|
||||
CreateDecoder(aParams.mDiagnostics);
|
||||
}
|
||||
|
@ -194,7 +196,9 @@ H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics)
|
|||
aDiagnostics,
|
||||
mImageContainer,
|
||||
mKnowsCompositor,
|
||||
mGMPCrashHelper
|
||||
mGMPCrashHelper,
|
||||
mType,
|
||||
mOnWaitingForKeyEvent
|
||||
});
|
||||
|
||||
if (!mDecoder) {
|
||||
|
|
|
@ -76,6 +76,8 @@ private:
|
|||
bool mNeedAVCC;
|
||||
nsresult mLastError;
|
||||
bool mNeedKeyframe = true;
|
||||
const TrackInfo::TrackType mType;
|
||||
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче