зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1144409 - Encrypted event should be fired once per initData. r=cpearce
This commit is contained in:
Родитель
73191bb9d0
Коммит
9c87262f4f
|
@ -694,6 +694,10 @@ void HTMLMediaElement::AbortExistingLoads()
|
|||
mSuspendedForPreloadNone = false;
|
||||
mDownloadSuspendedByCache = false;
|
||||
mMediaInfo = MediaInfo();
|
||||
mIsEncrypted = false;
|
||||
#ifdef MOZ_EME
|
||||
mPendingEncryptedInitData.mInitDatas.Clear();
|
||||
#endif // MOZ_EME
|
||||
mSourcePointer = nullptr;
|
||||
mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
|
||||
|
||||
|
@ -3088,7 +3092,11 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||
nsAutoPtr<const MetadataTags> aTags)
|
||||
{
|
||||
mMediaInfo = *aInfo;
|
||||
mIsEncrypted = aInfo->IsEncrypted();
|
||||
mIsEncrypted = aInfo->IsEncrypted()
|
||||
#ifdef MOZ_EME
|
||||
|| mPendingEncryptedInitData.IsEncrypted()
|
||||
#endif // MOZ_EME
|
||||
;
|
||||
mTags = aTags.forget();
|
||||
mLoadedDataFired = false;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
|
@ -3115,8 +3123,12 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
DispatchEncrypted(aInfo->mCrypto.mInitData, aInfo->mCrypto.mType);
|
||||
#endif
|
||||
// Dispatch a distinct 'encrypted' event for each initData we have.
|
||||
for (const auto& initData : mPendingEncryptedInitData.mInitDatas) {
|
||||
DispatchEncrypted(initData.mInitData, initData.mType);
|
||||
}
|
||||
mPendingEncryptedInitData.mInitDatas.Clear();
|
||||
#endif // MOZ_EME
|
||||
}
|
||||
|
||||
// Expose the tracks to JS directly.
|
||||
|
@ -4479,6 +4491,13 @@ void
|
|||
HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType)
|
||||
{
|
||||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
// Ready state not HAVE_METADATA (yet), don't dispatch encrypted now.
|
||||
// Queueing for later dispatch in MetadataLoaded.
|
||||
mPendingEncryptedInitData.AddInitData(aInitDataType, aInitData);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaEncryptedEvent> event;
|
||||
if (IsCORSSameOrigin()) {
|
||||
event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData);
|
||||
|
|
|
@ -561,7 +561,6 @@ public:
|
|||
void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType) override;
|
||||
|
||||
|
||||
bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
|
||||
// Returns the principal of the "top level" document; the origin displayed
|
||||
|
@ -1322,6 +1321,11 @@ protected:
|
|||
// True if the media has encryption information.
|
||||
bool mIsEncrypted;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
// Init Data that needs to be sent in 'encrypted' events in MetadataLoaded().
|
||||
EncryptionInfo mPendingEncryptedInitData;
|
||||
#endif // MOZ_EME
|
||||
|
||||
// True if the media's channel's download has been suspended.
|
||||
bool mDownloadSuspendedByCache;
|
||||
|
||||
|
|
|
@ -136,11 +136,11 @@ public:
|
|||
|
||||
#ifdef MOZ_EME
|
||||
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
|
||||
// provided init data.
|
||||
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
|
||||
// Main thread only.
|
||||
virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
|
||||
const nsAString& aInitDataType) = 0;
|
||||
#endif
|
||||
#endif // MOZ_EME
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -105,16 +105,41 @@ public:
|
|||
|
||||
class EncryptionInfo {
|
||||
public:
|
||||
EncryptionInfo() : mIsEncrypted(false) {}
|
||||
struct InitData {
|
||||
template<typename AInitDatas>
|
||||
InitData(const nsAString& aType, AInitDatas&& aInitData)
|
||||
: mType(aType)
|
||||
, mInitData(Forward<AInitDatas>(aInitData))
|
||||
{
|
||||
}
|
||||
|
||||
// Encryption type to be passed to JS. Usually `cenc'.
|
||||
nsString mType;
|
||||
// Encryption type to be passed to JS. Usually `cenc'.
|
||||
nsString mType;
|
||||
|
||||
// Encryption data.
|
||||
nsTArray<uint8_t> mInitData;
|
||||
// Encryption data.
|
||||
nsTArray<uint8_t> mInitData;
|
||||
};
|
||||
typedef nsTArray<InitData> InitDatas;
|
||||
|
||||
// True if the stream has encryption metadata
|
||||
bool mIsEncrypted;
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
return !mInitDatas.IsEmpty();
|
||||
}
|
||||
|
||||
template<typename AInitDatas>
|
||||
void AddInitData(const nsAString& aType, AInitDatas&& aInitData)
|
||||
{
|
||||
mInitDatas.AppendElement(InitData(aType, Forward<AInitDatas>(aInitData)));
|
||||
}
|
||||
|
||||
void AddInitData(const EncryptionInfo& aInfo)
|
||||
{
|
||||
mInitDatas.AppendElements(aInfo.mInitDatas);
|
||||
}
|
||||
|
||||
// One 'InitData' per encrypted buffer.
|
||||
InitDatas mInitDatas;
|
||||
};
|
||||
|
||||
class MediaInfo {
|
||||
|
@ -131,7 +156,7 @@ public:
|
|||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
return mCrypto.mIsEncrypted;
|
||||
return mCrypto.IsEncrypted();
|
||||
}
|
||||
|
||||
bool HasValidMedia() const
|
||||
|
|
|
@ -264,6 +264,34 @@ MP4Reader::Init(MediaDecoderReader* aCloneDonor)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
class DispatchKeyNeededEvent : public nsRunnable {
|
||||
public:
|
||||
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
|
||||
nsTArray<uint8_t>& aInitData,
|
||||
const nsString& aInitDataType)
|
||||
: mDecoder(aDecoder)
|
||||
, mInitData(aInitData)
|
||||
, mInitDataType(aInitDataType)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run() {
|
||||
// Note: Null check the owner, as the decoder could have been shutdown
|
||||
// since this event was dispatched.
|
||||
MediaDecoderOwner* owner = mDecoder->GetOwner();
|
||||
if (owner) {
|
||||
owner->DispatchEncrypted(mInitData, mInitDataType);
|
||||
}
|
||||
mDecoder = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
nsTArray<uint8_t> mInitData;
|
||||
nsString mInitDataType;
|
||||
};
|
||||
#endif // MOZ_EME
|
||||
|
||||
void MP4Reader::RequestCodecResource() {
|
||||
if (mVideo.mDecoder) {
|
||||
mVideo.mDecoder->AllocateMediaResources();
|
||||
|
@ -368,7 +396,7 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||
{
|
||||
MonitorAutoUnlock unlock(mDemuxerMonitor);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mInfo.mCrypto.mIsEncrypted = mIsEncrypted = mCrypto.valid;
|
||||
mIsEncrypted = mCrypto.valid;
|
||||
}
|
||||
|
||||
// Remember that we've initialized the demuxer, so that if we're decoding
|
||||
|
@ -400,15 +428,21 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||
}
|
||||
}
|
||||
|
||||
if (mIsEncrypted) {
|
||||
if (mCrypto.valid) {
|
||||
nsTArray<uint8_t> initData;
|
||||
ExtractCryptoInitData(initData);
|
||||
if (initData.Length() == 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mInfo.mCrypto.mInitData = initData;
|
||||
mInfo.mCrypto.mType = NS_LITERAL_STRING("cenc");
|
||||
#ifdef MOZ_EME
|
||||
// Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
|
||||
NS_DispatchToMainThread(
|
||||
new DispatchKeyNeededEvent(mDecoder, initData, NS_LITERAL_STRING("cenc")));
|
||||
#endif // MOZ_EME
|
||||
// Add init data to info, will get sent from HTMLMediaElement::MetadataLoaded
|
||||
// (i.e., when transitioning from HAVE_NOTHING to HAVE_METADATA).
|
||||
mInfo.mCrypto.AddInitData(NS_LITERAL_STRING("cenc"), Move(initData));
|
||||
}
|
||||
|
||||
// Get the duration, and report it to the decoder if we have it.
|
||||
|
|
|
@ -275,8 +275,6 @@ private:
|
|||
|
||||
layers::LayersBackend mLayersBackendType;
|
||||
|
||||
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
||||
|
||||
// True if we've read the streams' metadata.
|
||||
bool mDemuxerInitialized;
|
||||
|
||||
|
|
|
@ -1068,22 +1068,6 @@ MediaSourceReader::MaybeNotifyHaveData()
|
|||
IsSeeking(), haveAudio, haveVideo, ended);
|
||||
}
|
||||
|
||||
static void
|
||||
CombineEncryptionData(EncryptionInfo& aTo, const EncryptionInfo& aFrom)
|
||||
{
|
||||
if (!aFrom.mIsEncrypted) {
|
||||
return;
|
||||
}
|
||||
aTo.mIsEncrypted = true;
|
||||
|
||||
if (!aTo.mType.IsEmpty() && !aTo.mType.Equals(aFrom.mType)) {
|
||||
NS_WARNING("mismatched encryption types");
|
||||
}
|
||||
|
||||
aTo.mType = aFrom.mType;
|
||||
aTo.mInitData.AppendElements(aFrom.mInitData);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
{
|
||||
|
@ -1107,7 +1091,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||
const MediaInfo& info = GetAudioReader()->GetMediaInfo();
|
||||
MOZ_ASSERT(info.HasAudio());
|
||||
mInfo.mAudio = info.mAudio;
|
||||
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||
mInfo.mCrypto.AddInitData(info.mCrypto);
|
||||
MSE_DEBUG("audio reader=%p duration=%lld",
|
||||
mAudioSourceDecoder.get(),
|
||||
mAudioSourceDecoder->GetReader()->GetDecoder()->GetMediaDuration());
|
||||
|
@ -1120,7 +1104,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||
const MediaInfo& info = GetVideoReader()->GetMediaInfo();
|
||||
MOZ_ASSERT(info.HasVideo());
|
||||
mInfo.mVideo = info.mVideo;
|
||||
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||
mInfo.mCrypto.AddInitData(info.mCrypto);
|
||||
MSE_DEBUG("video reader=%p duration=%lld",
|
||||
GetVideoReader(),
|
||||
GetVideoReader()->GetDecoder()->GetMediaDuration());
|
||||
|
|
Загрузка…
Ссылка в новой задаче