diff options
Diffstat (limited to 'media/gmp-clearkey/0.1/AudioDecoder.cpp')
-rw-r--r-- | media/gmp-clearkey/0.1/AudioDecoder.cpp | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/media/gmp-clearkey/0.1/AudioDecoder.cpp b/media/gmp-clearkey/0.1/AudioDecoder.cpp deleted file mode 100644 index b02e1a8545..0000000000 --- a/media/gmp-clearkey/0.1/AudioDecoder.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cstdint> -#include <limits> - -#include "AudioDecoder.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeyUtils.h" -#include "gmp-task-utils.h" - -using namespace wmf; - -AudioDecoder::AudioDecoder(GMPAudioHost *aHostAPI) - : mHostAPI(aHostAPI) - , mCallback(nullptr) - , mWorkerThread(nullptr) - , mMutex(nullptr) - , mNumInputTasks(0) - , mHasShutdown(false) -{ - // We drop the ref in DecodingComplete(). - AddRef(); -} - -AudioDecoder::~AudioDecoder() -{ - if (mMutex) { - mMutex->Destroy(); - } -} - -void -AudioDecoder::InitDecode(const GMPAudioCodec& aConfig, - GMPAudioDecoderCallback* aCallback) -{ - mCallback = aCallback; - assert(mCallback); - mDecoder = new WMFAACDecoder(); - HRESULT hr = mDecoder->Init(aConfig.mChannelCount, - aConfig.mSamplesPerSecond, - (BYTE*)aConfig.mExtraData, - aConfig.mExtraDataLen); - LOG("[%p] AudioDecoder::InitializeAudioDecoder() hr=0x%x\n", this, hr); - if (FAILED(hr)) { - mCallback->Error(GMPGenericErr); - return; - } - auto err = GetPlatform()->createmutex(&mMutex); - if (GMP_FAILED(err)) { - mCallback->Error(GMPGenericErr); - return; - } -} - -void -AudioDecoder::EnsureWorker() -{ - if (!mWorkerThread) { - GetPlatform()->createthread(&mWorkerThread); - if (!mWorkerThread) { - mCallback->Error(GMPAllocErr); - return; - } - } -} - -void -AudioDecoder::Decode(GMPAudioSamples* aInput) -{ - EnsureWorker(); - { - AutoLock lock(mMutex); - mNumInputTasks++; - } - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DecodeTask, - aInput)); -} - -void -AudioDecoder::DecodeTask(GMPAudioSamples* aInput) -{ - HRESULT hr; - - { - AutoLock lock(mMutex); - mNumInputTasks--; - assert(mNumInputTasks >= 0); - } - - if (!aInput || !mHostAPI || !mDecoder) { - LOG("Decode job not set up correctly!"); - return; - } - - const uint8_t* inBuffer = aInput->Buffer(); - if (!inBuffer) { - LOG("No buffer for encoded samples!\n"); - return; - } - - const GMPEncryptedBufferMetadata* crypto = aInput->GetDecryptionData(); - std::vector<uint8_t> buffer(inBuffer, inBuffer + aInput->Size()); - if (crypto) { - // Plugin host should have set up its decryptor/key sessions - // before trying to decode! - GMPErr rv = - ClearKeyDecryptionManager::Get()->Decrypt(buffer, CryptoMetaData(crypto)); - - if (GMP_FAILED(rv)) { - CK_LOGE("Failed to decrypt with key id %08x...", *(uint32_t*)crypto->KeyId()); - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Error, rv)); - return; - } - } - - hr = mDecoder->Input(&buffer[0], - buffer.size(), - aInput->TimeStamp()); - - // We must delete the input sample! - GetPlatform()->runonmainthread(WrapTask(aInput, &GMPAudioSamples::Destroy)); - - SAMPLE_LOG("AudioDecoder::DecodeTask() Input ret hr=0x%x\n", hr); - if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() decode failed ret=0x%x%s\n", - hr, - ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : "")); - return; - } - - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DecodeTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - AutoLock lock(mMutex); - if (mNumInputTasks == 0) { - // We have run all input tasks. We *must* notify Gecko so that it will - // send us more data. - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::InputDataExhausted)); - } - } else if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() output failed hr=0x%x\n", hr); - } - } -} - -void -AudioDecoder::ReturnOutput(IMFSample* aSample) -{ - SAMPLE_LOG("[%p] AudioDecoder::ReturnOutput()\n", this); - assert(aSample); - - HRESULT hr; - - GMPAudioSamples* samples = nullptr; - mHostAPI->CreateSamples(kGMPAudioIS16Samples, &samples); - if (!samples) { - LOG("Failed to create i420 frame!\n"); - return; - } - - hr = MFToGMPSample(aSample, samples); - if (FAILED(hr)) { - samples->Destroy(); - LOG("Failed to prepare output sample!"); - return; - } - ENSURE(SUCCEEDED(hr), /*void*/); - - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Decoded, samples)); -} - -HRESULT -AudioDecoder::MFToGMPSample(IMFSample* aInput, - GMPAudioSamples* aOutput) -{ - ENSURE(aInput != nullptr, E_POINTER); - ENSURE(aOutput != nullptr, E_POINTER); - - HRESULT hr; - CComPtr<IMFMediaBuffer> mediaBuffer; - - hr = aInput->ConvertToContiguousBuffer(&mediaBuffer); - ENSURE(SUCCEEDED(hr), hr); - - BYTE* data = nullptr; // Note: *data will be owned by the IMFMediaBuffer, we don't need to free it. - DWORD maxLength = 0, currentLength = 0; - hr = mediaBuffer->Lock(&data, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - auto err = aOutput->SetBufferSize(currentLength); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - memcpy(aOutput->Buffer(), data, currentLength); - - mediaBuffer->Unlock(); - - LONGLONG hns = 0; - hr = aInput->GetSampleTime(&hns); - ENSURE(SUCCEEDED(hr), hr); - aOutput->SetTimeStamp(HNsToUsecs(hns)); - aOutput->SetChannels(mDecoder->Channels()); - aOutput->SetRate(mDecoder->Rate()); - - return S_OK; -} - -void -AudioDecoder::Reset() -{ - if (mDecoder) { - mDecoder->Reset(); - } - if (mCallback) { - mCallback->ResetComplete(); - } -} - -void -AudioDecoder::DrainTask() -{ - mDecoder->Drain(); - - // Return any pending output. - HRESULT hr = S_OK; - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DrainTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - } - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::DrainComplete)); -} - -void -AudioDecoder::Drain() -{ - if (!mDecoder) { - return; - } - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DrainTask)); -} - -void -AudioDecoder::DecodingComplete() -{ - if (mWorkerThread) { - mWorkerThread->Join(); - } - mHasShutdown = true; - - // Release the reference we added in the constructor. There may be - // WrapRefCounted tasks that also hold references to us, and keep - // us alive a little longer. - Release(); -} - -void -AudioDecoder::MaybeRunOnMainThread(GMPTask* aTask) -{ - class MaybeRunTask : public GMPTask - { - public: - MaybeRunTask(AudioDecoder* aDecoder, GMPTask* aTask) - : mDecoder(aDecoder), mTask(aTask) - { } - - virtual void Run(void) { - if (mDecoder->HasShutdown()) { - CK_LOGD("Trying to dispatch to main thread after AudioDecoder has shut down"); - return; - } - - mTask->Run(); - } - - virtual void Destroy() - { - mTask->Destroy(); - delete this; - } - - private: - RefPtr<AudioDecoder> mDecoder; - GMPTask* mTask; - }; - - GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask)); -} |