зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1342822 - Backed out changeset a379d64f8496 (Bug 1338924 patch 3). r=gerald
MozReview-Commit-ID: 4aFx52mwpQ6 --HG-- extra : rebase_source : 45cfb3aba27e93d49c5ebf64510d0143f1c57654
This commit is contained in:
Родитель
941b2b29b9
Коммит
892e18f12e
|
@ -8,9 +8,7 @@
|
|||
#include "WidevineAdapter.h"
|
||||
#include "WidevineUtils.h"
|
||||
#include "WidevineFileIO.h"
|
||||
#include "GMPPlatform.h"
|
||||
#include <stdarg.h>
|
||||
#include "TimeUnits.h"
|
||||
|
||||
using namespace cdm;
|
||||
using namespace std;
|
||||
|
@ -160,33 +158,6 @@ WidevineDecryptor::SetServerCertificate(uint32_t aPromiseId,
|
|||
CDM()->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize);
|
||||
}
|
||||
|
||||
cdm::Time
|
||||
WidevineDecryptor::ThrottleDecrypt(cdm::Time aWallTime, cdm::Time aSampleDuration)
|
||||
{
|
||||
const cdm::Time WindowSize = 1.0;
|
||||
const cdm::Time MaxThroughput = 2.0;
|
||||
|
||||
// Forget decrypts that happened before the start of our window.
|
||||
while (!mDecrypts.empty() && mDecrypts.front().mWallTime < aWallTime - WindowSize) {
|
||||
mDecrypts.pop_front();
|
||||
}
|
||||
|
||||
// How much time duration of the media would we have decrypted inside the
|
||||
// time window if we did decrypt this block?
|
||||
cdm::Time durationDecrypted = aSampleDuration;
|
||||
for (const DecryptJob& job : mDecrypts) {
|
||||
durationDecrypted += job.mSampleDuration;
|
||||
}
|
||||
|
||||
if (durationDecrypted > MaxThroughput) {
|
||||
// If we decrypted a sample of this duration, we would have decrypted more than
|
||||
// our threshold for max throughput, over the preceding wall time window.
|
||||
return durationDecrypted - MaxThroughput;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
WidevineDecryptor::Decrypt(GMPBuffer* aBuffer,
|
||||
GMPEncryptedBufferMetadata* aMetadata,
|
||||
|
@ -196,72 +167,21 @@ WidevineDecryptor::Decrypt(GMPBuffer* aBuffer,
|
|||
CDM_LOG("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this);
|
||||
return;
|
||||
}
|
||||
|
||||
cdm::Time duration = double(aDurationUsecs) / USECS_PER_S;
|
||||
mPendingDecrypts.push({aBuffer, aMetadata, duration});
|
||||
ProcessDecrypts();
|
||||
}
|
||||
|
||||
void
|
||||
WidevineDecryptor::ProcessDecryptsFromTimer()
|
||||
{
|
||||
MOZ_ASSERT(mPendingDecryptTimerSet);
|
||||
mPendingDecryptTimerSet = false;
|
||||
ProcessDecrypts();
|
||||
}
|
||||
|
||||
void
|
||||
WidevineDecryptor::ProcessDecrypts()
|
||||
{
|
||||
while (!mPendingDecrypts.empty()) {
|
||||
PendingDecrypt job = mPendingDecrypts.front();
|
||||
|
||||
// We throttle our decrypt so that we don't decrypt more than a certain
|
||||
// duration of samples per second. This is to work around bugs in the
|
||||
// Widevine CDM. See bug 1338924.
|
||||
cdm::Time now = GetCurrentWallTime();
|
||||
cdm::Time delay = ThrottleDecrypt(now, job.mSampleDuration);
|
||||
|
||||
if (delay > 0.0) {
|
||||
// If we decrypted this sample now, we'd decrypt more than our threshold
|
||||
// per second of samples. Enqueue the sample, and wait until we'd be able
|
||||
// to decrypt it without breaking our throughput threshold.
|
||||
if (!mPendingDecryptTimerSet) {
|
||||
mPendingDecryptTimerSet = true;
|
||||
RefPtr<WidevineDecryptor> self = this;
|
||||
GMPTask* task = gmp::NewGMPTask(
|
||||
[self]() {
|
||||
self->ProcessDecryptsFromTimer();
|
||||
});
|
||||
gmp::SetTimerOnMainThread(task, delay * 1000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
DecryptBuffer(job);
|
||||
mDecrypts.push_back(DecryptJob(now, job.mSampleDuration));
|
||||
mPendingDecrypts.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WidevineDecryptor::DecryptBuffer(const PendingDecrypt& aJob)
|
||||
{
|
||||
GMPBuffer* buffer = aJob.mBuffer;
|
||||
const GMPEncryptedBufferMetadata* crypto = aJob.mMetadata;
|
||||
const GMPEncryptedBufferMetadata* crypto = aMetadata;
|
||||
InputBuffer sample;
|
||||
nsTArray<SubsampleEntry> subsamples;
|
||||
InitInputBuffer(crypto, buffer->Id(), buffer->Data(), buffer->Size(), sample, subsamples);
|
||||
InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples);
|
||||
WidevineDecryptedBlock decrypted;
|
||||
Status rv = CDM()->Decrypt(sample, &decrypted);
|
||||
CDM_LOG("Decryptor::Decrypt(timestamp=%" PRId64 ") rv=%d sz=%d",
|
||||
sample.timestamp, rv, decrypted.DecryptedBuffer()->Size());
|
||||
if (rv == kSuccess) {
|
||||
buffer->Resize(decrypted.DecryptedBuffer()->Size());
|
||||
memcpy(buffer->Data(),
|
||||
aBuffer->Resize(decrypted.DecryptedBuffer()->Size());
|
||||
memcpy(aBuffer->Data(),
|
||||
decrypted.DecryptedBuffer()->Data(),
|
||||
decrypted.DecryptedBuffer()->Size());
|
||||
}
|
||||
mCallback->Decrypted(buffer, ToGMPErr(rv));
|
||||
mCallback->Decrypted(aBuffer, ToGMPErr(rv));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -269,16 +189,6 @@ WidevineDecryptor::DecryptingComplete()
|
|||
{
|
||||
CDM_LOG("WidevineDecryptor::DecryptingComplete() this=%p, instanceId=%u",
|
||||
this, mInstanceId);
|
||||
|
||||
// Ensure buffers are freed.
|
||||
while (!mPendingDecrypts.empty()) {
|
||||
PendingDecrypt& job = mPendingDecrypts.front();
|
||||
if (mCallback) {
|
||||
mCallback->Decrypted(job.mBuffer, GMPAbortedErr);
|
||||
}
|
||||
mPendingDecrypts.pop();
|
||||
}
|
||||
|
||||
// Drop our references to the CDMWrapper. When any other references
|
||||
// held elsewhere are dropped (for example references held by a
|
||||
// WidevineVideoDecoder, or a runnable), the CDMWrapper destroys
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "mozilla/RefPtr.h"
|
||||
#include "WidevineUtils.h"
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -121,45 +119,6 @@ public:
|
|||
GMPDecryptorCallback* Callback() const { return mCallback; }
|
||||
RefPtr<CDMWrapper> GetCDMWrapper() const { return mCDM; }
|
||||
private:
|
||||
|
||||
struct PendingDecrypt
|
||||
{
|
||||
PendingDecrypt(GMPBuffer* aBuffer,
|
||||
GMPEncryptedBufferMetadata* aMetadata,
|
||||
cdm::Time aSampleDuration)
|
||||
: mBuffer(aBuffer)
|
||||
, mMetadata(aMetadata)
|
||||
, mSampleDuration(aSampleDuration)
|
||||
{
|
||||
}
|
||||
GMPBuffer* mBuffer;
|
||||
GMPEncryptedBufferMetadata* mMetadata;
|
||||
cdm::Time mSampleDuration;
|
||||
};
|
||||
|
||||
// Queue of buffers waiting to be decrypted.
|
||||
std::queue<PendingDecrypt> mPendingDecrypts;
|
||||
|
||||
void DecryptBuffer(const PendingDecrypt& aJob);
|
||||
cdm::Time ThrottleDecrypt(cdm::Time aWallClock, cdm::Time aSampleDuration);
|
||||
void ProcessDecrypts();
|
||||
void ProcessDecryptsFromTimer();
|
||||
|
||||
struct DecryptJob
|
||||
{
|
||||
DecryptJob(cdm::Time aWallTime, cdm::Time aSampleDuration)
|
||||
: mWallTime(aWallTime)
|
||||
, mSampleDuration(aSampleDuration)
|
||||
{}
|
||||
cdm::Time mWallTime;
|
||||
cdm::Time mSampleDuration;
|
||||
};
|
||||
|
||||
// Queue of durations of buffers that have been decrypted, along with the
|
||||
// wall-clock timestamp when they were decrypted. This enables us to
|
||||
// throttle the throughput against the wall-clock.
|
||||
std::deque<DecryptJob> mDecrypts;
|
||||
|
||||
~WidevineDecryptor();
|
||||
RefPtr<CDMWrapper> mCDM;
|
||||
cdm::ContentDecryptionModule_8* CDM() { return mCDM->GetCDM(); }
|
||||
|
@ -169,7 +128,6 @@ private:
|
|||
bool mDistinctiveIdentifierRequired = false;
|
||||
bool mPersistentStateRequired = false;
|
||||
uint32_t mInstanceId = 0;
|
||||
bool mPendingDecryptTimerSet = false;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче