Bug 1154512 - Remove MediaTaskQueue::SyncDispatch() from PDM. r=cpearce

--HG--
extra : rebase_source : 1aac8eec5a39097d5cb17dac529578a6af053bd0
This commit is contained in:
Alfredo Yang 2015-05-04 03:04:00 -04:00
Родитель 27ead4e7d8
Коммит e727de4c04
4 изменённых файлов: 44 добавлений и 172 удалений

Просмотреть файл

@ -26,94 +26,55 @@ using namespace android;
namespace mozilla {
GonkDecoderManager::GonkDecoderManager(MediaTaskQueue* aTaskQueue)
: mTaskQueue(aTaskQueue)
: mMonitor("GonkDecoderManager")
, mTaskQueue(aTaskQueue)
{
}
nsresult
GonkDecoderManager::Input(MediaRawData* aSample)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
// To maintain the order of the MP4Sample, it needs to send the queued samples
// to OMX first. And then the current input aSample.
// If it fails to input sample to OMX, it needs to add current into queue
// for next round.
uint32_t len = mQueueSample.Length();
status_t rv = OK;
for (uint32_t i = 0; i < len; i++) {
rv = SendSampleToOMX(mQueueSample.ElementAt(0));
if (rv != OK) {
break;
}
mQueueSample.RemoveElementAt(0);
}
// When EOS, aSample will be null and sends this empty MediaRawData to nofity
// OMX it reachs EOS.
ReentrantMonitorAutoEnter mon(mMonitor);
nsRefPtr<MediaRawData> sample;
if (!aSample) {
// It means EOS with empty sample.
sample = new MediaRawData();
}
// If rv is OK, that means mQueueSample is empty, now try to queue current input
// aSample.
if (rv == OK) {
MOZ_ASSERT(!mQueueSample.Length());
MediaRawData* tmp;
if (aSample) {
tmp = aSample;
if (!PerformFormatSpecificProcess(aSample)) {
return NS_ERROR_FAILURE;
}
} else {
tmp = sample;
}
rv = SendSampleToOMX(tmp);
if (rv == OK) {
return NS_OK;
} else {
sample = aSample;
if (!PerformFormatSpecificProcess(sample)) {
return NS_ERROR_FAILURE;
}
}
// Current valid sample can't be sent into OMX, adding the clone one into queue
// for next round.
if (!sample) {
sample = aSample->Clone();
if (!sample) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
mQueueSample.AppendElement(sample);
// In most cases, EAGAIN or ETIMEOUT safe due to OMX can't process the
// filled buffer on time. It should be gone When requeuing sample next time.
if (rv == -EAGAIN || rv == -ETIMEDOUT) {
return NS_OK;
status_t rv;
while (mQueueSample.Length()) {
nsRefPtr<MediaRawData> data = mQueueSample.ElementAt(0);
{
ReentrantMonitorAutoExit mon_exit(mMonitor);
rv = SendSampleToOMX(data);
}
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_ERROR_UNEXPECTED;
return NS_OK;
}
nsresult
GonkDecoderManager::Flush()
{
class ClearQueueRunnable : public nsRunnable
{
public:
explicit ClearQueueRunnable(GonkDecoderManager* aManager)
: mManager(aManager) {}
NS_IMETHOD Run()
{
mManager->ClearQueuedSample();
return NS_OK;
}
GonkDecoderManager* mManager;
};
mTaskQueue->SyncDispatch(new ClearQueueRunnable(this));
ReentrantMonitorAutoEnter mon(mMonitor);
mQueueSample.Clear();
return NS_OK;
}

Просмотреть файл

@ -44,17 +44,12 @@ public:
// in the overrided function.
virtual nsresult Flush();
// It should be called in MediaTash thread.
// It should be called in MediaTask thread.
bool HasQueuedSample() {
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
ReentrantMonitorAutoEnter mon(mMonitor);
return mQueueSample.Length();
}
void ClearQueuedSample() {
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
mQueueSample.Clear();
}
protected:
// It performs special operation to MP4 sample, the real action is depended on
// the codec type.
@ -63,6 +58,9 @@ protected:
// It sends MP4Sample to OMX layer. It must be overrided by subclass.
virtual android::status_t SendSampleToOMX(MediaRawData* aSample) = 0;
// This monitor protects mQueueSample.
ReentrantMonitor 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.

Просмотреть файл

@ -50,6 +50,7 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
: GonkDecoderManager(aTaskQueue)
, mImageContainer(aImageContainer)
, mReaderCallback(nullptr)
, mLastDecodedTime(0)
, mColorConverterBufferSize(0)
, mNativeWindow(nullptr)
, mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock")
@ -118,51 +119,6 @@ GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
return mDecoder;
}
void
GonkVideoDecoderManager::QueueFrameTimeIn(int64_t aPTS, int64_t aDuration)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
FrameTimeInfo timeInfo = {aPTS, aDuration};
mFrameTimeInfo.AppendElement(timeInfo);
}
nsresult
GonkVideoDecoderManager::QueueFrameTimeOut(int64_t aPTS, int64_t& aDuration)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
// Set default to 1 here.
// During seeking, frames could still in MediaCodec and the mFrameTimeInfo could
// be cleared before these frames are out from MediaCodec. This is ok because
// these frames are old frame before seeking.
aDuration = 1;
for (uint32_t i = 0; i < mFrameTimeInfo.Length(); i++) {
const FrameTimeInfo& entry = mFrameTimeInfo.ElementAt(i);
if (i == 0) {
if (entry.pts > aPTS) {
// Codec sent a frame with rollbacked PTS time. It could
// be codec's problem.
ReleaseVideoBuffer();
return NS_ERROR_NOT_AVAILABLE;
}
}
// Ideally, the first entry in mFrameTimeInfo should be the one we are looking
// for. However, MediaCodec could dropped frame and the first entry doesn't
// match current decoded frame's PTS.
if (entry.pts == aPTS) {
aDuration = entry.duration;
if (i > 0) {
LOG("Frame could be dropped by MediaCodec, %d dropped frames.", i);
}
mFrameTimeInfo.RemoveElementsAt(0, i+1);
break;
}
}
return NS_OK;
}
nsresult
GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
{
@ -181,9 +137,12 @@ GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
return NS_ERROR_UNEXPECTED;
}
int64_t duration;
nsresult rv = QueueFrameTimeOut(timeUs, duration);
NS_ENSURE_SUCCESS(rv, rv);
if (mLastDecodedTime > timeUs) {
ReleaseVideoBuffer();
GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
return NS_ERROR_NOT_AVAILABLE;
}
mLastDecodedTime = timeUs;
if (mVideoBuffer->range_length() == 0) {
// Some decoders may return spurious empty buffers that we just want to ignore
@ -224,7 +183,8 @@ GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
mImageContainer,
aStreamOffset,
timeUs,
duration,
1, // No way to pass sample duration from muxer to
// OMX codec, so we hardcode the duration here.
textureClient,
keyFrame,
-1,
@ -438,47 +398,17 @@ void GonkVideoDecoderManager::ReleaseVideoBuffer() {
status_t
GonkVideoDecoderManager::SendSampleToOMX(MediaRawData* aSample)
{
// An empty MediaRawData is going to notify EOS to decoder. It doesn't need
// to keep PTS and duration.
if (aSample->mData && aSample->mDuration && aSample->mTime) {
QueueFrameTimeIn(aSample->mTime, aSample->mDuration);
}
return mDecoder->Input(reinterpret_cast<const uint8_t*>(aSample->mData),
aSample->mSize,
aSample->mTime,
0);
}
void
GonkVideoDecoderManager::ClearQueueFrameTime()
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
mFrameTimeInfo.Clear();
}
nsresult
GonkVideoDecoderManager::Flush()
{
GonkDecoderManager::Flush();
class ClearFrameTimeRunnable : public nsRunnable
{
public:
explicit ClearFrameTimeRunnable(GonkVideoDecoderManager* aManager)
: mManager(aManager) {}
NS_IMETHOD Run()
{
mManager->ClearQueueFrameTime();
return NS_OK;
}
GonkVideoDecoderManager* mManager;
};
mTaskQueue->SyncDispatch(new ClearFrameTimeRunnable(this));
mLastDecodedTime = 0;
status_t err = mDecoder->flush();
if (err != OK) {
return NS_ERROR_FAILURE;

Просмотреть файл

@ -108,15 +108,6 @@ private:
};
friend class VideoResourceListener;
// FrameTimeInfo keeps the presentation time stamp (pts) and its duration.
// On MediaDecoderStateMachine, it needs pts and duration to display decoded
// frame correctly. But OMX can carry one field of time info (kKeyTime) so
// we use FrameTimeInfo to keep pts and duration.
struct FrameTimeInfo {
int64_t pts; // presentation time stamp of this frame.
int64_t duration; // the playback duration.
};
bool SetVideoFormat();
nsresult CreateVideoData(int64_t aStreamOffset, VideoData** aOutData);
@ -131,10 +122,6 @@ private:
void ReleaseAllPendingVideoBuffers();
void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer);
void QueueFrameTimeIn(int64_t aPTS, int64_t aDuration);
nsresult QueueFrameTimeOut(int64_t aPTS, int64_t& aDuration);
void ClearQueueFrameTime();
uint32_t mVideoWidth;
uint32_t mVideoHeight;
uint32_t mDisplayWidth;
@ -155,11 +142,7 @@ private:
android::sp<ALooper> mManagerLooper;
FrameInfo mFrameInfo;
// Array of FrameTimeInfo whose corresponding frames are sent to OMX.
// Ideally, it is a FIFO. Input() adds the entry to the end element and
// CreateVideoData() takes the first entry. However, there are exceptions
// due to MediaCodec error or seeking.
nsTArray<FrameTimeInfo> mFrameTimeInfo;
int64_t mLastDecodedTime; // The last decoded frame presentation time.
// color converter
android::I420ColorConverterHelper mColorConverter;