1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "SamplesWaitingForKey.h"
8 
9 #include "MediaData.h"
10 #include "MediaEventSource.h"
11 #include "mozilla/CDMCaps.h"
12 #include "mozilla/CDMProxy.h"
13 #include "mozilla/TaskQueue.h"
14 
15 namespace mozilla {
16 
SamplesWaitingForKey(CDMProxy * aProxy,TrackInfo::TrackType aType,const std::function<MediaEventProducer<TrackInfo::TrackType> * ()> & aOnWaitingForKeyEvent)17 SamplesWaitingForKey::SamplesWaitingForKey(
18     CDMProxy* aProxy, TrackInfo::TrackType aType,
19     const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
20         aOnWaitingForKeyEvent)
21     : mMutex("SamplesWaitingForKey"),
22       mProxy(aProxy),
23       mType(aType),
24       mOnWaitingForKeyEvent(aOnWaitingForKeyEvent) {}
25 
~SamplesWaitingForKey()26 SamplesWaitingForKey::~SamplesWaitingForKey() { Flush(); }
27 
28 RefPtr<SamplesWaitingForKey::WaitForKeyPromise>
WaitIfKeyNotUsable(MediaRawData * aSample)29 SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample) {
30   if (!aSample || !aSample->mCrypto.IsEncrypted() || !mProxy) {
31     return WaitForKeyPromise::CreateAndResolve(aSample, __func__);
32   }
33   auto caps = mProxy->Capabilites().Lock();
34   const auto& keyid = aSample->mCrypto.mKeyId;
35   if (caps->IsKeyUsable(keyid)) {
36     return WaitForKeyPromise::CreateAndResolve(aSample, __func__);
37   }
38   SampleEntry entry;
39   entry.mSample = aSample;
40   RefPtr<WaitForKeyPromise> p = entry.mPromise.Ensure(__func__);
41   {
42     MutexAutoLock lock(mMutex);
43     mSamples.AppendElement(std::move(entry));
44   }
45   if (mOnWaitingForKeyEvent && mOnWaitingForKeyEvent()) {
46     mOnWaitingForKeyEvent()->Notify(mType);
47   }
48   caps->NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this);
49   return p;
50 }
51 
NotifyUsable(const CencKeyId & aKeyId)52 void SamplesWaitingForKey::NotifyUsable(const CencKeyId& aKeyId) {
53   MutexAutoLock lock(mMutex);
54   size_t i = 0;
55   while (i < mSamples.Length()) {
56     auto& entry = mSamples[i];
57     if (aKeyId == entry.mSample->mCrypto.mKeyId) {
58       entry.mPromise.Resolve(entry.mSample, __func__);
59       mSamples.RemoveElementAt(i);
60     } else {
61       i++;
62     }
63   }
64 }
65 
Flush()66 void SamplesWaitingForKey::Flush() {
67   MutexAutoLock lock(mMutex);
68   for (auto& sample : mSamples) {
69     sample.mPromise.Reject(true, __func__);
70   }
71   mSamples.Clear();
72 }
73 
BreakCycles()74 void SamplesWaitingForKey::BreakCycles() {
75   MutexAutoLock lock(mMutex);
76   mProxy = nullptr;
77 }
78 
79 }  // namespace mozilla
80