Squashed commit of the following:
commit 63be8ceb8b2354fb997a277c0092abae015ecf10 Author: Andreas Huber <andih@google.com> Date: Fri Dec 17 13:45:34 2010 -0800 Enable handling of discontinuities that involve potential format changes. Change-Id: I21848a113db8764abb54bdcf302b0923253eaf4d commit d18a7f80ec09af382026809263dcbbfa9e7a9ec8 Author: Andreas Huber <andih@google.com> Date: Fri Dec 17 13:45:01 2010 -0800 Signal whether or not a format change occured as part of the discontinuity. Change-Id: I06e64f542f4369549c9cebbb892dc612346ae43d commit c400adbd5fdbd65cfef7aed9ec65bcaace4bb69b Author: Andreas Huber <andih@google.com> Date: Fri Dec 17 13:44:46 2010 -0800 A little more instrumentation of ACodec Change-Id: I07f4aeccbbd15cdd9f80f48c3f92ee984ef6d92b commit 1d802ee01f47b3cdc5b89502cec7fbb595e197a3 Author: Andreas Huber <andih@google.com> Date: Fri Dec 17 13:43:58 2010 -0800 Only sync audio/video queues if both types of media are actually present. Change-Id: Ic88edf9bb1ebd4034c08747cce9877a4e28e0d35 commit e402da39d9a4d8b75653a78f728e20a3ef0fb497 Author: Andreas Huber <andih@google.com> Date: Fri Dec 17 13:42:24 2010 -0800 Disable the random seek for now. Change-Id: Iddd597b546e2f229e88214f9bdd6452bb188105e Change-Id: I27c4d9ba916080be94ce6117dbb095e9022ed62b
This commit is contained in:
@@ -151,6 +151,7 @@ struct DecoderWrapper::WrapperReader : public AHandler {
|
||||
const sp<AMessage> ¬ify);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void readMore(bool flush = false);
|
||||
|
||||
protected:
|
||||
@@ -189,6 +190,10 @@ void DecoderWrapper::WrapperReader::start() {
|
||||
readMore();
|
||||
}
|
||||
|
||||
void DecoderWrapper::WrapperReader::stop() {
|
||||
CHECK_EQ(mDecoder->stop(), (status_t)OK);
|
||||
}
|
||||
|
||||
void DecoderWrapper::WrapperReader::readMore(bool flush) {
|
||||
if (!flush && mEOS) {
|
||||
return;
|
||||
@@ -351,6 +356,10 @@ void DecoderWrapper::onMessageReceived(const sp<AMessage> &msg) {
|
||||
onSetup(msg);
|
||||
break;
|
||||
|
||||
case kWhatShutdown:
|
||||
onShutdown();
|
||||
break;
|
||||
|
||||
case kWhatInputDataRequested:
|
||||
{
|
||||
postFillBuffer();
|
||||
@@ -493,6 +502,25 @@ void DecoderWrapper::onSetup(const sp<AMessage> &msg) {
|
||||
++mNumPendingDecodes;
|
||||
}
|
||||
|
||||
void DecoderWrapper::onShutdown() {
|
||||
mReaderLooper->stop();
|
||||
mReaderLooper.clear();
|
||||
|
||||
mReader->stop();
|
||||
mReader.clear();
|
||||
|
||||
mSource.clear();
|
||||
|
||||
mNumOutstandingInputBuffers = 0;
|
||||
mNumOutstandingOutputBuffers = 0;
|
||||
mNumPendingDecodes = 0;
|
||||
mFlushing = false;
|
||||
|
||||
sp<AMessage> notify = mNotify->dup();
|
||||
notify->setInt32("what", ACodec::kWhatShutdownCompleted);
|
||||
notify->post();
|
||||
}
|
||||
|
||||
void DecoderWrapper::postFillBuffer() {
|
||||
sp<AMessage> notify = mNotify->dup();
|
||||
notify->setInt32("what", ACodec::kWhatFillThisBuffer);
|
||||
|
||||
@@ -66,6 +66,7 @@ private:
|
||||
bool mFlushing;
|
||||
|
||||
void onSetup(const sp<AMessage> &msg);
|
||||
void onShutdown();
|
||||
void onFlush();
|
||||
void onResume();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "NuPlayerRenderer.h"
|
||||
#include "NuPlayerStreamListener.h"
|
||||
|
||||
#include <media/stagefright/foundation/hexdump.h>
|
||||
#include <media/stagefright/foundation/ABuffer.h>
|
||||
#include <media/stagefright/foundation/ADebug.h>
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
@@ -31,6 +32,8 @@
|
||||
#include <media/stagefright/MetaData.h>
|
||||
#include <surfaceflinger/Surface.h>
|
||||
|
||||
#define SHUTDOWN_ON_DISCONTINUITY 0
|
||||
|
||||
namespace android {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -132,10 +135,16 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
|
||||
case kWhatScanSources:
|
||||
{
|
||||
instantiateDecoder(false, &mVideoDecoder);
|
||||
instantiateDecoder(
|
||||
false,
|
||||
&mVideoDecoder,
|
||||
false /* ignoreCodecSpecificData */);
|
||||
|
||||
if (mAudioSink != NULL) {
|
||||
instantiateDecoder(true, &mAudioDecoder);
|
||||
instantiateDecoder(
|
||||
true,
|
||||
&mAudioDecoder,
|
||||
false /* ignoreCodecSpecificData */);
|
||||
}
|
||||
|
||||
if (mEOS) {
|
||||
@@ -182,22 +191,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
|
||||
LOGI("decoder %s flush completed", audio ? "audio" : "video");
|
||||
|
||||
if (mFlushingAudio == FLUSHED && mFlushingVideo == FLUSHED) {
|
||||
LOGI("both audio and video are flushed now.");
|
||||
#if SHUTDOWN_ON_DISCONTINUITY
|
||||
LOGI("initiating %s decoder shutdown",
|
||||
audio ? "audio" : "video");
|
||||
|
||||
mRenderer->signalTimeDiscontinuity();
|
||||
(audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
|
||||
|
||||
if (mAudioDecoder != NULL) {
|
||||
mAudioDecoder->signalResume();
|
||||
}
|
||||
|
||||
if (mVideoDecoder != NULL) {
|
||||
mVideoDecoder->signalResume();
|
||||
}
|
||||
|
||||
mFlushingAudio = NONE;
|
||||
mFlushingVideo = NONE;
|
||||
if (audio) {
|
||||
mFlushingAudio = SHUTTING_DOWN_DECODER;
|
||||
} else {
|
||||
mFlushingVideo = SHUTTING_DOWN_DECODER;
|
||||
}
|
||||
#endif
|
||||
|
||||
finishFlushIfPossible();
|
||||
} else if (what == ACodec::kWhatOutputFormatChanged) {
|
||||
CHECK(audio);
|
||||
|
||||
@@ -213,6 +220,23 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
mAudioSink->close();
|
||||
CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
|
||||
mAudioSink->start();
|
||||
|
||||
mRenderer->signalAudioSinkChanged();
|
||||
} else if (what == ACodec::kWhatShutdownCompleted) {
|
||||
LOGI("%s shutdown completed", audio ? "audio" : "video");
|
||||
if (audio) {
|
||||
mAudioDecoder.clear();
|
||||
|
||||
CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
|
||||
mFlushingAudio = SHUT_DOWN;
|
||||
} else {
|
||||
mVideoDecoder.clear();
|
||||
|
||||
CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
|
||||
mFlushingVideo = SHUT_DOWN;
|
||||
}
|
||||
|
||||
finishFlushIfPossible();
|
||||
} else {
|
||||
CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
|
||||
|
||||
@@ -265,6 +289,43 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
}
|
||||
}
|
||||
|
||||
void NuPlayer::finishFlushIfPossible() {
|
||||
if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("both audio and video are flushed now.");
|
||||
|
||||
mRenderer->signalTimeDiscontinuity();
|
||||
|
||||
if (mFlushingAudio == SHUT_DOWN) {
|
||||
instantiateDecoder(
|
||||
true,
|
||||
&mAudioDecoder,
|
||||
true /* ignoreCodecSpecificData */);
|
||||
CHECK(mAudioDecoder != NULL);
|
||||
} else if (mAudioDecoder != NULL) {
|
||||
mAudioDecoder->signalResume();
|
||||
}
|
||||
|
||||
if (mFlushingVideo == SHUT_DOWN) {
|
||||
instantiateDecoder(
|
||||
false,
|
||||
&mVideoDecoder,
|
||||
true /* ignoreCodecSpecificData */);
|
||||
CHECK(mVideoDecoder != NULL);
|
||||
} else if (mVideoDecoder != NULL) {
|
||||
mVideoDecoder->signalResume();
|
||||
}
|
||||
|
||||
mFlushingAudio = NONE;
|
||||
mFlushingVideo = NONE;
|
||||
}
|
||||
|
||||
void NuPlayer::feedMoreTSData() {
|
||||
CHECK(!mEOS);
|
||||
|
||||
@@ -285,7 +346,10 @@ void NuPlayer::feedMoreTSData() {
|
||||
} else {
|
||||
if (buffer[0] == 0x00) {
|
||||
// XXX legacy
|
||||
mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
|
||||
mTSParser->signalDiscontinuity(
|
||||
buffer[1] == 0x00
|
||||
? ATSParser::DISCONTINUITY_SEEK
|
||||
: ATSParser::DISCONTINUITY_FORMATCHANGE);
|
||||
} else {
|
||||
mTSParser->feedTSPacket(buffer, sizeof(buffer));
|
||||
}
|
||||
@@ -354,7 +418,7 @@ status_t NuPlayer::dequeueAccessUnit(
|
||||
}
|
||||
|
||||
status_t NuPlayer::instantiateDecoder(
|
||||
bool audio, sp<Decoder> *decoder) {
|
||||
bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData) {
|
||||
if (*decoder != NULL) {
|
||||
return OK;
|
||||
}
|
||||
@@ -378,7 +442,7 @@ status_t NuPlayer::instantiateDecoder(
|
||||
looper()->registerHandler(*decoder);
|
||||
|
||||
const sp<MetaData> &meta = source->getFormat();
|
||||
(*decoder)->configure(meta);
|
||||
(*decoder)->configure(meta, ignoreCodecSpecificData);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -79,14 +79,16 @@ private:
|
||||
NONE,
|
||||
AWAITING_DISCONTINUITY,
|
||||
FLUSHING_DECODER,
|
||||
FLUSHED
|
||||
SHUTTING_DOWN_DECODER,
|
||||
FLUSHED,
|
||||
SHUT_DOWN,
|
||||
};
|
||||
|
||||
FlushStatus mFlushingAudio;
|
||||
FlushStatus mFlushingVideo;
|
||||
|
||||
status_t instantiateDecoder(
|
||||
bool audio, sp<Decoder> *decoder);
|
||||
bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData);
|
||||
|
||||
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
|
||||
void renderBuffer(bool audio, const sp<AMessage> &msg);
|
||||
@@ -100,6 +102,8 @@ private:
|
||||
void feedMoreTSData();
|
||||
void notifyListener(int msg, int ext1, int ext2);
|
||||
|
||||
void finishFlushIfPossible();
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ NuPlayer::Decoder::Decoder(
|
||||
NuPlayer::Decoder::~Decoder() {
|
||||
}
|
||||
|
||||
void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
|
||||
void NuPlayer::Decoder::configure(
|
||||
const sp<MetaData> &meta, bool ignoreCodecSpecificData) {
|
||||
CHECK(mCodec == NULL);
|
||||
CHECK(mWrapper == NULL);
|
||||
|
||||
@@ -54,6 +55,10 @@ void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
|
||||
|
||||
sp<AMessage> format = makeFormat(meta);
|
||||
|
||||
if (ignoreCodecSpecificData) {
|
||||
mCSD.clear();
|
||||
}
|
||||
|
||||
if (mSurface != NULL) {
|
||||
format->setObject("surface", mSurface);
|
||||
}
|
||||
@@ -282,5 +287,14 @@ void NuPlayer::Decoder::signalResume() {
|
||||
}
|
||||
}
|
||||
|
||||
void NuPlayer::Decoder::initiateShutdown() {
|
||||
if (mCodec != NULL) {
|
||||
mCodec->initiateShutdown();
|
||||
} else {
|
||||
CHECK(mWrapper != NULL);
|
||||
mWrapper->initiateShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -29,9 +29,12 @@ struct DecoderWrapper;
|
||||
struct NuPlayer::Decoder : public AHandler {
|
||||
Decoder(const sp<AMessage> ¬ify, const sp<Surface> &surface = NULL);
|
||||
|
||||
void configure(const sp<MetaData> &meta);
|
||||
void configure(
|
||||
const sp<MetaData> &meta, bool ignoreCodecSpecificData);
|
||||
|
||||
void signalFlush();
|
||||
void signalResume();
|
||||
void initiateShutdown();
|
||||
|
||||
protected:
|
||||
virtual ~Decoder();
|
||||
|
||||
@@ -39,7 +39,9 @@ NuPlayer::Renderer::Renderer(
|
||||
mAnchorTimeRealUs(-1),
|
||||
mFlushingAudio(false),
|
||||
mFlushingVideo(false),
|
||||
mSyncQueues(true) {
|
||||
mHasAudio(mAudioSink != NULL),
|
||||
mHasVideo(true),
|
||||
mSyncQueues(mHasAudio && mHasVideo) {
|
||||
}
|
||||
|
||||
NuPlayer::Renderer::~Renderer() {
|
||||
@@ -87,7 +89,7 @@ void NuPlayer::Renderer::signalTimeDiscontinuity() {
|
||||
CHECK(mVideoQueue.empty());
|
||||
mAnchorTimeMediaUs = -1;
|
||||
mAnchorTimeRealUs = -1;
|
||||
mSyncQueues = true;
|
||||
mSyncQueues = mHasAudio && mHasVideo;
|
||||
}
|
||||
|
||||
void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
@@ -142,6 +144,12 @@ void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
|
||||
break;
|
||||
}
|
||||
|
||||
case kWhatAudioSinkChanged:
|
||||
{
|
||||
onAudioSinkChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRESPASS();
|
||||
break;
|
||||
@@ -163,6 +171,10 @@ void NuPlayer::Renderer::postDrainAudioQueue() {
|
||||
msg->post(10000);
|
||||
}
|
||||
|
||||
void NuPlayer::Renderer::signalAudioSinkChanged() {
|
||||
(new AMessage(kWhatAudioSinkChanged, id()))->post();
|
||||
}
|
||||
|
||||
void NuPlayer::Renderer::onDrainAudioQueue() {
|
||||
uint32_t numFramesPlayed;
|
||||
CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
|
||||
@@ -264,7 +276,7 @@ void NuPlayer::Renderer::postDrainVideoQueue() {
|
||||
if (mAnchorTimeMediaUs < 0) {
|
||||
delayUs = 0;
|
||||
|
||||
if (mAudioSink == NULL) {
|
||||
if (!mHasAudio) {
|
||||
mAnchorTimeMediaUs = mediaTimeUs;
|
||||
mAnchorTimeRealUs = ALooper::GetNowUs();
|
||||
}
|
||||
@@ -492,5 +504,10 @@ bool NuPlayer::Renderer::dropBufferWhileFlushing(
|
||||
return true;
|
||||
}
|
||||
|
||||
void NuPlayer::Renderer::onAudioSinkChanged() {
|
||||
CHECK(!mDrainAudioQueuePending);
|
||||
mNumFramesWritten = 0;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ struct NuPlayer::Renderer : public AHandler {
|
||||
|
||||
void signalTimeDiscontinuity();
|
||||
|
||||
void signalAudioSinkChanged();
|
||||
|
||||
enum {
|
||||
kWhatEOS,
|
||||
kWhatFlushComplete,
|
||||
@@ -54,6 +56,7 @@ private:
|
||||
kWhatQueueBuffer,
|
||||
kWhatQueueEOS,
|
||||
kWhatFlush,
|
||||
kWhatAudioSinkChanged,
|
||||
};
|
||||
|
||||
struct QueueEntry {
|
||||
@@ -81,6 +84,8 @@ private:
|
||||
bool mFlushingAudio;
|
||||
bool mFlushingVideo;
|
||||
|
||||
bool mHasAudio;
|
||||
bool mHasVideo;
|
||||
bool mSyncQueues;
|
||||
|
||||
void onDrainAudioQueue();
|
||||
@@ -92,6 +97,7 @@ private:
|
||||
void onQueueBuffer(const sp<AMessage> &msg);
|
||||
void onQueueEOS(const sp<AMessage> &msg);
|
||||
void onFlush(const sp<AMessage> &msg);
|
||||
void onAudioSinkChanged();
|
||||
|
||||
void notifyEOS(bool audio);
|
||||
void notifyFlushComplete(bool audio);
|
||||
|
||||
@@ -1157,6 +1157,9 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
|
||||
if (!msg->findObject("buffer", &obj)) {
|
||||
CHECK(msg->findInt32("err", &err));
|
||||
|
||||
LOGV("[%s] saw error %d instead of an input buffer",
|
||||
mCodec->mComponentName.c_str(), err);
|
||||
|
||||
obj.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -468,13 +468,16 @@ void LiveSession::onDownloadNext() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (explicitDiscontinuity
|
||||
|| (mPrevBandwidthIndex >= 0
|
||||
&& (size_t)mPrevBandwidthIndex != bandwidthIndex)) {
|
||||
bool bandwidthChanged =
|
||||
mPrevBandwidthIndex >= 0
|
||||
&& (size_t)mPrevBandwidthIndex != bandwidthIndex;
|
||||
|
||||
if (explicitDiscontinuity || bandwidthChanged) {
|
||||
// Signal discontinuity.
|
||||
|
||||
sp<ABuffer> tmp = new ABuffer(188);
|
||||
memset(tmp->data(), 0, tmp->size());
|
||||
tmp->data()[1] = bandwidthChanged;
|
||||
|
||||
mDataSource->queueBuffer(tmp);
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ ATSParser::Stream::Stream(
|
||||
: mProgram(program),
|
||||
mElementaryPID(elementaryPID),
|
||||
mStreamType(streamType),
|
||||
mBuffer(new ABuffer(128 * 1024)),
|
||||
mBuffer(new ABuffer(192 * 1024)),
|
||||
mPayloadStarted(false),
|
||||
mQueue(streamType == 0x1b
|
||||
? ElementaryStreamQueue::H264 : ElementaryStreamQueue::AAC) {
|
||||
|
||||
Reference in New Issue
Block a user