mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
00dac32040
commit
e87bda79bd
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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_
|
@ -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
|
@ -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
|
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
@ -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',]
|
||||
]
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user