Bug 1198664 - Refactor: move common behaviors to base class. r=bwu,jya

This commit is contained in:
John Lin 2015-10-06 02:18:00 +02:00
parent 0db40bcc41
commit 4aec628c96
6 changed files with 170 additions and 261 deletions

View File

@ -34,18 +34,15 @@ typedef android::MediaCodecProxy MediaCodecProxy;
namespace mozilla {
GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
: mLastDecodedTime(0)
, mAudioChannels(aConfig.mChannels)
: mAudioChannels(aConfig.mChannels)
, mAudioRate(aConfig.mRate)
, mAudioProfile(aConfig.mProfile)
, mAudioBuffer(nullptr)
, mMonitor("GonkAudioDecoderManager")
{
MOZ_COUNT_CTOR(GonkAudioDecoderManager);
MOZ_ASSERT(mAudioChannels);
mCodecSpecificData = aConfig.mCodecSpecificConfig;
mMimeType = aConfig.mMimeType;
}
GonkAudioDecoderManager::~GonkAudioDecoderManager()
@ -54,9 +51,9 @@ GonkAudioDecoderManager::~GonkAudioDecoderManager()
}
nsRefPtr<MediaDataDecoder::InitPromise>
GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
GonkAudioDecoderManager::Init()
{
if (InitMediaCodecProxy(aCallback)) {
if (InitMediaCodecProxy()) {
return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
} else {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
@ -64,18 +61,14 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
}
bool
GonkAudioDecoderManager::InitMediaCodecProxy(MediaDataDecoderCallback* aCallback)
GonkAudioDecoderManager::InitMediaCodecProxy()
{
status_t rv = OK;
if (mLooper != nullptr) {
if (!InitLoopers(MediaData::AUDIO_DATA)) {
return false;
}
// Create ALooper
mLooper = new ALooper;
mLooper->setName("GonkAudioDecoderManager");
mLooper->start();
mDecoder = MediaCodecProxy::CreateByType(mLooper, mMimeType.get(), false, nullptr);
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, nullptr);
if (!mDecoder.get()) {
return false;
}
@ -110,52 +103,6 @@ GonkAudioDecoderManager::InitMediaCodecProxy(MediaDataDecoderCallback* aCallback
}
}
bool
GonkAudioDecoderManager::HasQueuedSample()
{
MonitorAutoLock mon(mMonitor);
return mQueueSample.Length();
}
nsresult
GonkAudioDecoderManager::Input(MediaRawData* aSample)
{
MonitorAutoLock mon(mMonitor);
nsRefPtr<MediaRawData> sample;
if (aSample) {
sample = aSample;
} else {
// It means EOS with empty sample.
sample = new MediaRawData();
}
mQueueSample.AppendElement(sample);
status_t rv;
while (mQueueSample.Length()) {
nsRefPtr<MediaRawData> data = mQueueSample.ElementAt(0);
{
MonitorAutoUnlock mon_exit(mMonitor);
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0);
}
if (rv == OK) {
mQueueSample.RemoveElementAt(0);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
nsresult
GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
if (!(mAudioBuffer != nullptr && mAudioBuffer->data() != nullptr)) {
@ -175,13 +122,13 @@ GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
return NS_ERROR_NOT_AVAILABLE;
}
if (mLastDecodedTime > timeUs) {
if (mLastTime > timeUs) {
ReleaseAudioBuffer();
GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
MOZ_ASSERT(false);
return NS_ERROR_NOT_AVAILABLE;
}
mLastDecodedTime = timeUs;
mLastTime = timeUs;
const uint8_t *data = static_cast<const uint8_t*>(mAudioBuffer->data());
size_t dataOffset = mAudioBuffer->range_offset();
@ -207,23 +154,6 @@ GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
return NS_OK;
}
nsresult
GonkAudioDecoderManager::Flush()
{
{
MonitorAutoLock mon(mMonitor);
mQueueSample.Clear();
}
mLastDecodedTime = 0;
if (mDecoder->flush() != OK) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
GonkAudioDecoderManager::Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutData)

View File

@ -13,7 +13,6 @@
using namespace android;
namespace android {
struct MOZ_EXPORT ALooper;
class MOZ_EXPORT MediaBuffer;
} // namespace android
@ -24,44 +23,26 @@ typedef android::MediaCodecProxy MediaCodecProxy;
public:
GonkAudioDecoderManager(const AudioInfo& aConfig);
virtual ~GonkAudioDecoderManager() override;
virtual ~GonkAudioDecoderManager();
nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) override;
nsresult Input(MediaRawData* aSample) override;
nsRefPtr<InitPromise> Init() override;
nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;
nsresult Flush() override;
bool HasQueuedSample() override;
private:
bool InitMediaCodecProxy(MediaDataDecoderCallback* aCallback);
bool InitMediaCodecProxy();
nsresult CreateAudioData(int64_t aStreamOffset,
AudioData** aOutData);
void ReleaseAudioBuffer();
int64_t mLastDecodedTime;
uint32_t mAudioChannels;
uint32_t mAudioRate;
const uint32_t mAudioProfile;
MediaDataDecoderCallback* mReaderCallback;
android::MediaBuffer* mAudioBuffer;
android::sp<ALooper> mLooper;
// This monitor protects mQueueSample.
Monitor mMonitor;
// An queue with the MP4 samples which are waiting to be sent into OMX.
// If an element is an empty MP4Sample, that menas EOS. There should not
// any sample be queued after EOS.
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
};
} // namespace mozilla

View File

@ -8,6 +8,8 @@
#include "nsTArray.h"
#include "MediaCodecProxy.h"
#include <stagefright/foundation/ADebug.h>
#include "mozilla/Logging.h"
#include <android/log.h>
#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__)
@ -19,6 +21,87 @@ using namespace android;
namespace mozilla {
bool
GonkDecoderManager::InitLoopers(MediaData::Type aType)
{
MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr);
MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA);
const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio");
mDecodeLooper = new ALooper;
android::AString name("MediaCodecProxy/");
name.append(suffix);
mDecodeLooper->setName(name.c_str());
mTaskLooper = new ALooper;
name.setTo("GonkDecoderManager/");
name.append(suffix);
mTaskLooper->setName(name.c_str());
mTaskLooper->registerHandler(this);
return mDecodeLooper->start() == OK && mTaskLooper->start() == OK;
}
nsresult
GonkDecoderManager::Input(MediaRawData* aSample)
{
MutexAutoLock lock(mMutex);
nsRefPtr<MediaRawData> sample;
if (!aSample) {
// It means EOS with empty sample.
sample = new MediaRawData();
} else {
sample = aSample;
}
mQueuedSamples.AppendElement(sample);
status_t rv;
while (mQueuedSamples.Length()) {
nsRefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
{
MutexAutoUnlock unlock(mMutex);
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0);
}
if (rv == OK) {
mQueuedSamples.RemoveElementAt(0);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
nsresult
GonkDecoderManager::Flush()
{
if (mDecoder == nullptr) {
GMDD_LOG("Decoder is not initialized");
return NS_ERROR_UNEXPECTED;
}
{
MutexAutoLock lock(mMutex);
mQueuedSamples.Clear();
}
mLastTime = 0;
if (mDecoder->flush() != OK) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
GonkDecoderManager::Shutdown()
{
@ -33,6 +116,25 @@ GonkDecoderManager::Shutdown()
return NS_OK;
}
bool
GonkDecoderManager::HasQueuedSample()
{
MutexAutoLock lock(mMutex);
return mQueuedSamples.Length();
}
void
GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
{
switch (aMessage->what()) {
default:
{
TRESPASS();
break;
}
}
}
GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
@ -43,6 +145,7 @@ GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
, mDrainComplete(false)
{
MOZ_COUNT_CTOR(GonkMediaDataDecoder);
mManager->SetDecodeCallback(aCallback);
}
GonkMediaDataDecoder::~GonkMediaDataDecoder()
@ -55,7 +158,7 @@ GonkMediaDataDecoder::Init()
{
mDrainComplete = false;
return mManager->Init(mCallback);
return mManager->Init();
}
nsresult

View File

@ -7,8 +7,10 @@
#if !defined(GonkMediaDataDecoder_h_)
#define GonkMediaDataDecoder_h_
#include "PlatformDecoderModule.h"
#include <stagefright/foundation/AHandler.h>
namespace android {
struct ALooper;
class MediaCodecProxy;
} // namespace android
@ -16,7 +18,7 @@ namespace mozilla {
class MediaRawData;
// Manage the data flow from inputting encoded data and outputting decode data.
class GonkDecoderManager {
class GonkDecoderManager : public android::AHandler {
public:
typedef TrackInfo::TrackType TrackType;
typedef MediaDataDecoder::InitPromise InitPromise;
@ -24,10 +26,8 @@ public:
virtual ~GonkDecoderManager() {}
virtual nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) = 0;
// Add samples into OMX decoder or queue them if decoder is out of input buffer.
virtual nsresult Input(MediaRawData* aSample) = 0;
nsresult Input(MediaRawData* aSample);
// 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
@ -37,26 +37,57 @@ public:
// The overrided class should follow the same behaviour.
virtual nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) = 0;
virtual nsRefPtr<InitPromise> Init() = 0;
// Flush the queued sample.
virtual nsresult Flush() = 0;
nsresult Flush();
// Shutdown decoder and rejects the init promise.
nsresult Shutdown();
// True if sample is queued.
virtual bool HasQueuedSample() = 0;
bool HasQueuedSample();
// Set callback for decoder events, such as requesting more input,
// returning output, or reporting error.
void SetDecodeCallback(MediaDataDecoderCallback* aCallback)
{
mDecodeCallback = aCallback;
}
protected:
GonkDecoderManager()
: mMutex("GonkDecoderManager")
, mLastTime(0)
, mDecodeCallback(nullptr)
{}
bool InitLoopers(MediaData::Type aType);
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
nsRefPtr<MediaByteBuffer> mCodecSpecificData;
nsAutoCString mMimeType;
// MediaCodedc's wrapper that performs the decoding.
android::sp<android::MediaCodecProxy> mDecoder;
// Looper for mDecoder to run on.
android::sp<android::ALooper> mDecodeLooper;
// Looper to run decode tasks such as recycling output buffers.
android::sp<android::ALooper> mTaskLooper;
MozPromiseHolder<InitPromise> mInitPromise;
Mutex mMutex; // Protects mQueuedSamples.
// A queue that stores the samples waiting to be sent to mDecoder.
// Empty element means EOS and there shouldn't be any sample be queued after it.
// Samples are queued in caller's thread and dequeued in mTaskLooper.
nsTArray<nsRefPtr<MediaRawData>> mQueuedSamples;
int64_t mLastTime; // The last decoded frame presentation time.
MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
};
// Samples are decoded using the GonkDecoder (MediaCodec)
@ -101,7 +132,7 @@ private:
RefPtr<FlushableTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
nsAutoPtr<GonkDecoderManager> mManager;
android::sp<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.

View File

@ -17,10 +17,7 @@
#include "stagefright/MediaBuffer.h"
#include "stagefright/MetaData.h"
#include "stagefright/MediaErrors.h"
#include <stagefright/foundation/ADebug.h>
#include <stagefright/foundation/AMessage.h>
#include <stagefright/foundation/AString.h>
#include <stagefright/foundation/ALooper.h>
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "mozilla/layers/GrallocTextureClient.h"
@ -44,12 +41,9 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
mozilla::layers::ImageContainer* aImageContainer,
const VideoInfo& aConfig)
: mImageContainer(aImageContainer)
, mReaderCallback(nullptr)
, mLastDecodedTime(0)
, mColorConverterBufferSize(0)
, mNativeWindow(nullptr)
, mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
, mMonitor("GonkVideoDecoderManager")
{
MOZ_COUNT_CTOR(GonkVideoDecoderManager);
mMimeType = aConfig.mMimeType;
@ -64,7 +58,6 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
nsIntSize frameSize(mVideoWidth, mVideoHeight);
mPicture = pictureRect;
mInitialFrame = frameSize;
mHandler = new MessageHandler(this);
mVideoListener = new VideoResourceListener(this);
}
@ -76,7 +69,7 @@ GonkVideoDecoderManager::~GonkVideoDecoderManager()
}
nsRefPtr<MediaDataDecoder::InitPromise>
GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
GonkVideoDecoderManager::Init()
{
nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
@ -101,26 +94,19 @@ GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
mReaderCallback = aCallback;
mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
MOZ_ASSERT(mReaderTaskQueue);
if (mLooper.get() != nullptr) {
if (mDecodeLooper.get() != nullptr) {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
// Create ALooper
mLooper = new ALooper;
mManagerLooper = new ALooper;
mManagerLooper->setName("GonkVideoDecoderManager");
// Register AMessage handler to ALooper.
mManagerLooper->registerHandler(mHandler);
// Start ALooper thread.
if (mLooper->start() != OK || mManagerLooper->start() != OK ) {
if (!InitLoopers(MediaData::VIDEO_DATA)) {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
nsRefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
mDecoder = MediaCodecProxy::CreateByType(mLooper, mMimeType.get(), false, mVideoListener);
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
mDecoder->AsyncAskMediaCodec();
uint32_t capability = MediaCodecProxy::kEmptyCapability;
@ -132,52 +118,6 @@ GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
return p;
}
nsresult
GonkVideoDecoderManager::Input(MediaRawData* aSample)
{
MonitorAutoLock mon(mMonitor);
nsRefPtr<MediaRawData> sample;
if (!aSample) {
// It means EOS with empty sample.
sample = new MediaRawData();
} else {
sample = aSample;
}
mQueueSample.AppendElement(sample);
status_t rv;
while (mQueueSample.Length()) {
nsRefPtr<MediaRawData> data = mQueueSample.ElementAt(0);
{
MonitorAutoUnlock mon_unlock(mMonitor);
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0);
}
if (rv == OK) {
mQueueSample.RemoveElementAt(0);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
bool
GonkVideoDecoderManager::HasQueuedSample()
{
MonitorAutoLock mon(mMonitor);
return mQueueSample.Length();
}
nsresult
GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
{
@ -197,12 +137,12 @@ GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
return NS_ERROR_UNEXPECTED;
}
if (mLastDecodedTime > timeUs) {
if (mLastTime > timeUs) {
ReleaseVideoBuffer();
GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
return NS_ERROR_NOT_AVAILABLE;
}
mLastDecodedTime = timeUs;
mLastTime = timeUs;
if (mVideoBuffer->range_length() == 0) {
// Some decoders may return spurious empty buffers that we just want to ignore
@ -367,27 +307,6 @@ GonkVideoDecoderManager::SetVideoFormat()
return false;
}
nsresult
GonkVideoDecoderManager::Flush()
{
if (mDecoder == nullptr) {
GVDM_LOG("Decoder is not inited");
return NS_ERROR_UNEXPECTED;
}
{
MonitorAutoLock mon(mMonitor);
mQueueSample.Clear();
}
mLastDecodedTime = 0;
if (mDecoder->flush() != OK) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// Blocks until decoded sample is produced by the deoder.
nsresult
GonkVideoDecoderManager::Output(int64_t aStreamOffset,
@ -516,7 +435,7 @@ GonkVideoDecoderManager::codecCanceled()
mInitPromise.RejectIfExists(DecoderFailureReason::CANCELED, __func__);
}
// Called on GonkVideoDecoderManager::mManagerLooper thread.
// Called on GonkDecoderManager::mTaskLooper thread.
void
GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
{
@ -528,26 +447,10 @@ GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
}
default:
TRESPASS();
{
GonkDecoderManager::onMessageReceived(aMessage);
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);
}
}
}
@ -652,7 +555,7 @@ void GonkVideoDecoderManager::PostReleaseVideoBuffer(
}
}
sp<AMessage> notify =
new AMessage(kNotifyPostReleaseBuffer, mHandler->id());
new AMessage(kNotifyPostReleaseBuffer, id());
notify->post();
}

View File

@ -7,13 +7,11 @@
#if !defined(GonkVideoDecoderManager_h_)
#define GonkVideoDecoderManager_h_
#include <set>
#include "nsRect.h"
#include "GonkMediaDataDecoder.h"
#include "mozilla/RefPtr.h"
#include "I420ColorConverterHelper.h"
#include "MediaCodecProxy.h"
#include <stagefright/foundation/AHandler.h>
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "mozilla/layers/FenceUtils.h"
@ -22,7 +20,6 @@
using namespace android;
namespace android {
struct ALooper;
class MediaBuffer;
struct MOZ_EXPORT AString;
class GonkNativeWindow;
@ -42,19 +39,13 @@ public:
GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
const VideoInfo& aConfig);
virtual ~GonkVideoDecoderManager() override;
virtual ~GonkVideoDecoderManager();
nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) override;
nsresult Input(MediaRawData* aSample) override;
nsRefPtr<InitPromise> Init() override;
nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;
nsresult Flush() override;
bool HasQueuedSample() override;
static void RecycleCallback(TextureClient* aClient, void* aClosure);
private:
@ -70,23 +61,8 @@ private:
int32_t mCropRight = 0;
int32_t mCropBottom = 0;
};
class MessageHandler : public android::AHandler
{
public:
MessageHandler(GonkVideoDecoderManager *aManager);
~MessageHandler();
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
private:
// Forbidden
MessageHandler() = delete;
MessageHandler(const MessageHandler &rhs) = delete;
const MessageHandler &operator=(const MessageHandler &rhs) = delete;
GonkVideoDecoderManager *mManager;
};
friend class MessageHandler;
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
{
@ -119,7 +95,6 @@ private:
// For codec resource management
void codecReserved();
void codecCanceled();
void onMessageReceived(const sp<AMessage> &aMessage);
void ReleaseAllPendingVideoBuffers();
void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
@ -136,16 +111,10 @@ private:
android::MediaBuffer* mVideoBuffer;
MediaDataDecoderCallback* mReaderCallback;
MediaInfo mInfo;
android::sp<VideoResourceListener> mVideoListener;
android::sp<MessageHandler> mHandler;
android::sp<ALooper> mLooper;
android::sp<ALooper> mManagerLooper;
FrameInfo mFrameInfo;
int64_t mLastDecodedTime; // The last decoded frame presentation time.
// color converter
android::I420ColorConverterHelper mColorConverter;
nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
@ -168,17 +137,9 @@ private:
// The lock protects mPendingReleaseItems.
Mutex mPendingReleaseItemsLock;
// This monitor protects mQueueSample.
Monitor mMonitor;
// This TaskQueue should be the same one in mReaderCallback->OnReaderTaskQueue().
// This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue().
// It is for codec resource mangement, decoding task should not dispatch to it.
nsRefPtr<TaskQueue> mReaderTaskQueue;
// An queue with the MP4 samples which are waiting to be sent into OMX.
// If an element is an empty MP4Sample, that menas EOS. There should not
// any sample be queued after EOS.
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
};
} // namespace mozilla