summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms')
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.cpp268
-rw-r--r--dom/media/platforms/gonk/GonkAudioDecoderManager.h59
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.cpp63
-rw-r--r--dom/media/platforms/gonk/GonkDecoderModule.h37
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.cpp385
-rw-r--r--dom/media/platforms/gonk/GonkMediaDataDecoder.h214
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.cpp772
-rw-r--r--dom/media/platforms/gonk/GonkVideoDecoderManager.h149
-rw-r--r--dom/media/platforms/gonk/moz.build39
-rw-r--r--dom/media/platforms/moz.build4
-rw-r--r--dom/media/platforms/omx/GonkOmxPlatformLayer.cpp667
-rw-r--r--dom/media/platforms/omx/GonkOmxPlatformLayer.h205
-rw-r--r--dom/media/platforms/omx/OmxPlatformLayer.cpp5
-rw-r--r--dom/media/platforms/omx/moz.build23
14 files changed, 0 insertions, 2890 deletions
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp b/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
deleted file mode 100644
index 0bc3fbea9..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkAudioDecoderManager.h"
-#include "MediaDecoderReader.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "mozilla/Logging.h"
-#include "stagefright/MediaBuffer.h"
-#include "stagefright/MetaData.h"
-#include "stagefright/MediaErrors.h"
-#include <stagefright/foundation/AMessage.h>
-#include <stagefright/foundation/ALooper.h>
-#include "media/openmax/OMX_Audio.h"
-#include "MediaData.h"
-#include "MediaInfo.h"
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
- : mAudioChannels(aConfig.mChannels)
- , mAudioRate(aConfig.mRate)
- , mAudioProfile(aConfig.mProfile)
- , mAudioCompactor(mAudioQueue)
-{
- MOZ_COUNT_CTOR(GonkAudioDecoderManager);
- MOZ_ASSERT(mAudioChannels);
- mCodecSpecificData = aConfig.mCodecSpecificConfig;
- mMimeType = aConfig.mMimeType;
-}
-
-GonkAudioDecoderManager::~GonkAudioDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkAudioDecoderManager);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkAudioDecoderManager::Init()
-{
- if (InitMediaCodecProxy()) {
- return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
- } else {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-}
-
-bool
-GonkAudioDecoderManager::InitMediaCodecProxy()
-{
- status_t rv = OK;
- if (!InitLoopers(MediaData::AUDIO_DATA)) {
- return false;
- }
-
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
- if (!mDecoder.get()) {
- return false;
- }
- if (!mDecoder->AllocateAudioMediaCodec())
- {
- mDecoder = nullptr;
- return false;
- }
- sp<AMessage> format = new AMessage;
- // Fixed values
- GADM_LOG("Configure audio mime type:%s, chan no:%d, sample-rate:%d, profile:%d",
- mMimeType.get(), mAudioChannels, mAudioRate, mAudioProfile);
- format->setString("mime", mMimeType.get());
- format->setInt32("channel-count", mAudioChannels);
- format->setInt32("sample-rate", mAudioRate);
- format->setInt32("aac-profile", mAudioProfile);
- status_t err = mDecoder->configure(format, nullptr, nullptr, 0);
- if (err != OK || !mDecoder->Prepare()) {
- return false;
- }
-
- if (mMimeType.EqualsLiteral("audio/mp4a-latm")) {
- rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv == OK) {
- return true;
- } else {
- GADM_LOG("Failed to input codec specific data!");
- return false;
- }
-}
-
-nsresult
-GonkAudioDecoderManager::CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset)
-{
- if (!(aBuffer != nullptr && aBuffer->data() != nullptr)) {
- GADM_LOG("Audio Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- int64_t timeUs;
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (mLastTime > timeUs) {
- GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- MOZ_ASSERT(false);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- const uint8_t *data = static_cast<const uint8_t*>(aBuffer->data());
- size_t dataOffset = aBuffer->range_offset();
- size_t size = aBuffer->range_length();
-
- uint32_t frames = size / (2 * mAudioChannels);
-
- CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
- if (!duration.isValid()) {
- return NS_ERROR_UNEXPECTED;
- }
-
- typedef AudioCompactor::NativeCopy OmxCopy;
- mAudioCompactor.Push(aStreamOffset,
- timeUs,
- mAudioRate,
- frames,
- mAudioChannels,
- OmxCopy(data+dataOffset,
- size,
- mAudioChannels));
- return NS_OK;
-}
-
-nsresult
-GonkAudioDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- status_t err;
- MediaBuffer* audioBuffer = nullptr;
- err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
- AutoReleaseMediaBuffer a(audioBuffer, mDecoder.get());
-
- switch (err) {
- case OK:
- {
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- break;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GADM_LOG("Decoder format changed");
- sp<AMessage> audioCodecFormat;
-
- if (mDecoder->getOutputFormat(&audioCodecFormat) != OK ||
- audioCodecFormat == nullptr) {
- return NS_ERROR_UNEXPECTED;
- }
-
- int32_t codec_channel_count = 0;
- int32_t codec_sample_rate = 0;
-
- if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) ||
- !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- // Update AudioInfo
- AudioConfig::ChannelLayout layout(codec_channel_count);
- if (!layout.IsValid()) {
- return NS_ERROR_FAILURE;
- }
- mAudioChannels = codec_channel_count;
- mAudioRate = codec_sample_rate;
-
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- GADM_LOG("Info Output Buffers Changed");
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GADM_LOG("Got EOS frame!");
- nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
- MOZ_ASSERT(mAudioQueue.GetSize() > 0);
- mAudioQueue.Finish();
- break;
- }
- case -ETIMEDOUT:
- {
- GADM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GADM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- if (mAudioQueue.GetSize() > 0) {
- aOutData = mAudioQueue.PopFront();
- // Return NS_ERROR_ABORT at the last sample.
- return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
- }
-
- return NS_ERROR_NOT_AVAILABLE;
-}
-
-void
-GonkAudioDecoderManager::ProcessFlush()
-{
- GADM_LOG("FLUSH<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>FLUSH");
- GonkDecoderManager::ProcessFlush();
-}
-
-void
-GonkAudioDecoderManager::ResetEOS()
-{
- GADM_LOG("ResetEOS(<<<");
- mAudioQueue.Reset();
- GADM_LOG(">>>ResetEOS(");
- GonkDecoderManager::ResetEOS();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkAudioDecoderManager.h b/dom/media/platforms/gonk/GonkAudioDecoderManager.h
deleted file mode 100644
index aa35d620e..000000000
--- a/dom/media/platforms/gonk/GonkAudioDecoderManager.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkAudioDecoderManager_h_)
-#define GonkAudioDecoderManager_h_
-
-#include "AudioCompactor.h"
-#include "mozilla/RefPtr.h"
-#include "GonkMediaDataDecoder.h"
-
-using namespace android;
-
-namespace android {
-class MOZ_EXPORT MediaBuffer;
-} // namespace android
-
-namespace mozilla {
-
-class GonkAudioDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-public:
- GonkAudioDecoderManager(const AudioInfo& aConfig);
-
- virtual ~GonkAudioDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- void ProcessFlush() override;
- virtual void ResetEOS() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk audio decoder";
- }
-
-private:
- bool InitMediaCodecProxy();
-
- nsresult CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset);
-
- uint32_t mAudioChannels;
- uint32_t mAudioRate;
- const uint32_t mAudioProfile;
-
- MediaQueue<AudioData> mAudioQueue;
-
- AudioCompactor mAudioCompactor;
-
-};
-
-} // namespace mozilla
-
-#endif // GonkAudioDecoderManager_h_
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.cpp b/dom/media/platforms/gonk/GonkDecoderModule.cpp
deleted file mode 100644
index 537bc299c..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkDecoderModule.h"
-#include "GonkVideoDecoderManager.h"
-#include "GonkAudioDecoderManager.h"
-#include "mozilla/DebugOnly.h"
-#include "GonkMediaDataDecoder.h"
-
-namespace mozilla {
-GonkDecoderModule::GonkDecoderModule()
-{
-}
-
-GonkDecoderModule::~GonkDecoderModule()
-{
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkVideoDecoderManager(aParams.mImageContainer, aParams.VideoConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-already_AddRefed<MediaDataDecoder>
-GonkDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
-{
- RefPtr<MediaDataDecoder> decoder =
- new GonkMediaDataDecoder(new GonkAudioDecoderManager(aParams.AudioConfig()),
- aParams.mCallback);
- return decoder.forget();
-}
-
-PlatformDecoderModule::ConversionRequired
-GonkDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo()) {
- return ConversionRequired::kNeedAnnexB;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
-bool
-GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const
-{
- return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
- aMimeType.EqualsLiteral("audio/3gpp") ||
- aMimeType.EqualsLiteral("audio/amr-wb") ||
- aMimeType.EqualsLiteral("audio/mpeg") ||
- aMimeType.EqualsLiteral("video/mp4") ||
- aMimeType.EqualsLiteral("video/mp4v-es") ||
- aMimeType.EqualsLiteral("video/avc") ||
- aMimeType.EqualsLiteral("video/3gpp");
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkDecoderModule.h b/dom/media/platforms/gonk/GonkDecoderModule.h
deleted file mode 100644
index 4f29f0e75..000000000
--- a/dom/media/platforms/gonk/GonkDecoderModule.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkPlatformDecoderModule_h_)
-#define GonkPlatformDecoderModule_h_
-
-#include "PlatformDecoderModule.h"
-
-namespace mozilla {
-
-class GonkDecoderModule : public PlatformDecoderModule {
-public:
- GonkDecoderModule();
- virtual ~GonkDecoderModule();
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateVideoDecoder(const CreateDecoderParams& aParams) override;
-
- // Decode thread.
- already_AddRefed<MediaDataDecoder>
- CreateAudioDecoder(const CreateDecoderParams& aParams) override;
-
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
- bool SupportsMimeType(const nsACString& aMimeType,
- DecoderDoctorDiagnostics* aDiagnostics) const override;
-
-};
-
-} // namespace mozilla
-
-#endif
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp b/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
deleted file mode 100644
index 6d59d72e1..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "GonkMediaDataDecoder.h"
-#include "VideoUtils.h"
-#include "nsTArray.h"
-#include "MediaCodecProxy.h"
-
-#include <stagefright/foundation/ADebug.h>
-
-#include "mozilla/Logging.h"
-#include <android/log.h>
-#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__)
-#define INPUT_TIMEOUT_US 0LL // Don't wait for buffer if none is available.
-#define MIN_QUEUED_SAMPLES 2
-
-#ifdef DEBUG
-#include <utils/AndroidThreads.h>
-#endif
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-using namespace android;
-
-namespace mozilla {
-
-bool
-GonkDecoderManager::InitLoopers(MediaData::Type aType)
-{
- MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr);
- MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA);
-
- const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio");
- mDecodeLooper = new ALooper;
- android::AString name("MediaCodecProxy/");
- name.append(suffix);
- mDecodeLooper->setName(name.c_str());
-
- mTaskLooper = new ALooper;
- name.setTo("GonkDecoderManager/");
- name.append(suffix);
- mTaskLooper->setName(name.c_str());
- mTaskLooper->registerHandler(this);
-
-#ifdef DEBUG
- sp<AMessage> findThreadId(new AMessage(kNotifyFindLooperId, id()));
- findThreadId->post();
-#endif
-
- return mDecodeLooper->start() == OK && mTaskLooper->start() == OK;
-}
-
-nsresult
-GonkDecoderManager::Input(MediaRawData* aSample)
-{
- RefPtr<MediaRawData> sample;
-
- if (aSample) {
- sample = aSample;
- } else {
- // It means EOS with empty sample.
- sample = new MediaRawData();
- }
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.AppendElement(sample);
- }
-
- sp<AMessage> input = new AMessage(kNotifyProcessInput, id());
- if (!aSample) {
- input->setInt32("input-eos", 1);
- }
- input->post();
- return NS_OK;
-}
-
-int32_t
-GonkDecoderManager::ProcessQueuedSamples()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MutexAutoLock lock(mMutex);
- status_t rv;
- while (mQueuedSamples.Length()) {
- RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
- rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
- data->Size(),
- data->mTime,
- 0,
- INPUT_TIMEOUT_US);
- if (rv == OK) {
- mQueuedSamples.RemoveElementAt(0);
- mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime,
- /* eos */ data->Data() == nullptr));
- } else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
- // In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
- // buffer on time.
- break;
- } else {
- return rv;
- }
- }
- return mQueuedSamples.Length();
-}
-
-nsresult
-GonkDecoderManager::Flush()
-{
- if (mDecoder == nullptr) {
- GMDD_LOG("Decoder is not initialized");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (!mInitPromise.IsEmpty()) {
- return NS_OK;
- }
-
- {
- MutexAutoLock lock(mMutex);
- mQueuedSamples.Clear();
- }
-
- MonitorAutoLock lock(mFlushMonitor);
- mIsFlushing = true;
- sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id());
- flush->post();
- while (mIsFlushing) {
- lock.Wait();
- }
- return NS_OK;
-}
-
-nsresult
-GonkDecoderManager::Shutdown()
-{
- if (mDecoder.get()) {
- mDecoder->stop();
- mDecoder->ReleaseMediaResources();
- mDecoder = nullptr;
- }
-
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-
- return NS_OK;
-}
-
-size_t
-GonkDecoderManager::NumQueuedSamples()
-{
- MutexAutoLock lock(mMutex);
- return mQueuedSamples.Length();
-}
-
-void
-GonkDecoderManager::ProcessInput(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- status_t rv = ProcessQueuedSamples();
- if (rv >= 0) {
- if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- }
-
- if (mToDo.get() == nullptr) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- } else if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- } else {
- GMDD_LOG("input processed: error#%d", rv);
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::ProcessFlush()
-{
- MOZ_ASSERT(OnTaskLooper());
-
- mLastTime = INT64_MIN;
- MonitorAutoLock lock(mFlushMonitor);
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
- mIsFlushing = false;
- lock.NotifyAll();
-}
-
-// Use output timestamp to determine which output buffer is already returned
-// and remove corresponding info, except for EOS, from the waiting list.
-// This method handles the cases that audio decoder sends multiple output
-// buffers for one input.
-void
-GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- size_t i;
- for (i = 0; i < mWaitOutput.Length(); i++) {
- const auto& item = mWaitOutput.ElementAt(i);
- if (item.mEOS || item.mTimestamp > aForgetUpTo) {
- break;
- }
- }
- if (i > 0) {
- mWaitOutput.RemoveElementsAt(0, i);
- }
-}
-
-void
-GonkDecoderManager::ProcessToDo(bool aEndOfStream)
-{
- MOZ_ASSERT(OnTaskLooper());
-
- MOZ_ASSERT(mToDo.get() != nullptr);
- mToDo.clear();
-
- if (NumQueuedSamples() > 0 && ProcessQueuedSamples() < 0) {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
-
- while (mWaitOutput.Length() > 0) {
- RefPtr<MediaData> output;
- WaitOutputInfo wait = mWaitOutput.ElementAt(0);
- nsresult rv = Output(wait.mOffset, output);
- if (rv == NS_OK) {
- MOZ_ASSERT(output);
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- } else if (rv == NS_ERROR_ABORT) {
- // EOS
- MOZ_ASSERT(mQueuedSamples.IsEmpty());
- if (output) {
- mDecodeCallback->Output(output);
- UpdateWaitingList(output->mTime);
- }
- MOZ_ASSERT(mWaitOutput.Length() == 1);
- mWaitOutput.RemoveElementAt(0);
- mDecodeCallback->DrainComplete();
- ResetEOS();
- return;
- } else if (rv == NS_ERROR_NOT_AVAILABLE) {
- break;
- } else {
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- return;
- }
- }
-
- if (!aEndOfStream && NumQueuedSamples() <= MIN_QUEUED_SAMPLES) {
- mDecodeCallback->InputExhausted();
- // No need to shedule todo task this time because InputExhausted() will
- // cause Input() to be invoked and do it for us.
- return;
- }
-
- if (NumQueuedSamples() || mWaitOutput.Length() > 0) {
- mToDo = new AMessage(kNotifyDecoderActivity, id());
- if (aEndOfStream) {
- mToDo->setInt32("input-eos", 1);
- }
- mDecoder->requestActivityNotification(mToDo);
- }
-}
-
-void
-GonkDecoderManager::ResetEOS()
-{
- // After eos, android::MediaCodec needs to be flushed to receive next input
- mWaitOutput.Clear();
- if (mDecoder->flush() != OK) {
- GMDD_LOG("flush error");
- mDecodeCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
- __func__));
- }
-}
-
-void
-GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyProcessInput:
- {
- int32_t eos = 0;
- ProcessInput(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
- case kNotifyProcessFlush:
- {
- ProcessFlush();
- break;
- }
- case kNotifyDecoderActivity:
- {
- int32_t eos = 0;
- ProcessToDo(aMessage->findInt32("input-eos", &eos) && eos);
- break;
- }
-#ifdef DEBUG
- case kNotifyFindLooperId:
- {
- mTaskLooperId = androidGetThreadId();
- MOZ_ASSERT(mTaskLooperId);
- break;
- }
-#endif
- default:
- {
- TRESPASS();
- break;
- }
- }
-}
-
-#ifdef DEBUG
-bool
-GonkDecoderManager::OnTaskLooper()
-{
- return androidGetThreadId() == mTaskLooperId;
-}
-#endif
-
-GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
- MediaDataDecoderCallback* aCallback)
- : mManager(aManager)
-{
- MOZ_COUNT_CTOR(GonkMediaDataDecoder);
- mManager->SetDecodeCallback(aCallback);
-}
-
-GonkMediaDataDecoder::~GonkMediaDataDecoder()
-{
- MOZ_COUNT_DTOR(GonkMediaDataDecoder);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkMediaDataDecoder::Init()
-{
- return mManager->Init();
-}
-
-void
-GonkMediaDataDecoder::Shutdown()
-{
- mManager->Shutdown();
-
- // Because codec allocated runnable and init promise is at reader TaskQueue,
- // so manager needs to be destroyed at reader TaskQueue to prevent racing.
- mManager = nullptr;
-}
-
-// Inserts data into the decoder's pipeline.
-void
-GonkMediaDataDecoder::Input(MediaRawData* aSample)
-{
- mManager->Input(aSample);
-}
-
-void
-GonkMediaDataDecoder::Flush()
-{
- mManager->Flush();
-}
-
-void
-GonkMediaDataDecoder::Drain()
-{
- mManager->Input(nullptr);
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkMediaDataDecoder.h b/dom/media/platforms/gonk/GonkMediaDataDecoder.h
deleted file mode 100644
index bba2a8645..000000000
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkMediaDataDecoder_h_)
-#define GonkMediaDataDecoder_h_
-#include "PlatformDecoderModule.h"
-#include <stagefright/foundation/AHandler.h>
-
-namespace android {
-struct ALooper;
-class MediaBuffer;
-class MediaCodecProxy;
-} // namespace android
-
-namespace mozilla {
-class MediaRawData;
-
-// Manage the data flow from inputting encoded data and outputting decode data.
-class GonkDecoderManager : public android::AHandler {
-public:
- typedef TrackInfo::TrackType TrackType;
- typedef MediaDataDecoder::InitPromise InitPromise;
-
- virtual ~GonkDecoderManager() {}
-
- virtual RefPtr<InitPromise> Init() = 0;
- virtual const char* GetDescriptionName() const = 0;
-
- // Asynchronously send sample into mDecoder. If out of input buffer, aSample
- // will be queued for later re-send.
- nsresult Input(MediaRawData* aSample);
-
- // Flush the queued samples and signal decoder to throw all pending input/output away.
- nsresult Flush();
-
- // Shutdown decoder and rejects the init promise.
- virtual nsresult Shutdown();
-
- // How many samples are waiting for processing.
- size_t NumQueuedSamples();
-
- // Set callback for decoder events, such as requesting more input,
- // returning output, or reporting error.
- void SetDecodeCallback(MediaDataDecoderCallback* aCallback)
- {
- mDecodeCallback = aCallback;
- }
-
-protected:
- GonkDecoderManager()
- : mMutex("GonkDecoderManager")
- , mLastTime(INT64_MIN)
- , mFlushMonitor("GonkDecoderManager::Flush")
- , mIsFlushing(false)
- , mDecodeCallback(nullptr)
- {}
-
- bool InitLoopers(MediaData::Type aType);
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- // Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
- // when output is not produced yet.
- // If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error
- // will be reported through mDecodeCallback.
- virtual nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) = 0;
-
- // Send queued samples to OMX. It returns how many samples are still in
- // queue after processing, or negative error code if failed.
- int32_t ProcessQueuedSamples();
-
- void ProcessInput(bool aEndOfStream);
- virtual void ProcessFlush();
- void ProcessToDo(bool aEndOfStream);
- virtual void ResetEOS();
-
- RefPtr<MediaByteBuffer> mCodecSpecificData;
-
- nsAutoCString mMimeType;
-
- // MediaCodedc's wrapper that performs the decoding.
- android::sp<android::MediaCodecProxy> mDecoder;
- // Looper for mDecoder to run on.
- android::sp<android::ALooper> mDecodeLooper;
- // Looper to run decode tasks such as processing input, output, flush, and
- // recycling output buffers.
- android::sp<android::ALooper> mTaskLooper;
- // Message codes for tasks running on mTaskLooper.
- enum {
- // Decoder will send this to indicate internal state change such as input or
- // output buffers availability. Used to run pending input & output tasks.
- kNotifyDecoderActivity = 'nda ',
- // Signal the decoder to flush.
- kNotifyProcessFlush = 'npf ',
- // Used to process queued samples when there is new input.
- kNotifyProcessInput = 'npi ',
-#ifdef DEBUG
- kNotifyFindLooperId = 'nfli',
-#endif
- };
-
- MozPromiseHolder<InitPromise> mInitPromise;
-
- Mutex mMutex; // Protects mQueuedSamples.
- // A queue that stores the samples waiting to be sent to mDecoder.
- // Empty element means EOS and there shouldn't be any sample be queued after it.
- // Samples are queued in caller's thread and dequeued in mTaskLooper.
- nsTArray<RefPtr<MediaRawData>> mQueuedSamples;
-
- // The last decoded frame presentation time. Only accessed on mTaskLooper.
- int64_t mLastTime;
-
- Monitor mFlushMonitor; // Waits for flushing to complete.
- bool mIsFlushing; // Protected by mFlushMonitor.
-
- // Remembers the notification that is currently waiting for the decoder event
- // to avoid requesting more than one notification at the time, which is
- // forbidden by mDecoder.
- android::sp<android::AMessage> mToDo;
-
- // Stores sample info for output buffer processing later.
- struct WaitOutputInfo {
- WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS)
- : mOffset(aOffset)
- , mTimestamp(aTimestamp)
- , mEOS(aEOS)
- {}
- const int64_t mOffset;
- const int64_t mTimestamp;
- const bool mEOS;
- };
-
- nsTArray<WaitOutputInfo> mWaitOutput;
-
- MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
-
-private:
- void UpdateWaitingList(int64_t aForgetUpTo);
-
-#ifdef DEBUG
- typedef void* LooperId;
-
- bool OnTaskLooper();
- LooperId mTaskLooperId;
-#endif
-};
-
-class AutoReleaseMediaBuffer
-{
-public:
- AutoReleaseMediaBuffer(android::MediaBuffer* aBuffer, android::MediaCodecProxy* aCodec)
- : mBuffer(aBuffer)
- , mCodec(aCodec)
- {}
-
- ~AutoReleaseMediaBuffer()
- {
- MOZ_ASSERT(mCodec.get());
- if (mBuffer) {
- mCodec->ReleaseMediaBuffer(mBuffer);
- }
- }
-
- android::MediaBuffer* forget()
- {
- android::MediaBuffer* tmp = mBuffer;
- mBuffer = nullptr;
- return tmp;
- }
-
-private:
- android::MediaBuffer* mBuffer;
- android::sp<android::MediaCodecProxy> mCodec;
-};
-
-// Samples are decoded using the GonkDecoder (MediaCodec)
-// created by the GonkDecoderManager. This class implements
-// the higher-level logic that drives mapping the Gonk to the async
-// MediaDataDecoder interface. The specifics of decoding the exact stream
-// type are handled by GonkDecoderManager and the GonkDecoder it creates.
-class GonkMediaDataDecoder : public MediaDataDecoder {
-public:
- GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
- MediaDataDecoderCallback* aCallback);
-
- ~GonkMediaDataDecoder();
-
- RefPtr<InitPromise> Init() override;
-
- void Input(MediaRawData* aSample) override;
-
- void Flush() override;
-
- void Drain() override;
-
- void Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk decoder";
- }
-
-private:
-
- android::sp<GonkDecoderManager> mManager;
-};
-
-} // namespace mozilla
-
-#endif // GonkMediaDataDecoder_h_
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
deleted file mode 100644
index 0c7b3b6af..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "MediaCodecProxy.h"
-#include <OMX_IVCommon.h>
-#include <gui/Surface.h>
-#include <ICrypto.h>
-#include "GonkVideoDecoderManager.h"
-#include "GrallocImages.h"
-#include "MediaDecoderReader.h"
-#include "ImageContainer.h"
-#include "VideoUtils.h"
-#include "nsThreadUtils.h"
-#include "Layers.h"
-#include "mozilla/Logging.h"
-#include <stagefright/MediaBuffer.h>
-#include <stagefright/MetaData.h>
-#include <stagefright/MediaErrors.h>
-#include <stagefright/foundation/AString.h>
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
-#include <cutils/properties.h>
-
-#define CODECCONFIG_TIMEOUT_US 10000LL
-#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
-
-#include <android/log.h>
-#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__)
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-using namespace mozilla::layers;
-using namespace android;
-typedef android::MediaCodecProxy MediaCodecProxy;
-
-namespace mozilla {
-
-class GonkTextureClientAllocationHelper : public layers::ITextureClientAllocationHelper
-{
-public:
- GonkTextureClientAllocationHelper(uint32_t aGrallocFormat,
- gfx::IntSize aSize)
- : ITextureClientAllocationHelper(gfx::SurfaceFormat::UNKNOWN,
- aSize,
- BackendSelector::Content,
- TextureFlags::DEALLOCATE_CLIENT,
- ALLOC_DISALLOW_BUFFERTEXTURECLIENT)
- , mGrallocFormat(aGrallocFormat)
- {}
-
- already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
- {
- uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
- android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
- android::GraphicBuffer::USAGE_HW_TEXTURE;
-
- GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat,
- gfx::BackendType::NONE,
- usage, aAllocator->GetTextureForwarder());
- if (!texData) {
- return nullptr;
- }
- sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
- if (!graphicBuffer.get()) {
- return nullptr;
- }
- RefPtr<TextureClient> textureClient =
- TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator->GetTextureForwarder());
- return textureClient.forget();
- }
-
- bool IsCompatible(TextureClient* aTextureClient) override
- {
- if (!aTextureClient) {
- return false;
- }
- sp<GraphicBuffer> graphicBuffer =
- static_cast<GrallocTextureData*>(aTextureClient->GetInternalData())->GetGraphicBuffer();
- if (!graphicBuffer.get() ||
- static_cast<uint32_t>(graphicBuffer->getPixelFormat()) != mGrallocFormat ||
- aTextureClient->GetSize() != mSize) {
- return false;
- }
- return true;
- }
-
-private:
- uint32_t mGrallocFormat;
-};
-
-GonkVideoDecoderManager::GonkVideoDecoderManager(
- mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig)
- : mConfig(aConfig)
- , mImageContainer(aImageContainer)
- , mColorConverterBufferSize(0)
- , mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
- , mNeedsCopyBuffer(false)
-{
- MOZ_COUNT_CTOR(GonkVideoDecoderManager);
-}
-
-GonkVideoDecoderManager::~GonkVideoDecoderManager()
-{
- MOZ_COUNT_DTOR(GonkVideoDecoderManager);
-}
-
-nsresult
-GonkVideoDecoderManager::Shutdown()
-{
- mVideoCodecRequest.DisconnectIfExists();
- return GonkDecoderManager::Shutdown();
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-GonkVideoDecoderManager::Init()
-{
- mNeedsCopyBuffer = false;
-
- uint32_t maxWidth, maxHeight;
- char propValue[PROPERTY_VALUE_MAX];
- property_get("ro.moz.omx.hw.max_width", propValue, "-1");
- maxWidth = -1 == atoi(propValue) ? MAX_VIDEO_WIDTH : atoi(propValue);
- property_get("ro.moz.omx.hw.max_height", propValue, "-1");
- maxHeight = -1 == atoi(propValue) ? MAX_VIDEO_HEIGHT : atoi(propValue) ;
-
- if (uint32_t(mConfig.mImage.width * mConfig.mImage.height) > maxWidth * maxHeight) {
- GVDM_LOG("Video resolution exceeds hw codec capability");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- // Validate the container-reported frame and pictureRect sizes. This ensures
- // that our video frame creation code doesn't overflow.
- if (!IsValidVideoRegion(mConfig.mImage, mConfig.ImageRect(), mConfig.mDisplay)) {
- GVDM_LOG("It is not a valid region");
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
- MOZ_ASSERT(mReaderTaskQueue);
-
- if (mDecodeLooper.get() != nullptr) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- if (!InitLoopers(MediaData::VIDEO_DATA)) {
- return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- }
-
- RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
- android::sp<GonkVideoDecoderManager> self = this;
- mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper,
- mConfig.mMimeType.get(),
- false);
-
- uint32_t capability = MediaCodecProxy::kEmptyCapability;
- if (mDecoder->getCapability(&capability) == OK && (capability &
- MediaCodecProxy::kCanExposeGraphicBuffer)) {
-#if ANDROID_VERSION >= 21
- sp<IGonkGraphicBufferConsumer> consumer;
- GonkBufferQueue::createBufferQueue(&mGraphicBufferProducer, &consumer);
- mNativeWindow = new GonkNativeWindow(consumer);
-#else
- mNativeWindow = new GonkNativeWindow();
-#endif
- }
-
- mVideoCodecRequest.Begin(mDecoder->AsyncAllocateVideoMediaCodec()
- ->Then(mReaderTaskQueue, __func__,
- [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecReserved();
- }, [self] (bool) -> void {
- self->mVideoCodecRequest.Complete();
- self->codecCanceled();
- }));
-
- return p;
-}
-
-nsresult
-GonkVideoDecoderManager::CreateVideoData(MediaBuffer* aBuffer,
- int64_t aStreamOffset,
- VideoData **v)
-{
- *v = nullptr;
- RefPtr<VideoData> data;
- int64_t timeUs;
- int32_t keyFrame;
-
- if (aBuffer == nullptr) {
- GVDM_LOG("Video Buffer is not valid!");
- return NS_ERROR_UNEXPECTED;
- }
-
- AutoReleaseMediaBuffer autoRelease(aBuffer, mDecoder.get());
-
- if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- GVDM_LOG("Decoder did not return frame time");
- return NS_ERROR_UNEXPECTED;
- }
-
- if (mLastTime > timeUs) {
- GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
- return NS_ERROR_NOT_AVAILABLE;
- }
- mLastTime = timeUs;
-
- if (aBuffer->range_length() == 0) {
- // Some decoders may return spurious empty buffers that we just want to ignore
- // quoted from Android's AwesomePlayer.cpp
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- if (!aBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
- keyFrame = 0;
- }
-
- gfx::IntRect picture =
- mConfig.ScaledImageRect(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (aBuffer->graphicBuffer().get()) {
- data = CreateVideoDataFromGraphicBuffer(aBuffer, picture);
- if (data && !mNeedsCopyBuffer) {
- // RecycleCallback() will be responsible for release the buffer.
- autoRelease.forget();
- }
- mNeedsCopyBuffer = false;
- } else {
- data = CreateVideoDataFromDataBuffer(aBuffer, picture);
- }
-
- if (!data) {
- return NS_ERROR_UNEXPECTED;
- }
- // Fill necessary info.
- data->mOffset = aStreamOffset;
- data->mTime = timeUs;
- data->mKeyframe = keyFrame;
-
- data.forget(v);
- return NS_OK;
-}
-
-// Copy pixels from one planar YUV to another.
-static void
-CopyYUV(PlanarYCbCrData& aSource, PlanarYCbCrData& aDestination)
-{
- // Fill Y plane.
- uint8_t* srcY = aSource.mYChannel;
- gfx::IntSize ySize = aSource.mYSize;
- uint8_t* destY = aDestination.mYChannel;
- // Y plane.
- for (int i = 0; i < ySize.height; i++) {
- memcpy(destY, srcY, ySize.width);
- srcY += aSource.mYStride;
- destY += aDestination.mYStride;
- }
-
- // Fill UV plane.
- // Line start
- uint8_t* srcU = aSource.mCbChannel;
- uint8_t* srcV = aSource.mCrChannel;
- uint8_t* destU = aDestination.mCbChannel;
- uint8_t* destV = aDestination.mCrChannel;
-
- gfx::IntSize uvSize = aSource.mCbCrSize;
- for (int i = 0; i < uvSize.height; i++) {
- uint8_t* su = srcU;
- uint8_t* sv = srcV;
- uint8_t* du = destU;
- uint8_t* dv =destV;
- for (int j = 0; j < uvSize.width; j++) {
- *du++ = *su++;
- *dv++ = *sv++;
- // Move to next pixel.
- su += aSource.mCbSkip;
- sv += aSource.mCrSkip;
- du += aDestination.mCbSkip;
- dv += aDestination.mCrSkip;
- }
- // Move to next line.
- srcU += aSource.mCbCrStride;
- srcV += aSource.mCbCrStride;
- destU += aDestination.mCbCrStride;
- destV += aDestination.mCbCrStride;
- }
-}
-
-inline static int
-Align(int aX, int aAlign)
-{
- return (aX + aAlign - 1) & ~(aAlign - 1);
-}
-
-// Venus formats are doucmented in kernel/include/media/msm_media_info.h:
-// * Y_Stride : Width aligned to 128
-// * UV_Stride : Width aligned to 128
-// * Y_Scanlines: Height aligned to 32
-// * UV_Scanlines: Height/2 aligned to 16
-// * Total size = align((Y_Stride * Y_Scanlines
-// * + UV_Stride * UV_Scanlines + 4096), 4096)
-static void
-CopyVenus(uint8_t* aSrc, uint8_t* aDest, uint32_t aWidth, uint32_t aHeight)
-{
- size_t yStride = Align(aWidth, 128);
- uint8_t* s = aSrc;
- uint8_t* d = aDest;
- for (size_t i = 0; i < aHeight; i++) {
- memcpy(d, s, aWidth);
- s += yStride;
- d += yStride;
- }
- size_t uvStride = yStride;
- size_t uvLines = (aHeight + 1) / 2;
- size_t ySize = yStride * Align(aHeight, 32);
- s = aSrc + ySize;
- d = aDest + ySize;
- for (size_t i = 0; i < uvLines; i++) {
- memcpy(d, s, aWidth);
- s += uvStride;
- d += uvStride;
- }
-}
-
-static void
-CopyGraphicBuffer(sp<GraphicBuffer>& aSource, sp<GraphicBuffer>& aDestination)
-{
- void* srcPtr = nullptr;
- aSource->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &srcPtr);
- void* destPtr = nullptr;
- aDestination->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destPtr);
- MOZ_ASSERT(srcPtr && destPtr);
-
- // Build PlanarYCbCrData for source buffer.
- PlanarYCbCrData srcData;
- switch (aSource->getPixelFormat()) {
- case HAL_PIXEL_FORMAT_YV12: {
- // Android YV12 format is defined in system/core/include/system/graphics.h
- srcData.mYChannel = static_cast<uint8_t*>(srcPtr);
- srcData.mYSkip = 0;
- srcData.mYSize.width = aSource->getWidth();
- srcData.mYSize.height = aSource->getHeight();
- srcData.mYStride = aSource->getStride();
- // 4:2:0.
- srcData.mCbCrSize.width = srcData.mYSize.width / 2;
- srcData.mCbCrSize.height = srcData.mYSize.height / 2;
- srcData.mCrChannel = srcData.mYChannel + (srcData.mYStride * srcData.mYSize.height);
- // Aligned to 16 bytes boundary.
- srcData.mCbCrStride = Align(srcData.mYStride / 2, 16);
- srcData.mCrSkip = 0;
- srcData.mCbChannel = srcData.mCrChannel + (srcData.mCbCrStride * srcData.mCbCrSize.height);
- srcData.mCbSkip = 0;
-
- // Build PlanarYCbCrData for destination buffer.
- PlanarYCbCrData destData;
- destData.mYChannel = static_cast<uint8_t*>(destPtr);
- destData.mYSkip = 0;
- destData.mYSize.width = aDestination->getWidth();
- destData.mYSize.height = aDestination->getHeight();
- destData.mYStride = aDestination->getStride();
- // 4:2:0.
- destData.mCbCrSize.width = destData.mYSize.width / 2;
- destData.mCbCrSize.height = destData.mYSize.height / 2;
- destData.mCrChannel = destData.mYChannel + (destData.mYStride * destData.mYSize.height);
- // Aligned to 16 bytes boundary.
- destData.mCbCrStride = Align(destData.mYStride / 2, 16);
- destData.mCrSkip = 0;
- destData.mCbChannel = destData.mCrChannel + (destData.mCbCrStride * destData.mCbCrSize.height);
- destData.mCbSkip = 0;
-
- CopyYUV(srcData, destData);
- break;
- }
- case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- CopyVenus(static_cast<uint8_t*>(srcPtr),
- static_cast<uint8_t*>(destPtr),
- aSource->getWidth(),
- aSource->getHeight());
- break;
- default:
- NS_ERROR("Unsupported input gralloc image type. Should never be here.");
- }
-
-
- aSource->unlock();
- aDestination->unlock();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromGraphicBuffer(MediaBuffer* aSource,
- gfx::IntRect& aPicture)
-{
- sp<GraphicBuffer> srcBuffer(aSource->graphicBuffer());
- RefPtr<TextureClient> textureClient;
-
- if (mNeedsCopyBuffer) {
- // Copy buffer contents for bug 1199809.
- if (!mCopyAllocator) {
- RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
- mCopyAllocator = new TextureClientRecycleAllocator(bridge);
- }
- if (!mCopyAllocator) {
- GVDM_LOG("Create buffer allocator failed!");
- return nullptr;
- }
-
- gfx::IntSize size(srcBuffer->getWidth(), srcBuffer->getHeight());
- GonkTextureClientAllocationHelper helper(srcBuffer->getPixelFormat(), size);
- textureClient = mCopyAllocator->CreateOrRecycle(helper);
- if (!textureClient) {
- GVDM_LOG("Copy buffer allocation failed!");
- return nullptr;
- }
-
- sp<GraphicBuffer> destBuffer =
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
-
- CopyGraphicBuffer(srcBuffer, destBuffer);
- } else {
- textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get());
- textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
- static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource);
- }
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyIntoTextureClient(mConfig,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // No way to pass sample duration from muxer to
- // OMX codec, so we hardcode the duration here.
- textureClient,
- false, // Filled later by caller.
- -1,
- aPicture);
- return data.forget();
-}
-
-already_AddRefed<VideoData>
-GonkVideoDecoderManager::CreateVideoDataFromDataBuffer(MediaBuffer* aSource, gfx::IntRect& aPicture)
-{
- if (!aSource->data()) {
- GVDM_LOG("No data in Video Buffer!");
- return nullptr;
- }
- uint8_t *yuv420p_buffer = (uint8_t *)aSource->data();
- int32_t stride = mFrameInfo.mStride;
- int32_t slice_height = mFrameInfo.mSliceHeight;
-
- // Converts to OMX_COLOR_FormatYUV420Planar
- if (mFrameInfo.mColorFormat != OMX_COLOR_FormatYUV420Planar) {
- ARect crop;
- crop.top = 0;
- crop.bottom = mFrameInfo.mHeight;
- crop.left = 0;
- crop.right = mFrameInfo.mWidth;
- yuv420p_buffer = GetColorConverterBuffer(mFrameInfo.mWidth, mFrameInfo.mHeight);
- if (mColorConverter.convertDecoderOutputToI420(aSource->data(),
- mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) {
- GVDM_LOG("Color conversion failed!");
- return nullptr;
- }
- stride = mFrameInfo.mWidth;
- slice_height = mFrameInfo.mHeight;
- }
-
- size_t yuv420p_y_size = stride * slice_height;
- size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
- uint8_t *yuv420p_y = yuv420p_buffer;
- uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
- uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
-
- VideoData::YCbCrBuffer b;
- b.mPlanes[0].mData = yuv420p_y;
- b.mPlanes[0].mWidth = mFrameInfo.mWidth;
- b.mPlanes[0].mHeight = mFrameInfo.mHeight;
- b.mPlanes[0].mStride = stride;
- b.mPlanes[0].mOffset = 0;
- b.mPlanes[0].mSkip = 0;
-
- b.mPlanes[1].mData = yuv420p_u;
- b.mPlanes[1].mWidth = (mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[1].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[1].mStride = (stride + 1) / 2;
- b.mPlanes[1].mOffset = 0;
- b.mPlanes[1].mSkip = 0;
-
- b.mPlanes[2].mData = yuv420p_v;
- b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2;
- b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2;
- b.mPlanes[2].mStride = (stride + 1) / 2;
- b.mPlanes[2].mOffset = 0;
- b.mPlanes[2].mSkip = 0;
-
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyData(mConfig,
- mImageContainer,
- 0, // Filled later by caller.
- 0, // Filled later by caller.
- 1, // We don't know the duration.
- b,
- 0, // Filled later by caller.
- -1,
- aPicture);
-
- return data.forget();
-}
-
-bool
-GonkVideoDecoderManager::SetVideoFormat()
-{
- // read video metadata from MediaCodec
- sp<AMessage> codecFormat;
- if (mDecoder->getOutputFormat(&codecFormat) == OK) {
- AString mime;
- int32_t width = 0;
- int32_t height = 0;
- int32_t stride = 0;
- int32_t slice_height = 0;
- int32_t color_format = 0;
- int32_t crop_left = 0;
- int32_t crop_top = 0;
- int32_t crop_right = 0;
- int32_t crop_bottom = 0;
- if (!codecFormat->findString("mime", &mime) ||
- !codecFormat->findInt32("width", &width) ||
- !codecFormat->findInt32("height", &height) ||
- !codecFormat->findInt32("stride", &stride) ||
- !codecFormat->findInt32("slice-height", &slice_height) ||
- !codecFormat->findInt32("color-format", &color_format) ||
- !codecFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
- GVDM_LOG("Failed to find values");
- return false;
- }
- mFrameInfo.mWidth = width;
- mFrameInfo.mHeight = height;
- mFrameInfo.mStride = stride;
- mFrameInfo.mSliceHeight = slice_height;
- mFrameInfo.mColorFormat = color_format;
-
- nsIntSize displaySize(width, height);
- if (!IsValidVideoRegion(mConfig.mDisplay,
- mConfig.ScaledImageRect(width, height),
- displaySize)) {
- GVDM_LOG("It is not a valid region");
- return false;
- }
- return true;
- }
- GVDM_LOG("Fail to get output format");
- return false;
-}
-
-// Blocks until decoded sample is produced by the deoder.
-nsresult
-GonkVideoDecoderManager::Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutData)
-{
- aOutData = nullptr;
- status_t err;
- if (mDecoder == nullptr) {
- GVDM_LOG("Decoder is not inited");
- return NS_ERROR_UNEXPECTED;
- }
- MediaBuffer* outputBuffer = nullptr;
- err = mDecoder->Output(&outputBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
-
- switch (err) {
- case OK:
- {
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // Decoder outputs a empty video buffer, try again
- return NS_ERROR_NOT_AVAILABLE;
- } else if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create VideoData");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_OK;
- }
- case android::INFO_FORMAT_CHANGED:
- {
- // If the format changed, update our cached info.
- GVDM_LOG("Decoder format changed");
- if (!SetVideoFormat()) {
- return NS_ERROR_UNEXPECTED;
- }
- return Output(aStreamOffset, aOutData);
- }
- case android::INFO_OUTPUT_BUFFERS_CHANGED:
- {
- if (mDecoder->UpdateOutputBuffers()) {
- return Output(aStreamOffset, aOutData);
- }
- GVDM_LOG("Fails to update output buffers!");
- return NS_ERROR_FAILURE;
- }
- case -EAGAIN:
- {
-// GVDM_LOG("Need to try again!");
- return NS_ERROR_NOT_AVAILABLE;
- }
- case android::ERROR_END_OF_STREAM:
- {
- GVDM_LOG("Got the EOS frame!");
- RefPtr<VideoData> data;
- nsresult rv = CreateVideoData(outputBuffer, aStreamOffset, getter_AddRefs(data));
- if (rv == NS_ERROR_NOT_AVAILABLE) {
- // For EOS, no need to do any thing.
- return NS_ERROR_ABORT;
- }
- if (rv != NS_OK || data == nullptr) {
- GVDM_LOG("Failed to create video data");
- return NS_ERROR_UNEXPECTED;
- }
- aOutData = data;
- return NS_ERROR_ABORT;
- }
- case -ETIMEDOUT:
- {
- GVDM_LOG("Timeout. can try again next time");
- return NS_ERROR_UNEXPECTED;
- }
- default:
- {
- GVDM_LOG("Decoder failed, err=%d", err);
- return NS_ERROR_UNEXPECTED;
- }
- }
-
- return NS_OK;
-}
-
-void
-GonkVideoDecoderManager::codecReserved()
-{
- if (mInitPromise.IsEmpty()) {
- return;
- }
- GVDM_LOG("codecReserved");
- sp<AMessage> format = new AMessage;
- sp<Surface> surface;
- status_t rv = OK;
- // Fixed values
- GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mConfig.mMimeType.get(), mConfig.mImage.width, mConfig.mImage.height);
- format->setString("mime", mConfig.mMimeType.get());
- format->setInt32("width", mConfig.mImage.width);
- format->setInt32("height", mConfig.mImage.height);
- // Set the "moz-use-undequeued-bufs" to use the undeque buffers to accelerate
- // the video decoding.
- format->setInt32("moz-use-undequeued-bufs", 1);
- if (mNativeWindow != nullptr) {
-#if ANDROID_VERSION >= 21
- surface = new Surface(mGraphicBufferProducer);
-#else
- surface = new Surface(mNativeWindow->getBufferQueue());
-#endif
- }
- mDecoder->configure(format, surface, nullptr, 0);
- mDecoder->Prepare();
-
- if (mConfig.mMimeType.EqualsLiteral("video/mp4v-es")) {
- rv = mDecoder->Input(mConfig.mCodecSpecificConfig->Elements(),
- mConfig.mCodecSpecificConfig->Length(), 0,
- android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
- CODECCONFIG_TIMEOUT_US);
- }
-
- if (rv != OK) {
- GVDM_LOG("Failed to configure codec!!!!");
- mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
- return;
- }
-
- mInitPromise.Resolve(TrackType::kVideoTrack, __func__);
-}
-
-void
-GonkVideoDecoderManager::codecCanceled()
-{
- GVDM_LOG("codecCanceled");
- mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
-}
-
-// Called on GonkDecoderManager::mTaskLooper thread.
-void
-GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
-{
- switch (aMessage->what()) {
- case kNotifyPostReleaseBuffer:
- {
- ReleaseAllPendingVideoBuffers();
- break;
- }
-
- default:
- {
- GonkDecoderManager::onMessageReceived(aMessage);
- break;
- }
- }
-}
-
-uint8_t *
-GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
-{
- // Allocate a temporary YUV420Planer buffer.
- size_t yuv420p_y_size = aWidth * aHeight;
- size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
- size_t yuv420p_v_size = yuv420p_u_size;
- size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
- if (mColorConverterBufferSize != yuv420p_size) {
- mColorConverterBuffer = MakeUnique<uint8_t[]>(yuv420p_size);
- mColorConverterBufferSize = yuv420p_size;
- }
- return mColorConverterBuffer.get();
-}
-
-/* static */
-void
-GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
-{
- MOZ_ASSERT(aClient && !aClient->IsDead());
- GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
- GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData());
- aClient->ClearRecycleCallback();
- FenceHandle handle = aClient->GetAndResetReleaseFenceHandle();
- videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle);
-}
-
-void GonkVideoDecoderManager::PostReleaseVideoBuffer(
- android::MediaBuffer *aBuffer,
- FenceHandle aReleaseFence)
-{
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- if (aBuffer) {
- mPendingReleaseItems.AppendElement(ReleaseItem(aBuffer, aReleaseFence));
- }
- }
- sp<AMessage> notify =
- new AMessage(kNotifyPostReleaseBuffer, id());
- notify->post();
-
-}
-
-void GonkVideoDecoderManager::ReleaseAllPendingVideoBuffers()
-{
- nsTArray<ReleaseItem> releasingItems;
- {
- MutexAutoLock autoLock(mPendingReleaseItemsLock);
- releasingItems.AppendElements(mPendingReleaseItems);
- mPendingReleaseItems.Clear();
- }
-
- // Free all pending video buffers without holding mPendingReleaseItemsLock.
- size_t size = releasingItems.Length();
- for (size_t i = 0; i < size; i++) {
- RefPtr<FenceHandle::FdObj> fdObj = releasingItems[i].mReleaseFence.GetAndResetFdObj();
- sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
- fence->waitForever("GonkVideoDecoderManager");
- mDecoder->ReleaseMediaBuffer(releasingItems[i].mBuffer);
- }
- releasingItems.Clear();
-}
-
-} // namespace mozilla
diff --git a/dom/media/platforms/gonk/GonkVideoDecoderManager.h b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
deleted file mode 100644
index 343bb2a5c..000000000
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkVideoDecoderManager_h_)
-#define GonkVideoDecoderManager_h_
-
-#include "nsRect.h"
-#include "GonkMediaDataDecoder.h"
-#include "mozilla/RefPtr.h"
-#include "I420ColorConverterHelper.h"
-#include "MediaCodecProxy.h"
-#include "GonkNativeWindow.h"
-#include "mozilla/layers/FenceUtils.h"
-#include "mozilla/UniquePtr.h"
-#include <ui/Fence.h>
-
-using namespace android;
-
-namespace android {
-class MediaBuffer;
-struct MOZ_EXPORT AString;
-class GonkNativeWindow;
-} // namespace android
-
-namespace mozilla {
-
-namespace layers {
-class TextureClient;
-class TextureClientRecycleAllocator;
-} // namespace mozilla::layers
-
-class GonkVideoDecoderManager : public GonkDecoderManager {
-typedef android::MediaCodecProxy MediaCodecProxy;
-typedef mozilla::layers::TextureClient TextureClient;
-
-public:
- GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
- const VideoInfo& aConfig);
-
- virtual ~GonkVideoDecoderManager();
-
- RefPtr<InitPromise> Init() override;
-
- nsresult Output(int64_t aStreamOffset,
- RefPtr<MediaData>& aOutput) override;
-
- nsresult Shutdown() override;
-
- const char* GetDescriptionName() const override
- {
- return "gonk video decoder";
- }
-
- static void RecycleCallback(TextureClient* aClient, void* aClosure);
-
-protected:
- // Bug 1199809: workaround to avoid sending the graphic buffer by making a
- // copy of output buffer after calling flush(). Bug 1203859 was created to
- // reimplementing Gonk PDM on top of OpenMax IL directly. Its buffer
- // management will work better with Gecko and solve problems like this.
- void ProcessFlush() override
- {
- mNeedsCopyBuffer = true;
- GonkDecoderManager::ProcessFlush();
- }
-
-private:
- struct FrameInfo
- {
- int32_t mWidth = 0;
- int32_t mHeight = 0;
- int32_t mStride = 0;
- int32_t mSliceHeight = 0;
- int32_t mColorFormat = 0;
- int32_t mCropLeft = 0;
- int32_t mCropTop = 0;
- int32_t mCropRight = 0;
- int32_t mCropBottom = 0;
- };
-
- void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
-
- bool SetVideoFormat();
-
- nsresult CreateVideoData(MediaBuffer* aBuffer, int64_t aStreamOffset, VideoData** aOutData);
- already_AddRefed<VideoData> CreateVideoDataFromGraphicBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
- already_AddRefed<VideoData> CreateVideoDataFromDataBuffer(android::MediaBuffer* aSource,
- gfx::IntRect& aPicture);
-
- uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
-
- // For codec resource management
- void codecReserved();
- void codecCanceled();
-
- void ReleaseAllPendingVideoBuffers();
- void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
- layers::FenceHandle mReleaseFence);
-
- VideoInfo mConfig;
-
- RefPtr<layers::ImageContainer> mImageContainer;
- RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
-
- MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
- FrameInfo mFrameInfo;
-
- // color converter
- android::I420ColorConverterHelper mColorConverter;
- UniquePtr<uint8_t[]> mColorConverterBuffer;
- size_t mColorConverterBufferSize;
-
- android::sp<android::GonkNativeWindow> mNativeWindow;
-#if ANDROID_VERSION >= 21
- android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer;
-#endif
-
- enum {
- kNotifyPostReleaseBuffer = 'nprb',
- };
-
- struct ReleaseItem {
- ReleaseItem(android::MediaBuffer* aBuffer, layers::FenceHandle& aFence)
- : mBuffer(aBuffer)
- , mReleaseFence(aFence) {}
- android::MediaBuffer* mBuffer;
- layers::FenceHandle mReleaseFence;
- };
- nsTArray<ReleaseItem> mPendingReleaseItems;
-
- // The lock protects mPendingReleaseItems.
- Mutex mPendingReleaseItemsLock;
-
- // This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue().
- // It is for codec resource mangement, decoding task should not dispatch to it.
- RefPtr<TaskQueue> mReaderTaskQueue;
-
- // Bug 1199809: do we need to make a copy of output buffer? Used only when
- // the decoder outputs graphic buffers.
- bool mNeedsCopyBuffer;
-};
-
-} // namespace mozilla
-
-#endif // GonkVideoDecoderManager_h_
diff --git a/dom/media/platforms/gonk/moz.build b/dom/media/platforms/gonk/moz.build
deleted file mode 100644
index 014594977..000000000
--- a/dom/media/platforms/gonk/moz.build
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
- 'GonkAudioDecoderManager.h',
- 'GonkDecoderModule.h',
- 'GonkMediaDataDecoder.h',
- 'GonkVideoDecoderManager.h',
-]
-UNIFIED_SOURCES += [
- 'GonkAudioDecoderManager.cpp',
- 'GonkDecoderModule.cpp',
- 'GonkMediaDataDecoder.cpp',
- 'GonkVideoDecoderManager.cpp',
-]
-LOCAL_INCLUDES += [
- '/dom/media/omx/',
-]
-include('/ipc/chromium/chromium-config.mozbuild')
-
-# Suppress some GCC/clang warnings being treated as errors:
-# - about attributes on forward declarations for types that are already
-# defined, which complains about an important MOZ_EXPORT for android::AString
-# - about multi-character constants which are used in codec-related code
-if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
- CXXFLAGS += [
- '-Wno-error=attributes',
- '-Wno-error=multichar'
- ]
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',]
-]
diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build
index 310820c91..3fb0cc842 100644
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -70,10 +70,6 @@ if CONFIG['MOZ_APPLEMEDIA']:
'-framework AudioToolbox',
]
-if CONFIG['MOZ_GONK_MEDIACODEC']:
- DEFINES['MOZ_GONK_MEDIACODEC'] = True
- DIRS += ['gonk']
-
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp b/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
deleted file mode 100644
index 870566cf5..000000000
--- a/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "GonkOmxPlatformLayer.h"
-
-#include <binder/MemoryDealer.h>
-#include <cutils/properties.h>
-#include <media/IOMX.h>
-#include <media/stagefright/MediaCodecList.h>
-#include <utils/List.h>
-
-#include "mozilla/Monitor.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/GrallocTextureClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
-
-#include "ImageContainer.h"
-#include "MediaInfo.h"
-#include "OmxDataDecoder.h"
-
-
-#ifdef LOG
-#undef LOG
-#endif
-
-#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("GonkOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
-
-#define CHECK_ERR(err) \
- if (err != OK) { \
- LOG("error %d at %s", err, __func__); \
- return NS_ERROR_FAILURE; \
- } \
-
-// Android proprietary value.
-#define ANDROID_OMX_VIDEO_CodingVP8 (static_cast<OMX_VIDEO_CODINGTYPE>(9))
-
-using namespace android;
-
-namespace mozilla {
-
-// In Gonk, the software component name has prefix "OMX.google". It needs to
-// have a way to use hardware codec first.
-bool IsSoftwareCodec(const char* aComponentName)
-{
- nsAutoCString str(aComponentName);
- return (str.Find(NS_LITERAL_CSTRING("OMX.google.")) == -1 ? false : true);
-}
-
-bool IsInEmulator()
-{
- char propQemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", propQemu, "");
- return !strncmp(propQemu, "1", 1);
-}
-
-class GonkOmxObserver : public BnOMXObserver {
-public:
- void onMessage(const omx_message& aMsg)
- {
- switch (aMsg.type) {
- case omx_message::EVENT:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (self->mClient && self->mClient->Event(aMsg.u.event_data.event,
- aMsg.u.event_data.data1,
- aMsg.u.event_data.data2))
- {
- return;
- }
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- case omx_message::EMPTY_BUFFER_DONE:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (!self->mPromiseLayer) {
- return;
- }
- BufferData::BufferID id = (BufferData::BufferID)aMsg.u.buffer_data.buffer;
- self->mPromiseLayer->EmptyFillBufferDone(OMX_DirInput, id);
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- case omx_message::FILL_BUFFER_DONE:
- {
- sp<GonkOmxObserver> self = this;
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aMsg] () {
- if (!self->mPromiseLayer) {
- return;
- }
-
- // TODO: these codes look a little ugly, it'd be better to improve them.
- RefPtr<BufferData> buf;
- BufferData::BufferID id = (BufferData::BufferID)aMsg.u.extended_buffer_data.buffer;
- buf = self->mPromiseLayer->FindAndRemoveBufferHolder(OMX_DirOutput, id);
- MOZ_RELEASE_ASSERT(buf);
- GonkBufferData* gonkBuffer = static_cast<GonkBufferData*>(buf.get());
-
- // Copy the critical information to local buffer.
- if (gonkBuffer->IsLocalBuffer()) {
- gonkBuffer->mBuffer->nOffset = aMsg.u.extended_buffer_data.range_offset;
- gonkBuffer->mBuffer->nFilledLen = aMsg.u.extended_buffer_data.range_length;
- gonkBuffer->mBuffer->nFlags = aMsg.u.extended_buffer_data.flags;
- gonkBuffer->mBuffer->nTimeStamp = aMsg.u.extended_buffer_data.timestamp;
- }
- self->mPromiseLayer->EmptyFillBufferDone(OMX_DirOutput, buf);
- });
- mTaskQueue->Dispatch(r.forget());
- break;
- }
- default:
- {
- LOG("Unhandle event %d", aMsg.type);
- }
- }
- }
-
- void Shutdown()
- {
- MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
- mPromiseLayer = nullptr;
- mClient = nullptr;
- }
-
- GonkOmxObserver(TaskQueue* aTaskQueue, OmxPromiseLayer* aPromiseLayer, OmxDataDecoder* aDataDecoder)
- : mTaskQueue(aTaskQueue)
- , mPromiseLayer(aPromiseLayer)
- , mClient(aDataDecoder)
- {}
-
-protected:
- RefPtr<TaskQueue> mTaskQueue;
- // TODO:
- // we should combine both event handlers into one. And we should provide
- // an unified way for event handling in OmxPlatformLayer class.
- RefPtr<OmxPromiseLayer> mPromiseLayer;
- RefPtr<OmxDataDecoder> mClient;
-};
-
-// This class allocates Gralloc buffer and manages TextureClient's recycle.
-class GonkTextureClientRecycleHandler : public layers::ITextureClientRecycleAllocator
-{
- typedef MozPromise<layers::TextureClient*, nsresult, /* IsExclusive = */ true> TextureClientRecyclePromise;
-
-public:
- GonkTextureClientRecycleHandler(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
- : ITextureClientRecycleAllocator()
- , mMonitor("GonkTextureClientRecycleHandler")
- {
- RefPtr<layers::ImageBridgeChild> bridge = layers::ImageBridgeChild::GetSingleton();
-
- // Allocate Gralloc texture memory.
- layers::GrallocTextureData* textureData =
- layers::GrallocTextureData::Create(gfx::IntSize(aDef.nFrameWidth, aDef.nFrameHeight),
- aDef.eColorFormat,
- gfx::BackendType::NONE,
- GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN,
- bridge);
-
- mGraphBuffer = textureData->GetGraphicBuffer();
- MOZ_ASSERT(mGraphBuffer.get());
-
- mTextureClient =
- layers::TextureClient::CreateWithData(textureData,
- layers::TextureFlags::DEALLOCATE_CLIENT | layers::TextureFlags::RECYCLE,
- bridge);
- MOZ_ASSERT(mTextureClient);
-
- mPromise.SetMonitor(&mMonitor);
- }
-
- RefPtr<TextureClientRecyclePromise> WaitforRecycle()
- {
- MonitorAutoLock lock(mMonitor);
- MOZ_ASSERT(!!mGraphBuffer.get());
-
- mTextureClient->SetRecycleAllocator(this);
- return mPromise.Ensure(__func__);
- }
-
- // DO NOT use smart pointer to receive TextureClient; otherwise it will
- // distrupt the reference count.
- layers::TextureClient* GetTextureClient()
- {
- return mTextureClient;
- }
-
- GraphicBuffer* GetGraphicBuffer()
- {
- MonitorAutoLock lock(mMonitor);
- return mGraphBuffer.get();
- }
-
- // This function is called from layers thread.
- void RecycleTextureClient(layers::TextureClient* aClient) override
- {
- MOZ_ASSERT(mTextureClient == aClient);
-
- // Clearing the recycle allocator drops a reference, so make sure we stay alive
- // for the duration of this function.
- RefPtr<GonkTextureClientRecycleHandler> kungFuDeathGrip(this);
- aClient->SetRecycleAllocator(nullptr);
-
- {
- MonitorAutoLock lock(mMonitor);
- mPromise.ResolveIfExists(mTextureClient, __func__);
- }
- }
-
- void Shutdown()
- {
- MonitorAutoLock lock(mMonitor);
-
- mPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
-
- // DO NOT clear TextureClient here.
- // The ref count could be 1 and RecycleCallback will be called if we clear
- // the ref count here. That breaks the whole mechanism. (RecycleCallback
- // should be called from layers)
- mGraphBuffer = nullptr;
- }
-
-private:
- // Because TextureClient calls RecycleCallbackl when ref count is 1, so we
- // should hold only one reference here and use raw pointer when out of this
- // class.
- RefPtr<layers::TextureClient> mTextureClient;
-
- // It is protected by mMonitor.
- sp<android::GraphicBuffer> mGraphBuffer;
-
- // It is protected by mMonitor.
- MozPromiseHolder<TextureClientRecyclePromise> mPromise;
-
- Monitor mMonitor;
-};
-
-GonkBufferData::GonkBufferData(bool aLiveInLocal,
- GonkOmxPlatformLayer* aGonkPlatformLayer)
- : BufferData(nullptr)
- , mId(0)
- , mGonkPlatformLayer(aGonkPlatformLayer)
-{
- if (!aLiveInLocal) {
- mMirrorBuffer = new OMX_BUFFERHEADERTYPE;
- PodZero(mMirrorBuffer.get());
- mBuffer = mMirrorBuffer.get();
- }
-}
-
-void
-GonkBufferData::ReleaseBuffer()
-{
- if (mTextureClientRecycleHandler) {
- mTextureClientRecycleHandler->Shutdown();
- mTextureClientRecycleHandler = nullptr;
- }
-}
-
-nsresult
-GonkBufferData::InitSharedMemory(android::IMemory* aMemory)
-{
- MOZ_RELEASE_ASSERT(mMirrorBuffer.get());
-
- // aMemory is a IPC memory, it is safe to use it here.
- mBuffer->pBuffer = (OMX_U8*)aMemory->pointer();
- mBuffer->nAllocLen = aMemory->size();
- return NS_OK;
-}
-
-nsresult
-GonkBufferData::InitLocalBuffer(IOMX::buffer_id aId)
-{
- MOZ_RELEASE_ASSERT(!mMirrorBuffer.get());
-
- mBuffer = (OMX_BUFFERHEADERTYPE*)aId;
- return NS_OK;
-}
-
-nsresult
-GonkBufferData::InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef)
-{
- mTextureClientRecycleHandler = new GonkTextureClientRecycleHandler(aDef);
-
- if (!mTextureClientRecycleHandler->GetGraphicBuffer()) {
- return NS_ERROR_FAILURE;
- }
-
- return NS_OK;
-}
-
-already_AddRefed<MediaData>
-GonkBufferData::GetPlatformMediaData()
-{
- if (mGonkPlatformLayer->GetTrackInfo()->GetAsAudioInfo()) {
- // This is audio decoding.
- return nullptr;
- }
-
- if (!mTextureClientRecycleHandler) {
- // There is no GraphicBuffer, it should fallback to normal YUV420 VideoData.
- return nullptr;
- }
-
- VideoInfo info(*mGonkPlatformLayer->GetTrackInfo()->GetAsVideoInfo());
- RefPtr<VideoData> data =
- VideoData::CreateAndCopyIntoTextureClient(info,
- 0,
- mBuffer->nTimeStamp,
- 1,
- mTextureClientRecycleHandler->GetTextureClient(),
- false,
- 0,
- info.ImageRect());
- LOG("%p, disp width %d, height %d, pic width %d, height %d, time %ld",
- this, info.mDisplay.width, info.mDisplay.height,
- info.mImage.width, info.mImage.height, mBuffer->nTimeStamp);
-
- // Get TextureClient Promise here to wait for resolved.
- RefPtr<GonkBufferData> self(this);
- mTextureClientRecycleHandler->WaitforRecycle()
- ->Then(mGonkPlatformLayer->GetTaskQueue(), __func__,
- [self] () {
- self->mPromise.ResolveIfExists(self, __func__);
- },
- [self] () {
- OmxBufferFailureHolder failure(OMX_ErrorUndefined, self);
- self->mPromise.RejectIfExists(failure, __func__);
- });
-
- return data.forget();
-}
-
-GonkOmxPlatformLayer::GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
- OmxPromiseLayer* aPromiseLayer,
- TaskQueue* aTaskQueue,
- layers::ImageContainer* aImageContainer)
- : mTaskQueue(aTaskQueue)
- , mImageContainer(aImageContainer)
- , mNode(0)
-{
- mOmxObserver = new GonkOmxObserver(mTaskQueue, aPromiseLayer, aDataDecoder);
-}
-
-nsresult
-GonkOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType,
- BUFFERLIST* aBufferList)
-{
- MOZ_ASSERT(!mMemoryDealer[aType].get());
-
- // Get port definition.
- OMX_PARAM_PORTDEFINITIONTYPE def;
- nsTArray<uint32_t> portindex;
- GetPortIndices(portindex);
- for (auto idx : portindex) {
- InitOmxParameter(&def);
- def.nPortIndex = idx;
-
- OMX_ERRORTYPE err = GetParameter(OMX_IndexParamPortDefinition,
- &def,
- sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
- if (err != OMX_ErrorNone) {
- return NS_ERROR_FAILURE;
- } else if (def.eDir == aType) {
- LOG("Get OMX_IndexParamPortDefinition: port: %d, type: %d", def.nPortIndex, def.eDir);
- break;
- }
- }
-
- size_t t = 0;
-
- // Configure video output GraphicBuffer for video decoding acceleration.
- bool useGralloc = false;
- if (aType == OMX_DirOutput && mQuirks.test(kRequiresAllocateBufferOnOutputPorts) &&
- (def.eDomain == OMX_PortDomainVideo)) {
- if (NS_FAILED(EnableOmxGraphicBufferPort(def))) {
- return NS_ERROR_FAILURE;
- }
-
- LOG("Enable OMX GraphicBuffer port, number %d, width %d, height %d", def.nBufferCountActual,
- def.format.video.nFrameWidth, def.format.video.nFrameHeight);
-
- useGralloc = true;
-
- t = 1024; // MemoryDealer doesn't like 0, it's just for MemoryDealer happy.
- } else {
- t = def.nBufferCountActual * def.nBufferSize;
- LOG("Buffer count %d, buffer size %d", def.nBufferCountActual, def.nBufferSize);
- }
-
- bool liveinlocal = mOmx->livesLocally(mNode, getpid());
-
- // MemoryDealer is a IPC buffer allocator in Gonk because IOMX is actually
- // lives in mediaserver.
- mMemoryDealer[aType] = new MemoryDealer(t, "Gecko-OMX");
- for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
- RefPtr<GonkBufferData> buffer;
- IOMX::buffer_id bufferID;
- status_t st;
- nsresult rv;
-
- buffer = new GonkBufferData(liveinlocal, this);
- if (useGralloc) {
- // Buffer is lived remotely. Use GraphicBuffer for decoded video frame display.
- rv = buffer->InitGraphicBuffer(def.format.video);
- NS_ENSURE_SUCCESS(rv, rv);
- st = mOmx->useGraphicBuffer(mNode,
- def.nPortIndex,
- buffer->mTextureClientRecycleHandler->GetGraphicBuffer(),
- &bufferID);
- CHECK_ERR(st);
- } else {
- sp<IMemory> mem = mMemoryDealer[aType]->allocate(def.nBufferSize);
- MOZ_ASSERT(mem.get());
-
- if ((mQuirks.test(kRequiresAllocateBufferOnInputPorts) && aType == OMX_DirInput) ||
- (mQuirks.test(kRequiresAllocateBufferOnOutputPorts) && aType == OMX_DirOutput)) {
- // Buffer is lived remotely. We allocate a local OMX_BUFFERHEADERTYPE
- // as the mirror of the remote OMX_BUFFERHEADERTYPE.
- st = mOmx->allocateBufferWithBackup(mNode, aType, mem, &bufferID);
- CHECK_ERR(st);
- rv = buffer->InitSharedMemory(mem.get());
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Buffer is lived locally, bufferID is the actually OMX_BUFFERHEADERTYPE
- // pointer.
- st = mOmx->useBuffer(mNode, aType, mem, &bufferID);
- CHECK_ERR(st);
- rv = buffer->InitLocalBuffer(bufferID);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- rv = buffer->SetBufferId(bufferID);
- NS_ENSURE_SUCCESS(rv, rv);
-
- aBufferList->AppendElement(buffer);
- }
-
- return NS_OK;
-}
-
-nsresult
-GonkOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType,
- BUFFERLIST* aBufferList)
-{
- status_t st;
- uint32_t len = aBufferList->Length();
- for (uint32_t i = 0; i < len; i++) {
- GonkBufferData* buffer = static_cast<GonkBufferData*>(aBufferList->ElementAt(i).get());
- IOMX::buffer_id id = (OMX_BUFFERHEADERTYPE*) buffer->ID();
- st = mOmx->freeBuffer(mNode, aType, id);
- if (st != OK) {
- return NS_ERROR_FAILURE;
- }
- buffer->ReleaseBuffer();
- }
- aBufferList->Clear();
- mMemoryDealer[aType].clear();
-
- return NS_OK;
-}
-
-nsresult
-GonkOmxPlatformLayer::EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef)
-{
- status_t st;
-
- st = mOmx->enableGraphicBuffers(mNode, aDef.nPortIndex, OMX_TRUE);
- CHECK_ERR(st);
-
- return NS_OK;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::GetState(OMX_STATETYPE* aType)
-{
- return (OMX_ERRORTYPE)mOmx->getState(mNode, aType);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize)
-{
- return (OMX_ERRORTYPE)mOmx->getParameter(mNode,
- aParamIndex,
- aComponentParameterStructure,
- aComponentParameterSize);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize)
-{
- return (OMX_ERRORTYPE)mOmx->setParameter(mNode,
- aParamIndex,
- aComponentParameterStructure,
- aComponentParameterSize);
-}
-
-nsresult
-GonkOmxPlatformLayer::Shutdown()
-{
- mOmx->freeNode(mNode);
- mOmxObserver->Shutdown();
- mOmxObserver = nullptr;
- mOmxClient.disconnect();
-
- return NS_OK;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo)
-{
- mInfo = aInfo;
- status_t err = mOmxClient.connect();
- if (err != OK) {
- return OMX_ErrorUndefined;
- }
- mOmx = mOmxClient.interface();
- if (!mOmx.get()) {
- return OMX_ErrorUndefined;
- }
-
- LOG("find componenet for mime type %s", mInfo->mMimeType.Data());
-
- nsTArray<ComponentInfo> components;
- if (FindComponents(mInfo->mMimeType, &components)) {
- for (auto comp : components) {
- if (LoadComponent(comp)) {
- return OMX_ErrorNone;
- }
- }
- }
-
- LOG("no component is loaded");
- return OMX_ErrorUndefined;
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::EmptyThisBuffer(BufferData* aData)
-{
- return (OMX_ERRORTYPE)mOmx->emptyBuffer(mNode,
- (IOMX::buffer_id)aData->ID(),
- aData->mBuffer->nOffset,
- aData->mBuffer->nFilledLen,
- aData->mBuffer->nFlags,
- aData->mBuffer->nTimeStamp);
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::FillThisBuffer(BufferData* aData)
-{
- return (OMX_ERRORTYPE)mOmx->fillBuffer(mNode, (IOMX::buffer_id)aData->ID());
-}
-
-OMX_ERRORTYPE
-GonkOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd,
- OMX_U32 aParam1,
- OMX_PTR aCmdData)
-{
- return (OMX_ERRORTYPE)mOmx->sendCommand(mNode, aCmd, aParam1);
-}
-
-bool
-GonkOmxPlatformLayer::LoadComponent(const ComponentInfo& aComponent)
-{
- status_t err = mOmx->allocateNode(aComponent.mName, mOmxObserver, &mNode);
- if (err == OK) {
- mQuirks = aComponent.mQuirks;
- LOG("Load OpenMax component %s, alloc input %d, alloc output %d, live locally %d",
- aComponent.mName, mQuirks.test(kRequiresAllocateBufferOnInputPorts),
- mQuirks.test(kRequiresAllocateBufferOnOutputPorts),
- mOmx->livesLocally(mNode, getpid()));
- return true;
- }
- return false;
-}
-
-layers::ImageContainer*
-GonkOmxPlatformLayer::GetImageContainer()
-{
- return mImageContainer;
-}
-
-const TrackInfo*
-GonkOmxPlatformLayer::GetTrackInfo()
-{
- return mInfo;
-}
-
-bool
-GonkOmxPlatformLayer::FindComponents(const nsACString& aMimeType,
- nsTArray<ComponentInfo>* aComponents)
-{
- static const MediaCodecList* codecs = MediaCodecList::getInstance();
-
- bool useHardwareCodecOnly = false;
-
- // H264 and H263 has different profiles, software codec doesn't support high profile.
- // So we use hardware codec only.
- if (!IsInEmulator() &&
- (aMimeType.EqualsLiteral("video/avc") ||
- aMimeType.EqualsLiteral("video/mp4") ||
- aMimeType.EqualsLiteral("video/mp4v-es") ||
- aMimeType.EqualsLiteral("video/3gp"))) {
- useHardwareCodecOnly = true;
- }
-
- const char* mime = aMimeType.Data();
- // Translate VP8 MIME type to Android format.
- if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
- mime = "video/x-vnd.on2.vp8";
- }
-
- size_t start = 0;
- bool found = false;
- while (true) {
- ssize_t index = codecs->findCodecByType(mime, false /* encoder */, start);
- if (index < 0) {
- break;
- }
- start = index + 1;
-
- const char* name = codecs->getCodecName(index);
- if (IsSoftwareCodec(name) && useHardwareCodecOnly) {
- continue;
- }
-
- found = true;
-
- if (!aComponents) {
- continue;
- }
- ComponentInfo* comp = aComponents->AppendElement();
- comp->mName = name;
- if (codecs->codecHasQuirk(index, "requires-allocate-on-input-ports")) {
- comp->mQuirks.set(kRequiresAllocateBufferOnInputPorts);
- }
- if (codecs->codecHasQuirk(index, "requires-allocate-on-output-ports")) {
- comp->mQuirks.set(kRequiresAllocateBufferOnOutputPorts);
- }
- }
-
- return found;
-}
-
-OMX_VIDEO_CODINGTYPE
-GonkOmxPlatformLayer::CompressionFormat()
-{
- MOZ_ASSERT(mInfo);
-
- return mInfo->mMimeType.EqualsLiteral("video/webm; codecs=vp8") ?
- ANDROID_OMX_VIDEO_CodingVP8 : OmxPlatformLayer::CompressionFormat();
-}
-
-} // mozilla
diff --git a/dom/media/platforms/omx/GonkOmxPlatformLayer.h b/dom/media/platforms/omx/GonkOmxPlatformLayer.h
deleted file mode 100644
index aaa8c654d..000000000
--- a/dom/media/platforms/omx/GonkOmxPlatformLayer.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(GonkOmxPlatformLayer_h_)
-#define GonkOmxPlatformLayer_h_
-
-#pragma GCC visibility push(default)
-
-#include <bitset>
-
-#include <utils/RefBase.h>
-#include <media/stagefright/OMXClient.h>
-#include "nsAutoPtr.h"
-
-#include "OMX_Component.h"
-
-#include "OmxPlatformLayer.h"
-
-class nsACString;
-
-namespace android {
-class IMemory;
-class MemoryDealer;
-}
-
-namespace mozilla {
-
-class GonkOmxObserver;
-class GonkOmxPlatformLayer;
-class GonkTextureClientRecycleHandler;
-
-/*
- * Due to Android's omx node could live in local process (client) or remote
- * process (mediaserver). And there are 3 kinds of buffer in Android OMX.
- *
- * 1.
- * When buffer is in local process, the IOMX::buffer_id is OMX_BUFFERHEADERTYPE
- * pointer actually, it is safe to use it directly.
- *
- * 2.
- * When buffer is in remote process, the OMX_BUFFERHEADERTYPE pointer is 'IN' the
- * remote process. It can't be used in local process, so here it allocates a
- * local OMX_BUFFERHEADERTYPE. The raw/decoded data is in the android shared
- * memory, IMemory.
- *
- * 3.
- * When buffer is in remote process for the display output port. It uses
- * GraphicBuffer to accelerate the decoding and display.
- *
- */
-class GonkBufferData : public OmxPromiseLayer::BufferData {
-protected:
- virtual ~GonkBufferData() {}
-
-public:
- GonkBufferData(bool aLiveInLocal,
- GonkOmxPlatformLayer* aLayer);
-
- BufferID ID() override
- {
- return mId;
- }
-
- already_AddRefed<MediaData> GetPlatformMediaData() override;
-
- bool IsLocalBuffer()
- {
- return !!mMirrorBuffer.get();
- }
-
- void ReleaseBuffer();
-
- nsresult SetBufferId(android::IOMX::buffer_id aId)
- {
- mId = aId;
- return NS_OK;
- }
-
- // The mBuffer is in local process. And aId is actually the OMX_BUFFERHEADERTYPE
- // pointer. It doesn't need a mirror buffer.
- nsresult InitLocalBuffer(android::IOMX::buffer_id aId);
-
- // aMemory is an IPC based memory which will be used as the pBuffer in
- // mBuffer. And the mBuffer will be the mirror OMX_BUFFERHEADERTYPE
- // of the one in the remote process.
- nsresult InitSharedMemory(android::IMemory* aMemory);
-
- // GraphicBuffer is for video decoding acceleration on output port.
- // Then mBuffer is the mirror OMX_BUFFERHEADERTYPE of the one in the remote
- // process.
- nsresult InitGraphicBuffer(OMX_VIDEO_PORTDEFINITIONTYPE& aDef);
-
- // Android OMX uses this id to pass the buffer between OMX component and
- // client.
- android::IOMX::buffer_id mId;
-
- // mMirrorBuffer are used only when the omx node is in mediaserver.
- // Due to IPC problem, the mId is the OMX_BUFFERHEADERTYPE address in mediaserver.
- // It can't mapping to client process, so we need a local OMX_BUFFERHEADERTYPE
- // here to mirror the remote OMX_BUFFERHEADERTYPE in mediaserver.
- nsAutoPtr<OMX_BUFFERHEADERTYPE> mMirrorBuffer;
-
- // It creates GraphicBuffer and manages TextureClient.
- RefPtr<GonkTextureClientRecycleHandler> mTextureClientRecycleHandler;
-
- GonkOmxPlatformLayer* mGonkPlatformLayer;
-};
-
-class GonkOmxPlatformLayer : public OmxPlatformLayer {
-public:
- enum {
- kRequiresAllocateBufferOnInputPorts = 0,
- kRequiresAllocateBufferOnOutputPorts,
- QUIRKS,
- };
- typedef std::bitset<QUIRKS> Quirks;
-
- struct ComponentInfo {
- const char* mName;
- Quirks mQuirks;
- };
-
- GonkOmxPlatformLayer(OmxDataDecoder* aDataDecoder,
- OmxPromiseLayer* aPromiseLayer,
- TaskQueue* aTaskQueue,
- layers::ImageContainer* aImageContainer);
-
- nsresult AllocateOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
-
- nsresult ReleaseOmxBuffer(OMX_DIRTYPE aType, BUFFERLIST* aBufferList) override;
-
- OMX_ERRORTYPE GetState(OMX_STATETYPE* aType) override;
-
- OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE aParamIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize) override;
-
- OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE nIndex,
- OMX_PTR aComponentParameterStructure,
- OMX_U32 aComponentParameterSize) override;
-
- OMX_ERRORTYPE InitOmxToStateLoaded(const TrackInfo* aInfo) override;
-
- OMX_ERRORTYPE EmptyThisBuffer(BufferData* aData) override;
-
- OMX_ERRORTYPE FillThisBuffer(BufferData* aData) override;
-
- OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE aCmd,
- OMX_U32 aParam1,
- OMX_PTR aCmdData) override;
-
- nsresult Shutdown() override;
-
- static bool FindComponents(const nsACString& aMimeType,
- nsTArray<ComponentInfo>* aComponents = nullptr);
-
- // Android/QCOM decoder uses its own OMX_VIDEO_CodingVP8 definition in
- // frameworks/native/media/include/openmax/OMX_Video.h, not the one defined
- // in OpenMAX v1.1.2 OMX_VideoExt.h
- OMX_VIDEO_CODINGTYPE CompressionFormat() override;
-
-protected:
- friend GonkBufferData;
-
- layers::ImageContainer* GetImageContainer();
-
- const TrackInfo* GetTrackInfo();
-
- TaskQueue* GetTaskQueue()
- {
- return mTaskQueue;
- }
-
- nsresult EnableOmxGraphicBufferPort(OMX_PARAM_PORTDEFINITIONTYPE& aDef);
-
- bool LoadComponent(const ComponentInfo& aComponent);
-
- friend class GonkOmxObserver;
-
- RefPtr<TaskQueue> mTaskQueue;
-
- RefPtr<layers::ImageContainer> mImageContainer;
-
- // OMX_DirInput is 0, OMX_DirOutput is 1.
- android::sp<android::MemoryDealer> mMemoryDealer[2];
-
- android::sp<GonkOmxObserver> mOmxObserver;
-
- android::sp<android::IOMX> mOmx;
-
- android::IOMX::node_id mNode;
-
- android::OMXClient mOmxClient;
-
- Quirks mQuirks;
-};
-
-}
-
-#pragma GCC visibility pop
-
-#endif // GonkOmxPlatformLayer_h_
diff --git a/dom/media/platforms/omx/OmxPlatformLayer.cpp b/dom/media/platforms/omx/OmxPlatformLayer.cpp
index d1f43144d..039b4a22f 100644
--- a/dom/media/platforms/omx/OmxPlatformLayer.cpp
+++ b/dom/media/platforms/omx/OmxPlatformLayer.cpp
@@ -8,11 +8,6 @@
#include "OMX_VideoExt.h" // For VP8.
-#if defined(MOZ_WIDGET_GONK) && (ANDROID_VERSION == 20 || ANDROID_VERSION == 19)
-#define OMX_PLATFORM_GONK
-#include "GonkOmxPlatformLayer.h"
-#endif
-
#include "VPXDecoder.h"
#ifdef LOG
diff --git a/dom/media/platforms/omx/moz.build b/dom/media/platforms/omx/moz.build
index 9f641d937..661e280e0 100644
--- a/dom/media/platforms/omx/moz.build
+++ b/dom/media/platforms/omx/moz.build
@@ -21,29 +21,6 @@ LOCAL_INCLUDES += [
include('/ipc/chromium/chromium-config.mozbuild')
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and (CONFIG['ANDROID_VERSION'] == '19' or CONFIG['ANDROID_VERSION'] == '20'):
- # Suppress some GCC/clang warnings being treated as errors:
- # - about attributes on forward declarations for types that are already
- # defined, which complains about an important MOZ_EXPORT for android::AString
- # - about multi-character constants which are used in codec-related code
- if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
- CXXFLAGS += [
- '-Wno-error=attributes',
- '-Wno-error=multichar'
- ]
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/base/include/binder',
- 'frameworks/base/include/utils',
- ]
- ]
- UNIFIED_SOURCES += [
- 'GonkOmxPlatformLayer.cpp',
- ]
- EXTRA_DSO_LDOPTS += [
- '-libbinder',
- ]
-
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']: