Backed out 5 changesets (bug 941302) for non-unified bustage. a=backout

Backed out changeset 73cfc50bcd37 (bug 941302)
Backed out changeset 13efa442f3bd (bug 941302)
Backed out changeset 6cf06baf92e1 (bug 941302)
Backed out changeset 0ee6c16041e0 (bug 941302)
Backed out changeset 2bc3c5dfbe97 (bug 941302)
This commit is contained in:
Ryan VanderMeulen 2014-08-06 12:54:17 -04:00
parent 00dac32040
commit e87bda79bd
20 changed files with 11 additions and 1457 deletions

View File

@ -309,10 +309,7 @@ pref("dom.indexedDB.warningQuota", 5);
pref("media.preload.default", 1); // default to preload none
pref("media.preload.auto", 2); // preload metadata if preload=auto
pref("media.cache_size", 4096); // 4MB media cache
#ifdef MOZ_FMP4
// Enable/Disable Gonk Decoder Module
pref("media.fragmented-mp4.gonk.enabled", false);
#endif
// The default number of decoded video frames that are enqueued in
// MediaDecoderReader's mVideoQueue.
pref("media.video-queue.default-size", 3);

View File

@ -261,7 +261,6 @@ if test -n "$gonkdir" ; then
MOZ_OMX_ENCODER=1
AC_SUBST(MOZ_OMX_ENCODER)
AC_DEFINE(MOZ_OMX_ENCODER)
MOZ_FMP4=1
;;
19)
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
@ -276,7 +275,7 @@ if test -n "$gonkdir" ; then
MOZ_AUDIO_OFFLOAD=1
AC_SUBST(MOZ_AUDIO_OFFLOAD)
AC_DEFINE(MOZ_AUDIO_OFFLOAD)
MOZ_FMP4=1
;;
*)
AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
@ -3776,11 +3775,7 @@ MOZ_WEBM=1
MOZ_GSTREAMER=
MOZ_DIRECTSHOW=
MOZ_WMF=
if test -n "$MOZ_FMP4"; then
MOZ_FMP4=1
else
MOZ_FMP4 =
fi
MOZ_FMP4=
MOZ_EME=1
MOZ_FFMPEG=
MOZ_WEBRTC=1

View File

@ -131,12 +131,6 @@ IsAppleAvailable()
#endif
}
static bool
IsGonkMP4DecoderAvailable()
{
return Preferences::GetBool("media.fragmented-mp4.gonk.enabled", false);
}
static bool
HavePlatformMPEGDecoders()
{
@ -147,7 +141,6 @@ HavePlatformMPEGDecoders()
#endif
IsFFmpegAvailable() ||
IsAppleAvailable() ||
IsGonkMP4DecoderAvailable() ||
// TODO: Other platforms...
false;
}

View File

@ -230,14 +230,8 @@ private:
nsString mInitDataType;
};
bool MP4Reader::IsWaitingOnCodecResource() {
#ifdef MOZ_GONK_MEDIACODEC
return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
#endif
return false;
}
bool MP4Reader::IsWaitingOnCDMResource() {
bool MP4Reader::IsWaitingMediaResources()
{
nsRefPtr<CDMProxy> proxy;
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@ -259,15 +253,6 @@ bool MP4Reader::IsWaitingOnCDMResource() {
}
}
bool MP4Reader::IsWaitingMediaResources()
{
// IsWaitingOnCDMResource() *must* come first, because we don't know whether
// we can create a decoder until the CDM is initialized and it has told us
// whether *it* will decode, or whether we need to create a PDM to do the
// decoding
return IsWaitingOnCDMResource() || IsWaitingOnCodecResource();
}
void
MP4Reader::ExtractCryptoInitData(nsTArray<uint8_t>& aInitData)
{
@ -309,12 +294,7 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
// an encrypted stream and we need to wait for a CDM to be set, we don't
// need to reinit the demuxer.
mDemuxerInitialized = true;
} else if (mPlatform && !IsWaitingMediaResources()) {
*aInfo = mInfo;
*aTags = nullptr;
return NS_OK;
}
if (mDemuxer->Crypto().valid) {
if (!sIsEMEEnabled) {
// TODO: Need to signal DRM/EME required somehow...
@ -755,36 +735,4 @@ MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
return NS_OK;
}
bool MP4Reader::IsDormantNeeded()
{
#ifdef MOZ_GONK_MEDIACODEC
return mVideo.mDecoder && mVideo.mDecoder->IsDormantNeeded();
#endif
return false;
}
void MP4Reader::ReleaseMediaResources()
{
#ifdef MOZ_GONK_MEDIACODEC
// Before freeing a video codec, all video buffers needed to be released
// even from graphics pipeline.
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
if (container) {
container->ClearCurrentFrame();
}
if (mVideo.mDecoder) {
mVideo.mDecoder->ReleaseMediaResources();
}
#endif
}
void MP4Reader::NotifyResourcesStatusChanged()
{
#ifdef MOZ_GONK_MEDIACODEC
if (mDecoder) {
mDecoder->NotifyWaitingForResourcesStatusChanged();
}
#endif
}
} // namespace mozilla

View File

@ -59,10 +59,7 @@ public:
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
int64_t aStartTime) MOZ_OVERRIDE;
// For Media Resource Management
virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
virtual bool IsDormantNeeded() MOZ_OVERRIDE;
virtual void ReleaseMediaResources() MOZ_OVERRIDE;
virtual nsresult ResetDecode() MOZ_OVERRIDE;
@ -87,9 +84,6 @@ private:
bool Decode(mp4_demuxer::TrackType aTrack);
void Flush(mp4_demuxer::TrackType aTrack);
void DrainComplete(mp4_demuxer::TrackType aTrack);
void NotifyResourcesStatusChanged();
bool IsWaitingOnCodecResource();
bool IsWaitingOnCDMResource();
nsAutoPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
nsAutoPtr<PlatformDecoderModule> mPlatform;
@ -114,12 +108,6 @@ private:
virtual void DrainComplete() MOZ_OVERRIDE {
mReader->DrainComplete(mType);
}
virtual void NotifyResourcesStatusChanged() MOZ_OVERRIDE {
mReader->NotifyResourcesStatusChanged();
}
virtual void ReleaseMediaResources() MOZ_OVERRIDE {
mReader->ReleaseMediaResources();
}
private:
MP4Reader* mReader;
mp4_demuxer::TrackType mType;

View File

@ -14,10 +14,6 @@
#ifdef MOZ_APPLEMEDIA
#include "AppleDecoderModule.h"
#endif
#ifdef MOZ_GONK_MEDIACODEC
#include "GonkDecoderModule.h"
#endif
#include "mozilla/Preferences.h"
#include "EMEDecoderModule.h"
#include "mozilla/CDMProxy.h"
@ -30,7 +26,6 @@ extern PlatformDecoderModule* CreateBlankDecoderModule();
bool PlatformDecoderModule::sUseBlankDecoder = false;
bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
bool PlatformDecoderModule::sGonkDecoderEnabled = false;
/* static */
void
@ -47,10 +42,6 @@ PlatformDecoderModule::Init()
"media.fragmented-mp4.use-blank-decoder");
Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
"media.fragmented-mp4.ffmpeg.enabled", false);
#ifdef MOZ_GONK_MEDIACODEC
Preferences::AddBoolVarCache(&sGonkDecoderEnabled,
"media.fragmented-mp4.gonk.enabled", false);
#endif
#ifdef XP_WIN
WMFDecoderModule::Init();
#endif
@ -137,11 +128,6 @@ PlatformDecoderModule::Create()
if (NS_SUCCEEDED(m->Startup())) {
return m.forget();
}
#endif
#ifdef MOZ_GONK_MEDIACODEC
if (sGonkDecoderEnabled) {
return new GonkDecoderModule();
}
#endif
return nullptr;
}

View File

@ -123,7 +123,6 @@ protected:
// Caches pref media.fragmented-mp4.use-blank-decoder
static bool sUseBlankDecoder;
static bool sFFmpegDecoderEnabled;
static bool sGonkDecoderEnabled;
};
// A callback used by MediaDataDecoder to return output/errors to the
@ -145,10 +144,6 @@ public:
virtual void InputExhausted() = 0;
virtual void DrainComplete() = 0;
virtual void NotifyResourcesStatusChanged() {};
virtual void ReleaseMediaResources() {};
};
// MediaDataDecoder is the interface exposed by decoders created by the
@ -214,15 +209,6 @@ public:
// returned.
virtual nsresult Shutdown() = 0;
// For Codec Resource Management
virtual bool IsWaitingMediaResources() {
return false;
};
virtual bool IsDormantNeeded() {
return false;
};
virtual void ReleaseMediaResources() {};
virtual void ReleaseDecoder() {};
};
} // namespace mozilla

View File

@ -1,197 +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 "GonkAudioDecoderManager.h"
#include "MediaDecoderReader.h"
#include "VideoUtils.h"
#include "nsTArray.h"
#include "prlog.h"
#include "stagefright/MediaBuffer.h"
#include "stagefright/MetaData.h"
#include "stagefright/MediaErrors.h"
#include <stagefright/foundation/AMessage.h>
#include "media/openmax/OMX_Audio.h"
#define LOG_TAG "GonkAudioDecoderManager"
#include <android/log.h>
#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#ifdef PR_LOGGING
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define LOG(...)
#endif
#define READ_OUTPUT_BUFFER_TIMEOUT_US 3000
using namespace android;
typedef android::MediaCodecProxy MediaCodecProxy;
namespace mozilla {
GonkAudioDecoderManager::GonkAudioDecoderManager(
const mp4_demuxer::AudioDecoderConfig& aConfig)
: mAudioChannels(aConfig.channel_count)
, mAudioRate(aConfig.samples_per_second)
, mAudioProfile(aConfig.aac_profile)
, mAudioBuffer(nullptr)
{
MOZ_COUNT_CTOR(GonkAudioDecoderManager);
MOZ_ASSERT(mAudioChannels);
mUserData.AppendElements(&aConfig.audio_specific_config[0],
aConfig.audio_specific_config.length());
}
GonkAudioDecoderManager::~GonkAudioDecoderManager()
{
MOZ_COUNT_DTOR(GonkAudioDecoderManager);
}
android::sp<MediaCodecProxy>
GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
{
if (mLooper != nullptr) {
return nullptr;
}
// Create ALooper
mLooper = new ALooper;
mLooper->setName("GonkAudioDecoderManager");
mLooper->start();
mDecoder = MediaCodecProxy::CreateByType(mLooper, "audio/mp4a-latm", false, false, nullptr);
if (!mDecoder.get()) {
return nullptr;
}
sp<AMessage> format = new AMessage;
// Fixed values
ALOG("Init Audio channel no:%d, sample-rate:%d", mAudioChannels, mAudioRate);
format->setString("mime", "audio/mp4a-latm");
format->setInt32("channel-count", mAudioChannels);
format->setInt32("sample-rate", mAudioRate);
format->setInt32("aac-profile", mAudioProfile);
format->setInt32("is-adts", true);
status_t err = mDecoder->configure(format, nullptr, nullptr, 0);
if (err != OK || !mDecoder->Prepare()) {
return nullptr;
}
status_t rv = mDecoder->Input(mUserData.Elements(), mUserData.Length(), 0,
android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
if (rv == OK) {
return mDecoder;
} else {
ALOG("Failed to input codec specific data!");
return nullptr;
}
}
nsresult
GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
void *data;
size_t dataOffset;
size_t size;
int64_t timeUs;
if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
return NS_ERROR_UNEXPECTED;
}
data = mAudioBuffer->data();
dataOffset = mAudioBuffer->range_offset();
size = mAudioBuffer->range_length();
nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[size/2] );
memcpy(buffer.get(), data+dataOffset, size);
uint32_t frames = size / (2 * mAudioChannels);
CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
if (!duration.isValid()) {
return NS_ERROR_UNEXPECTED;
}
*v = new AudioData(aStreamOffset, timeUs, duration.value(), frames, buffer.forget(),
mAudioChannels);
ReleaseAudioBuffer();
return NS_OK;
}
nsresult
GonkAudioDecoderManager::Output(int64_t aStreamOffset,
nsAutoPtr<MediaData>& aOutData)
{
aOutData = nullptr;
status_t err;
err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
switch (err) {
case OK:
{
if (mAudioBuffer && mAudioBuffer->range_length() != 0) {
int64_t timeUs;
if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
return NS_ERROR_UNEXPECTED;
}
}
AudioData* data = nullptr;
nsresult rv = CreateAudioData(aStreamOffset, &data);
// Frame should be non null only when we succeeded.
if (rv != NS_OK) {
return NS_ERROR_UNEXPECTED;
}
aOutData = data;
return NS_OK;
}
case android::INFO_FORMAT_CHANGED:
case android::INFO_OUTPUT_BUFFERS_CHANGED:
{
// If the format changed, update our cached info.
ALOG("Decoder format changed");
return Output(aStreamOffset, aOutData);
}
case -EAGAIN:
{
return NS_ERROR_NOT_AVAILABLE;
}
case android::ERROR_END_OF_STREAM:
{
ALOG("End of Stream");
return NS_ERROR_ABORT;
}
case -ETIMEDOUT:
{
ALOG("Timeout. can try again next time");
return NS_ERROR_UNEXPECTED;
}
default:
{
ALOG("Decoder failed, err=%d", err);
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
void GonkAudioDecoderManager::ReleaseAudioBuffer() {
if (mAudioBuffer) {
sp<MetaData> metaData = mAudioBuffer->meta_data();
int32_t index;
metaData->findInt32(android::MediaCodecProxy::kKeyBufferIndex, &index);
mAudioBuffer->release();
mAudioBuffer = nullptr;
mDecoder->releaseOutputBuffer(index);
}
}
nsresult
GonkAudioDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
{
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;
status_t rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
return rv == OK ? NS_OK : NS_ERROR_UNEXPECTED;
}
} // namespace mozilla

View File

@ -1,51 +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 "mozilla/RefPtr.h"
#include "MP4Reader.h"
#include "GonkMediaDataDecoder.h"
using namespace android;
namespace mozilla {
class GonkAudioDecoderManager : public GonkDecoderManager {
typedef android::MediaCodecProxy MediaCodecProxy;
public:
GonkAudioDecoderManager(const mp4_demuxer::AudioDecoderConfig& aConfig);
~GonkAudioDecoderManager();
virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
virtual nsresult Output(int64_t aStreamOffset,
nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
private:
nsresult CreateAudioData(int64_t aStreamOffset,
AudioData** aOutData);
void ReleaseAudioBuffer();
// MediaCodedc's wrapper that performs the decoding.
android::sp<MediaCodecProxy> mDecoder;
const uint32_t mAudioChannels;
const uint32_t mAudioRate;
const uint32_t mAudioProfile;
nsTArray<uint8_t> mUserData;
MediaDataDecoderCallback* mReaderCallback;
android::MediaBuffer* mAudioBuffer;
android::sp<ALooper> mLooper;
};
} // namespace mozilla
#endif // GonkAudioDecoderManager_h_

View File

@ -1,61 +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/Preferences.h"
#include "mozilla/DebugOnly.h"
#include "GonkMediaDataDecoder.h"
namespace mozilla {
GonkDecoderModule::GonkDecoderModule()
{
}
GonkDecoderModule::~GonkDecoderModule()
{
}
/* static */
void
GonkDecoderModule::Init()
{
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
}
nsresult
GonkDecoderModule::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
return NS_OK;
}
already_AddRefed<MediaDataDecoder>
GonkDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkVideoDecoderManager(aImageContainer,aConfig),
aVideoTaskQueue, aCallback);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
GonkDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig), aAudioTaskQueue,
aCallback);
return decoder.forget();
}
} // namespace mozilla

View File

@ -1,41 +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();
// Called when the decoders have shutdown.
virtual nsresult Shutdown() MOZ_OVERRIDE;
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
// Decode thread.
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
static void Init();
};
} // namespace mozilla
#endif

View File

@ -1,154 +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 "mp4_demuxer/mp4_demuxer.h"
#include "GonkMediaDataDecoder.h"
#include "VideoUtils.h"
#include "nsTArray.h"
#include "prlog.h"
#define LOG_TAG "GonkMediaDataDecoder(blake)"
#include <android/log.h>
#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#ifdef PR_LOGGING
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define LOG(...)
#endif
using namespace android;
namespace mozilla {
GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mManager(aManager)
{
MOZ_COUNT_CTOR(GonkMediaDataDecoder);
}
GonkMediaDataDecoder::~GonkMediaDataDecoder()
{
MOZ_COUNT_DTOR(GonkMediaDataDecoder);
}
nsresult
GonkMediaDataDecoder::Init()
{
mDecoder = mManager->Init(mCallback);
return mDecoder.get() ? NS_OK : NS_ERROR_UNEXPECTED;
}
nsresult
GonkMediaDataDecoder::Shutdown()
{
mDecoder->stop();
mDecoder = nullptr;
return NS_OK;
}
// Inserts data into the decoder's pipeline.
nsresult
GonkMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
{
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
this,
&GonkMediaDataDecoder::ProcessDecode,
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
return NS_OK;
}
void
GonkMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
{
nsresult rv = mManager->Input(aSample);
if (rv != NS_OK) {
NS_WARNING("GonkAudioDecoder failed to input data");
ALOG("Failed to input data err: %d",rv);
mCallback->Error();
return;
}
mLastStreamOffset = aSample->byte_offset;
ProcessOutput();
}
void
GonkMediaDataDecoder::ProcessOutput()
{
nsAutoPtr<MediaData> output;
nsresult rv;
while (true) {
rv = mManager->Output(mLastStreamOffset, output);
if (rv == NS_OK) {
mCallback->Output(output.forget());
continue;
}
else {
break;
}
}
if (rv == NS_ERROR_NOT_AVAILABLE) {
mCallback->InputExhausted();
return;
}
if (rv != NS_OK) {
NS_WARNING("GonkMediaDataDecoder failed to output data");
ALOG("Failed to output data");
mCallback->Error();
}
}
nsresult
GonkMediaDataDecoder::Flush()
{
// Flush the input task queue. This cancels all pending Decode() calls.
// Note this blocks until the task queue finishes its current job, if
// it's executing at all. Note the MP4Reader ignores all output while
// flushing.
mTaskQueue->Flush();
status_t err = mDecoder->flush();
return err == OK ? NS_OK : NS_ERROR_FAILURE;
}
void
GonkMediaDataDecoder::ProcessDrain()
{
// Then extract all available output.
ProcessOutput();
mCallback->DrainComplete();
}
nsresult
GonkMediaDataDecoder::Drain()
{
mTaskQueue->Dispatch(NS_NewRunnableMethod(this, &GonkMediaDataDecoder::ProcessDrain));
return NS_OK;
}
bool
GonkMediaDataDecoder::IsWaitingMediaResources() {
return mDecoder->IsWaitingResources();
}
bool
GonkMediaDataDecoder::IsDormantNeeded() {
return mDecoder->IsDormantNeeded();
}
void
GonkMediaDataDecoder::ReleaseMediaResources() {
mDecoder->ReleaseMediaResources();
}
} // namespace mozilla

View File

@ -1,92 +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 "mp4_demuxer/mp4_demuxer.h"
#include "mozilla/RefPtr.h"
#include "MP4Reader.h"
#include "MediaCodecProxy.h"
namespace mozilla {
// Manage the data flow from inputting encoded data and outputting decode data.
class GonkDecoderManager {
public:
virtual ~GonkDecoderManager() {}
// Creates and initializs the GonkDecoder.
// Returns nullptr on failure.
virtual android::sp<android::MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) = 0;
// Produces decoded output, it blocks until output can be produced or a timeout
// is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
// if there's not enough data to produce more output. If this returns a failure
// code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
// MP4Reader.
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
virtual nsresult Output(int64_t aStreamOffset,
nsAutoPtr<MediaData>& aOutput) = 0;
};
// 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,
MediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
~GonkMediaDataDecoder();
virtual nsresult Init() MOZ_OVERRIDE;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
virtual nsresult Flush() MOZ_OVERRIDE;
virtual nsresult Drain() MOZ_OVERRIDE;
virtual nsresult Shutdown() MOZ_OVERRIDE;
virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
virtual bool IsDormantNeeded() MOZ_OVERRIDE;
virtual void ReleaseMediaResources() MOZ_OVERRIDE;
private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available.
void ProcessDecode(mp4_demuxer::MP4Sample* aSample);
// Called on the task queue. Extracts output if available, and delivers
// it to the reader. Called after ProcessDecode() and ProcessDrain().
void ProcessOutput();
// Called on the task queue. Orders the Gonk to drain, and then extracts
// all available output.
void ProcessDrain();
RefPtr<MediaTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
android::sp<android::MediaCodecProxy> mDecoder;
nsAutoPtr<GonkDecoderManager> mManager;
// The last offset into the media resource that was passed into Input().
// This is used to approximate the decoder's position in the media resource.
int64_t mLastStreamOffset;
};
} // namespace mozilla
#endif // GonkMediaDataDecoder_h_

View File

@ -1,456 +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 <OMX_IVCommon.h>
#include <gui/Surface.h>
#include <ICrypto.h>
#include "GonkVideoDecoderManager.h"
#include "MediaDecoderReader.h"
#include "ImageContainer.h"
#include "VideoUtils.h"
#include "nsThreadUtils.h"
#include "Layers.h"
#include "prlog.h"
#include "stagefright/MediaBuffer.h"
#include "stagefright/MetaData.h"
#include "stagefright/MediaErrors.h"
#include <stagefright/foundation/ADebug.h>
#include <stagefright/foundation/AMessage.h>
#include "mp4_demuxer/AnnexB.h"
#define READ_OUTPUT_BUFFER_TIMEOUT_US 3000
#define LOG_TAG "GonkVideoDecoderManager"
#include <android/log.h>
#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#ifdef PR_LOGGING
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define LOG(...)
#endif
using namespace mozilla::layers;
using namespace android;
typedef android::MediaCodecProxy MediaCodecProxy;
namespace mozilla {
enum {
kNotifyCodecReserved = 'core',
kNotifyCodecCanceled = 'coca',
};
GonkVideoDecoderManager::GonkVideoDecoderManager(
mozilla::layers::ImageContainer* aImageContainer,
const mp4_demuxer::VideoDecoderConfig& aConfig)
: mImageContainer(aImageContainer)
, mConfig(aConfig)
, mReaderCallback(nullptr)
, mColorConverterBufferSize(0)
{
NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
MOZ_ASSERT(mImageContainer);
MOZ_COUNT_CTOR(GonkVideoDecoderManager);
mVideoWidth = aConfig.display_width;
mVideoHeight = aConfig.display_height;
mDisplayWidth = aConfig.display_width;
mDisplayHeight = aConfig.display_width;
mInfo.mVideo.mHasVideo = true;
nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
mInfo.mVideo.mDisplay = displaySize;
nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
nsIntSize frameSize(mVideoWidth, mVideoHeight);
mPicture = pictureRect;
mInitialFrame = frameSize;
mHandler = new MessageHandler(this);
mVideoListener = new VideoResourceListener(this);
}
GonkVideoDecoderManager::~GonkVideoDecoderManager()
{
MOZ_COUNT_DTOR(GonkVideoDecoderManager);
}
android::sp<MediaCodecProxy>
GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
{
nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
// Validate the container-reported frame and pictureRect sizes. This ensures
// that our video frame creation code doesn't overflow.
nsIntSize frameSize(mVideoWidth, mVideoHeight);
if (!IsValidVideoRegion(frameSize, pictureRect, displaySize)) {
ALOG("It is not a valid region");
return nullptr;
}
mReaderCallback = aCallback;
if (mLooper.get() != nullptr) {
return nullptr;
}
// Create ALooper
mLooper = new ALooper;
mLooper->setName("GonkVideoDecoderManager");
// Register AMessage handler to ALooper.
mLooper->registerHandler(mHandler);
// Start ALooper thread.
if (mLooper->start() != OK) {
return nullptr;
}
mDecoder = MediaCodecProxy::CreateByType(mLooper, "video/avc", false, true, mVideoListener);
return mDecoder;
}
nsresult
GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
{
*v = nullptr;
int64_t timeUs;
int32_t keyFrame;
if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
ALOG("Decoder did not return frame time");
return NS_ERROR_UNEXPECTED;
}
if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
keyFrame = 0;
}
gfx::IntRect picture = ToIntRect(mPicture);
if (mFrameInfo.mWidth != mInitialFrame.width ||
mFrameInfo.mHeight != mInitialFrame.height) {
// Frame size is different from what the container reports. This is legal,
// and we will preserve the ratio of the crop rectangle as it
// was reported relative to the picture size reported by the container.
picture.x = (mPicture.x * mFrameInfo.mWidth) / mInitialFrame.width;
picture.y = (mPicture.y * mFrameInfo.mHeight) / mInitialFrame.height;
picture.width = (mFrameInfo.mWidth * mPicture.width) / mInitialFrame.width;
picture.height = (mFrameInfo.mHeight * mPicture.height) / mInitialFrame.height;
}
if (!(mVideoBuffer != nullptr && mVideoBuffer->size() > 0 && mVideoBuffer->data() != nullptr)) {
ALOG("mVideoBuffer is not valid!");
return NS_ERROR_UNEXPECTED;
}
uint8_t *yuv420p_buffer = (uint8_t *)mVideoBuffer->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(mVideoBuffer->data(),
mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) {
ReleaseVideoBuffer();
ALOG("Color conversion failed!");
return NS_ERROR_UNEXPECTED;
}
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;
// This is the approximate byte position in the stream.
int64_t pos = aStreamOffset;
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;
*v = VideoData::Create(
mInfo.mVideo,
mImageContainer,
pos,
timeUs,
1, // We don't know the duration.
b,
keyFrame,
-1,
picture);
ReleaseVideoBuffer();
return NS_OK;
}
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)) {
ALOG("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(mInitialFrame, mPicture, displaySize)) {
ALOG("It is not a valid region");
return false;
}
}
return true;
}
// Blocks until decoded sample is produced by the deoder.
nsresult
GonkVideoDecoderManager::Output(int64_t aStreamOffset,
nsAutoPtr<MediaData>& aOutData)
{
aOutData = nullptr;
status_t err;
if (mDecoder == nullptr) {
ALOG("Decoder is not inited");
return NS_ERROR_UNEXPECTED;
}
err = mDecoder->Output(&mVideoBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
switch (err) {
case OK:
{
VideoData* data = nullptr;
nsresult rv = CreateVideoData(aStreamOffset, &data);
// Frame should be non null only when we succeeded.
if (rv != NS_OK || data == nullptr){
ALOG("Error unexpected in CreateVideoData");
return NS_ERROR_UNEXPECTED;
}
aOutData = data;
return NS_OK;
}
case android::INFO_FORMAT_CHANGED:
case android::INFO_OUTPUT_BUFFERS_CHANGED:
{
// If the format changed, update our cached info.
ALOG("Decoder format changed");
if (!SetVideoFormat()) {
return NS_ERROR_UNEXPECTED;
}
else
return Output(aStreamOffset, aOutData);
}
case -EAGAIN:
{
return NS_ERROR_NOT_AVAILABLE;
}
case android::ERROR_END_OF_STREAM:
{
ALOG("End of Stream");
return NS_ERROR_ABORT;
}
case -ETIMEDOUT:
{
ALOG("Timeout. can try again next time");
return NS_ERROR_UNEXPECTED;
}
default:
{
ALOG("Decoder failed, err=%d", err);
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
void GonkVideoDecoderManager::ReleaseVideoBuffer() {
if (mVideoBuffer) {
sp<MetaData> metaData = mVideoBuffer->meta_data();
int32_t index;
metaData->findInt32(android::MediaCodecProxy::kKeyBufferIndex, &index);
mVideoBuffer->release();
mVideoBuffer = nullptr;
mDecoder->releaseOutputBuffer(index);
}
}
nsresult
GonkVideoDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
{
// We must prepare samples in AVC Annex B.
mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b);
// Forward sample data to the decoder.
const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
uint32_t length = aSample->size;
if (mDecoder == nullptr) {
ALOG("Decoder is not inited");
return NS_ERROR_UNEXPECTED;
}
status_t rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
return (rv == OK) ? NS_OK : NS_ERROR_FAILURE;
}
void
GonkVideoDecoderManager::codecReserved()
{
sp<AMessage> format = new AMessage;
// Fixed values
format->setString("mime", "video/avc");
format->setInt32("width", mVideoWidth);
format->setInt32("height", mVideoHeight);
mDecoder->configure(format, nullptr, nullptr, 0);
mDecoder->Prepare();
SetVideoFormat();
if (mHandler != nullptr) {
// post kNotifyCodecReserved to MediaCodecReader::mLooper thread.
sp<AMessage> notify = new AMessage(kNotifyCodecReserved, mHandler->id());
notify->post();
}
}
void
GonkVideoDecoderManager::codecCanceled()
{
mDecoder = nullptr;
if (mHandler != nullptr) {
// post kNotifyCodecCanceled to MediaCodecReader::mLooper thread.
sp<AMessage> notify = new AMessage(kNotifyCodecCanceled, mHandler->id());
notify->post();
}
}
// Called on GonkVideoDecoderManager::mLooper thread.
void
GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
{
switch (aMessage->what()) {
case kNotifyCodecReserved:
{
// Our decode may have acquired the hardware resource that it needs
// to start. Notify the state machine to resume loading metadata.
mReaderCallback->NotifyResourcesStatusChanged();
break;
}
case kNotifyCodecCanceled:
{
mReaderCallback->ReleaseMediaResources();
break;
}
default:
TRESPASS();
break;
}
}
GonkVideoDecoderManager::MessageHandler::MessageHandler(GonkVideoDecoderManager *aManager)
: mManager(aManager)
{
}
GonkVideoDecoderManager::MessageHandler::~MessageHandler()
{
mManager = nullptr;
}
void
GonkVideoDecoderManager::MessageHandler::onMessageReceived(const android::sp<android::AMessage> &aMessage)
{
if (mManager != nullptr) {
mManager->onMessageReceived(aMessage);
}
}
GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener(GonkVideoDecoderManager *aManager)
: mManager(aManager)
{
}
GonkVideoDecoderManager::VideoResourceListener::~VideoResourceListener()
{
mManager = nullptr;
}
void
GonkVideoDecoderManager::VideoResourceListener::codecReserved()
{
if (mManager != nullptr) {
mManager->codecReserved();
}
}
void
GonkVideoDecoderManager::VideoResourceListener::codecCanceled()
{
if (mManager != nullptr) {
mManager->codecCanceled();
}
}
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 = nullptr; // release the previous buffer first
mColorConverterBuffer = new uint8_t[yuv420p_size];
mColorConverterBufferSize = yuv420p_size;
}
return mColorConverterBuffer.get();
}
} // namespace mozilla

View File

@ -1,125 +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 "MP4Reader.h"
#include "nsRect.h"
#include "GonkMediaDataDecoder.h"
#include "mozilla/RefPtr.h"
#include "I420ColorConverterHelper.h"
using namespace android;
namespace mozilla {
class GonkVideoDecoderManager : public GonkDecoderManager {
typedef android::MediaCodecProxy MediaCodecProxy;
public:
GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
const mp4_demuxer::VideoDecoderConfig& aConfig);
~GonkVideoDecoderManager();
virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
virtual nsresult Output(int64_t aStreamOffset,
nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
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;
};
class MessageHandler : public android::AHandler
{
public:
MessageHandler(GonkVideoDecoderManager *aManager);
~MessageHandler();
virtual void onMessageReceived(const android::sp<android::AMessage> &aMessage);
private:
// Forbidden
MessageHandler() MOZ_DELETE;
MessageHandler(const MessageHandler &rhs) MOZ_DELETE;
const MessageHandler &operator=(const MessageHandler &rhs) MOZ_DELETE;
GonkVideoDecoderManager *mManager;
};
friend class MessageHandler;
class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
{
public:
VideoResourceListener(GonkVideoDecoderManager *aManager);
~VideoResourceListener();
virtual void codecReserved() MOZ_OVERRIDE;
virtual void codecCanceled() MOZ_OVERRIDE;
private:
// Forbidden
VideoResourceListener() MOZ_DELETE;
VideoResourceListener(const VideoResourceListener &rhs) MOZ_DELETE;
const VideoResourceListener &operator=(const VideoResourceListener &rhs) MOZ_DELETE;
GonkVideoDecoderManager *mManager;
};
friend class VideoResourceListener;
bool SetVideoFormat();
nsresult CreateVideoData(int64_t aStreamOffset, VideoData** aOutData);
void ReleaseVideoBuffer();
uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
// For codec resource management
void codecReserved();
void codecCanceled();
void onMessageReceived(const sp<AMessage> &aMessage);
const mp4_demuxer::VideoDecoderConfig& mConfig;
uint32_t mVideoWidth;
uint32_t mVideoHeight;
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
nsIntRect mPicture;
nsIntSize mInitialFrame;
android::sp<MediaCodecProxy> mDecoder;
nsRefPtr<layers::ImageContainer> mImageContainer;
MediaDataDecoderCallback* mCallback;
android::MediaBuffer* mVideoBuffer;
MediaDataDecoderCallback* mReaderCallback;
MediaInfo mInfo;
android::sp<VideoResourceListener> mVideoListener;
android::sp<MessageHandler> mHandler;
android::sp<ALooper> mLooper;
FrameInfo mFrameInfo;
// color converter
android::I420ColorConverterHelper mColorConverter;
nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
size_t mColorConverterBufferSize;
};
} // namespace mozilla
#endif // GonkVideoDecoderManager_h_

View File

@ -1,32 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; 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 += [
'/content/media/omx/',
'/content/media/omx/mediaresourcemanager',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True
CXXFLAGS += [
'-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'frameworks/native/opengl/include',]
]

View File

@ -68,10 +68,6 @@ LOCAL_INCLUDES += [
'../base',
]
if CONFIG['ANDROID_VERSION'] >= '18'and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
DEFINES['MOZ_GONK_MEDIACODEC'] = True
DIRS += ['gonk']
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -5,16 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaCodecProxy.h"
#include <string.h>
#include <binder/IPCThreadState.h>
#include <stagefright/foundation/ABuffer.h>
#include <stagefright/foundation/ADebug.h>
#include <stagefright/MetaData.h>
#define LOG_TAG "MediaCodecProxy"
#include <android/log.h>
#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll
#include <string.h>
#include <binder/IPCThreadState.h>
namespace android {
sp<MediaCodecProxy>
@ -394,105 +389,4 @@ MediaCodecProxy::resourceCanceled()
}
}
bool MediaCodecProxy::Prepare()
{
status_t err;
if (start() != OK) {
ALOG("Couldn't start MediaCodec");
return false;
}
if (getInputBuffers(&mInputBuffers) != OK) {
ALOG("Couldn't get input buffers from MediaCodec");
return false;
}
if (getOutputBuffers(&mOutputBuffers) != OK) {
ALOG("Couldn't get output buffers from MediaCodec");
return false;
}
return true;
}
status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
int64_t aTimestampUsecs, uint64_t aflags)
{
if (mCodec == nullptr) {
ALOG("MediaCodec has not been inited from input!");
return NO_INIT;
}
size_t index;
status_t err = dequeueInputBuffer(&index, TIMEOUT_DEQUEUE_INPUTBUFFER_MS);
if (err != OK) {
ALOG("dequeueInputBuffer returned %d", err);
return err;
}
const sp<ABuffer> &dstBuffer = mInputBuffers.itemAt(index);
CHECK_LE(aDataSize, dstBuffer->capacity());
dstBuffer->setRange(0, aDataSize);
memcpy(dstBuffer->data(), aData, aDataSize);
err = queueInputBuffer(index, 0, dstBuffer->size(), aTimestampUsecs, aflags);
if (err != OK) {
ALOG("queueInputBuffer returned %d", err);
return err;
}
return err;
}
status_t MediaCodecProxy::Output(MediaBuffer** aBuffer, int64_t aTimeoutUs)
{
if (mCodec == nullptr) {
ALOG("MediaCodec has not been inited from output!");
return NO_INIT;
}
size_t index = 0;
size_t offset = 0;
size_t size = 0;
int64_t timeUs = 0;
uint32_t flags = 0;
*aBuffer = nullptr;
status_t err = dequeueOutputBuffer(&index, &offset, &size,
&timeUs, &flags, aTimeoutUs);
if (err != OK) {
ALOG("Output returned %d", err);
return err;
}
MediaBuffer *buffer;
buffer = new MediaBuffer(mOutputBuffers.itemAt(index));
sp<MetaData> metaData = buffer->meta_data();
metaData->setInt32(kKeyBufferIndex, index);
metaData->setInt64(kKeyTime, timeUs);
buffer->set_range(buffer->range_offset(), size);
*aBuffer = buffer;
return err;
}
bool MediaCodecProxy::IsWaitingResources()
{
return mCodec == nullptr;
}
bool MediaCodecProxy::IsDormantNeeded()
{
return mCodecLooper.get() ? true : false;
}
void MediaCodecProxy::ReleaseMediaResources()
{
if (mCodec.get()) {
mCodec->stop();
mCodec->release();
mCodec.clear();
}
}
} // namespace android

View File

@ -10,18 +10,12 @@
#include <nsString.h>
#include <stagefright/MediaCodec.h>
#include <stagefright/MediaBuffer.h>
#include <utils/threads.h>
#include "MediaResourceHandler.h"
namespace android {
// This class is intended to be a proxy for MediaCodec with codec resource
// management. Basically user can use it like MediaCodec, but need to handle
// the listener when Codec is reserved for Async case. A good example is
// MediaCodecReader.cpp. Another useage is to use configure(), Prepare(),
// Input(), and Output(). It is used in GonkVideoDecoderManager.cpp which
// doesn't need to handle the buffers for codec.
class MediaCodecProxy : public MediaResourceHandler::ResourceListener
{
public:
@ -40,9 +34,6 @@ public:
virtual void codecCanceled() = 0;
};
enum {
kKeyBufferIndex = 'bfin',
};
// Check whether MediaCodec has been allocated.
bool allocated() const;
@ -113,13 +104,6 @@ public:
// pending, an error is pending.
void requestActivityNotification(const sp<AMessage> &aNotify);
status_t Input(const uint8_t* aData, uint32_t aDataSize,
int64_t aTimestampUsecs, uint64_t flags);
status_t Output(MediaBuffer** aBuffer, int64_t aTimeoutUs);
bool Prepare();
bool IsWaitingResources();
bool IsDormantNeeded();
void ReleaseMediaResources();
protected:
virtual ~MediaCodecProxy();
@ -165,10 +149,6 @@ private:
// MediaCodec instance
mutable RWLock mCodecLock;
sp<MediaCodec> mCodec;
//MediaCodec buffers to hold input/output data.
Vector<sp<ABuffer> > mInputBuffers;
Vector<sp<ABuffer> > mOutputBuffers;
};
} // namespace android

View File

@ -97,7 +97,6 @@ public:
uint32_t bits_per_sample;
uint32_t samples_per_second;
int8_t frequency_index;
int8_t aac_profile;
mozilla::Vector<uint8_t> extra_data;
mozilla::Vector<uint8_t> audio_specific_config;
CryptoTrack crypto;
@ -108,6 +107,7 @@ public:
private:
friend class MP4Demuxer;
int8_t aac_profile;
};
class VideoDecoderConfig : public TrackConfig