summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2014-08-20 19:25:30 -0700
committerLajos Molnar <lajos@google.com>2014-08-23 08:49:27 -0700
commit87603c0dd1f4e62e52feffa8d6e960ad21f68893 (patch)
treeef7602edc3877ac901b6cb502a83d0288eb40868 /media/libmediaplayerservice
parent848726d845b51da04364bdaf4ec915c85d593c0e (diff)
downloadframeworks_av-87603c0dd1f4e62e52feffa8d6e960ad21f68893.zip
frameworks_av-87603c0dd1f4e62e52feffa8d6e960ad21f68893.tar.gz
frameworks_av-87603c0dd1f4e62e52feffa8d6e960ad21f68893.tar.bz2
NuPlayer: remember and resubmit CSDs after flush
Bug: 17118001 Change-Id: I09bbefd4c05de0db1c593e8d6d38859358a20ebb
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp65
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h9
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp57
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h7
4 files changed, 117 insertions, 21 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index b79a5dd..f4cd02c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -756,7 +756,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
ALOGV("initiating %s decoder shutdown",
audio ? "audio" : "video");
- (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
+ getDecoder(audio)->initiateShutdown();
if (audio) {
mFlushingAudio = SHUTTING_DOWN_DECODER;
@@ -1292,7 +1292,24 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
mTimeDiscontinuityPending =
mTimeDiscontinuityPending || timeChange;
- if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
+ bool seamlessFormatChange = false;
+ sp<AMessage> newFormat = mSource->getFormat(audio);
+ if (formatChange) {
+ seamlessFormatChange =
+ getDecoder(audio)->supportsSeamlessFormatChange(newFormat);
+ // treat seamless format change separately
+ formatChange = !seamlessFormatChange;
+ }
+ bool shutdownOrFlush = formatChange || timeChange;
+
+ // We want to queue up scan-sources only once per discontinuity.
+ // We control this by doing it only if neither audio nor video are
+ // flushing or shutting down. (After handling 1st discontinuity, one
+ // of the flushing states will not be NONE.)
+ // No need to scan sources if this discontinuity does not result
+ // in a flush or shutdown, as the flushing state will stay NONE.
+ if (mFlushingAudio == NONE && mFlushingVideo == NONE &&
+ shutdownOrFlush) {
// And we'll resume scanning sources once we're done
// flushing.
mDeferredActions.push_front(
@@ -1300,16 +1317,17 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
&NuPlayer::performScanSources));
}
- if (formatChange || timeChange) {
-
- sp<AMessage> newFormat = mSource->getFormat(audio);
- sp<Decoder> &decoder = audio ? mAudioDecoder : mVideoDecoder;
- if (formatChange && !decoder->supportsSeamlessFormatChange(newFormat)) {
- flushDecoder(audio, /* needShutdown = */ true);
- } else {
- flushDecoder(audio, /* needShutdown = */ false);
- err = OK;
- }
+ if (formatChange /* not seamless */) {
+ // must change decoder
+ flushDecoder(audio, /* needShutdown = */ true);
+ } else if (timeChange) {
+ // need to flush
+ flushDecoder(audio, /* needShutdown = */ false, newFormat);
+ err = OK;
+ } else if (seamlessFormatChange) {
+ // reuse existing decoder and don't flush
+ updateDecoderFormatWithoutFlush(audio, newFormat);
+ err = OK;
} else {
// This stream is unaffected by the discontinuity
return -EWOULDBLOCK;
@@ -1488,20 +1506,23 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
driver->notifyListener(msg, ext1, ext2, in);
}
-void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+void NuPlayer::flushDecoder(
+ bool audio, bool needShutdown, const sp<AMessage> &newFormat) {
ALOGV("[%s] flushDecoder needShutdown=%d",
audio ? "audio" : "video", needShutdown);
- if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
+ const sp<Decoder> &decoder = getDecoder(audio);
+ if (decoder == NULL) {
ALOGI("flushDecoder %s without decoder present",
audio ? "audio" : "video");
+ return;
}
// Make sure we don't continue to scan sources until we finish flushing.
++mScanSourcesGeneration;
mScanSourcesPending = false;
- (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
+ decoder->signalFlush(newFormat);
mRenderer->flush(audio);
FlushStatus newStatus =
@@ -1518,6 +1539,20 @@ void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
}
}
+void NuPlayer::updateDecoderFormatWithoutFlush(
+ bool audio, const sp<AMessage> &format) {
+ ALOGV("[%s] updateDecoderFormatWithoutFlush", audio ? "audio" : "video");
+
+ const sp<Decoder> &decoder = getDecoder(audio);
+ if (decoder == NULL) {
+ ALOGI("updateDecoderFormatWithoutFlush %s without decoder present",
+ audio ? "audio" : "video");
+ return;
+ }
+
+ decoder->signalUpdateFormat(format);
+}
+
void NuPlayer::queueDecoderShutdown(
bool audio, bool video, const sp<AMessage> &reply) {
ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 96306db..511d752 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -25,6 +25,7 @@
namespace android {
struct ABuffer;
+struct AMessage;
struct MetaData;
struct NuPlayerDriver;
@@ -169,6 +170,10 @@ private:
bool mStarted;
+ inline const sp<Decoder> &getDecoder(bool audio) {
+ return audio ? mAudioDecoder : mVideoDecoder;
+ }
+
void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
void closeAudioSink();
@@ -185,7 +190,9 @@ private:
void finishFlushIfPossible();
- void flushDecoder(bool audio, bool needShutdown);
+ void flushDecoder(
+ bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
+ void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);
static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 47c46d6..d1aac50 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -71,6 +71,19 @@ status_t PostAndAwaitResponse(
return err;
}
+void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
+ mCSDsForCurrentFormat.clear();
+ for (int32_t i = 0; ; ++i) {
+ AString tag = "csd-";
+ tag.append(i);
+ sp<ABuffer> buffer;
+ if (!format->findBuffer(tag.c_str(), &buffer)) {
+ break;
+ }
+ mCSDsForCurrentFormat.push(buffer);
+ }
+}
+
void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
CHECK(mCodec == NULL);
@@ -123,6 +136,8 @@ void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
handleError(err);
return;
}
+ rememberCodecSpecificData(format);
+
// the following should work in configured state
CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
@@ -189,6 +204,12 @@ void NuPlayer::Decoder::configure(const sp<AMessage> &format) {
msg->post();
}
+void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
+ sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
+ msg->setMessage("format", format);
+ msg->post();
+}
+
status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id());
msg->setPointer("buffers", buffers);
@@ -229,6 +250,15 @@ bool NuPlayer::Decoder::handleAnInputBuffer() {
reply->setSize("buffer-ix", bufferIx);
reply->setInt32("generation", mBufferGeneration);
+ if (!mCSDsToSubmit.isEmpty()) {
+ sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
+ ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
+ reply->setBuffer("buffer", buffer);
+ mCSDsToSubmit.removeAt(0);
+ reply->post();
+ return true;
+ }
+
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatFillThisBuffer);
notify->setBuffer("buffer", mInputBuffers[bufferIx]);
@@ -312,10 +342,12 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
uint32_t flags = 0;
CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
- int32_t eos;
- // we do not expect CODECCONFIG or SYNCFRAME for decoder
+ int32_t eos, csd;
+ // we do not expect SYNCFRAME for decoder
if (buffer->meta()->findInt32("eos", &eos) && eos) {
flags |= MediaCodec::BUFFER_FLAG_EOS;
+ } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
+ flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
}
// copy into codec buffer
@@ -448,6 +480,7 @@ void NuPlayer::Decoder::onFlush() {
status_t err = OK;
if (mCodec != NULL) {
err = mCodec->flush();
+ mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
++mBufferGeneration;
}
@@ -515,6 +548,14 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatUpdateFormat:
+ {
+ sp<AMessage> format;
+ CHECK(msg->findMessage("format", &format));
+ rememberCodecSpecificData(format);
+ break;
+ }
+
case kWhatGetInputBuffers:
{
uint32_t replyID;
@@ -566,6 +607,10 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
case kWhatFlush:
{
+ sp<AMessage> format;
+ if (msg->findMessage("new-format", &format)) {
+ rememberCodecSpecificData(format);
+ }
onFlush();
break;
}
@@ -588,8 +633,12 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
}
}
-void NuPlayer::Decoder::signalFlush() {
- (new AMessage(kWhatFlush, id()))->post();
+void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) {
+ sp<AMessage> msg = new AMessage(kWhatFlush, id());
+ if (format != NULL) {
+ msg->setMessage("new-format", format);
+ }
+ msg->post();
}
void NuPlayer::Decoder::signalResume() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index c6fc237..67bddb8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -36,7 +36,8 @@ struct NuPlayer::Decoder : public AHandler {
virtual void init();
status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
- virtual void signalFlush();
+ virtual void signalFlush(const sp<AMessage> &format = NULL);
+ virtual void signalUpdateFormat(const sp<AMessage> &format);
virtual void signalResume();
virtual void initiateShutdown();
@@ -67,6 +68,7 @@ private:
kWhatRenderBuffer = 'rndr',
kWhatFlush = 'flus',
kWhatShutdown = 'shuD',
+ kWhatUpdateFormat = 'uFmt',
};
sp<AMessage> mNotify;
@@ -80,6 +82,8 @@ private:
Vector<sp<ABuffer> > mInputBuffers;
Vector<sp<ABuffer> > mOutputBuffers;
+ Vector<sp<ABuffer> > mCSDsForCurrentFormat;
+ Vector<sp<ABuffer> > mCSDsToSubmit;
Vector<bool> mInputBufferIsDequeued;
Vector<MediaBuffer *> mMediaBuffers;
@@ -103,6 +107,7 @@ private:
AString mComponentName;
bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const;
+ void rememberCodecSpecificData(const sp<AMessage> &format);
DISALLOW_EVIL_CONSTRUCTORS(Decoder);
};