Merge "Allow optional specification of a PTS timestamp when signalling a discontinuity."
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index 4b698e6..d310cee 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -45,6 +45,12 @@
virtual void queueBuffer(size_t index, size_t size) = 0;
+ // When signalling a discontinuity you can optionally
+ // specify an int64_t PTS timestamp in "msg".
+ // If present, rendering of data following the discontinuity
+ // will be suppressed until media time reaches this timestamp.
+ static const char *const kKeyResumeAtPTS;
+
virtual void issueCommand(
Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
};
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index 5069002..c14ee82 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -26,6 +26,9 @@
namespace android {
+// static
+const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
+
enum {
// IStreamSource
SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index b3314be..d07ea1b 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -96,10 +96,12 @@
} else {
if (buffer[0] == 0x00) {
// XXX legacy
+ sp<AMessage> extra;
mTSParser->signalDiscontinuity(
buffer[1] == 0x00
? ATSParser::DISCONTINUITY_SEEK
- : ATSParser::DISCONTINUITY_FORMATCHANGE);
+ : ATSParser::DISCONTINUITY_FORMATCHANGE,
+ extra);
} else {
mTSParser->feedTSPacket(buffer, sizeof(buffer));
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 474c056..d439f6e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -191,6 +191,8 @@
mAudioEOS = false;
mVideoEOS = false;
+ mSkipRenderingAudioUntilMediaTimeUs = -1;
+ mSkipRenderingVideoUntilMediaTimeUs = -1;
mSource->start();
@@ -592,6 +594,31 @@
LOGV("%s discontinuity (formatChange=%d)",
audio ? "audio" : "video", formatChange);
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs = -1;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs = -1;
+ }
+
+ sp<AMessage> extra;
+ if (accessUnit->meta()->findMessage("extra", &extra)
+ && extra != NULL) {
+ int64_t resumeAtMediaTimeUs;
+ if (extra->findInt64(
+ "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+ LOGI("suppressing rendering of %s until %lld us",
+ audio ? "audio" : "video", resumeAtMediaTimeUs);
+
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ }
+ }
+ }
+
flushDecoder(audio, formatChange);
}
@@ -627,6 +654,27 @@
sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
+ int64_t &skipUntilMediaTimeUs =
+ audio
+ ? mSkipRenderingAudioUntilMediaTimeUs
+ : mSkipRenderingVideoUntilMediaTimeUs;
+
+ if (skipUntilMediaTimeUs >= 0) {
+ int64_t mediaTimeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+ if (mediaTimeUs < skipUntilMediaTimeUs) {
+ LOGV("dropping %s buffer at time %lld as requested.",
+ audio ? "audio" : "video",
+ mediaTimeUs);
+
+ reply->post();
+ return;
+ }
+
+ skipUntilMediaTimeUs = -1;
+ }
+
mRenderer->queueBuffer(audio, buffer, reply);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index e7c6a42..fb5b001 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -112,6 +112,9 @@
bool mResetInProgress;
bool mResetPostponed;
+ int64_t mSkipRenderingAudioUntilMediaTimeUs;
+ int64_t mSkipRenderingVideoUntilMediaTimeUs;
+
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index a23beb7..885ebe4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -92,9 +92,12 @@
}
}
-ssize_t NuPlayer::NuPlayerStreamListener::read(void *data, size_t size) {
+ssize_t NuPlayer::NuPlayerStreamListener::read(
+ void *data, size_t size, sp<AMessage> *extra) {
CHECK_GT(size, 0u);
+ extra->clear();
+
Mutex::Autolock autoLock(mLock);
if (mEOS) {
@@ -122,6 +125,8 @@
case DISCONTINUITY:
{
+ *extra = entry->mExtra;
+
mQueue.erase(mQueue.begin());
entry = NULL;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
index f88e945..df0935d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
@@ -37,7 +37,7 @@
Command cmd, bool synchronous, const sp<AMessage> &extra);
void start();
- ssize_t read(void *data, size_t size);
+ ssize_t read(void *data, size_t size, sp<AMessage> *extra);
private:
enum {
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index b85ac9f..2016282 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -54,7 +54,8 @@
for (int32_t i = 0; i < 10; ++i) {
char buffer[188];
- ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
+ sp<AMessage> extra;
+ ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
if (n == 0) {
LOGI("input data EOS reached.");
@@ -62,7 +63,8 @@
mEOS = true;
break;
} else if (n == INFO_DISCONTINUITY) {
- mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
+ mTSParser->signalDiscontinuity(
+ ATSParser::DISCONTINUITY_SEEK, extra);
} else if (n < 0) {
CHECK_EQ(n, -EWOULDBLOCK);
break;
@@ -72,7 +74,8 @@
mTSParser->signalDiscontinuity(
buffer[1] == 0x00
? ATSParser::DISCONTINUITY_SEEK
- : ATSParser::DISCONTINUITY_FORMATCHANGE);
+ : ATSParser::DISCONTINUITY_FORMATCHANGE,
+ extra);
} else {
mTSParser->feedTSPacket(buffer, sizeof(buffer));
}
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 6056739..5ba4a4f 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <media/IStreamSource.h>
#include <utils/KeyedVector.h>
namespace android {
@@ -49,7 +50,9 @@
unsigned pid, unsigned payload_unit_start_indicator,
ABitReader *br);
- void signalDiscontinuity(DiscontinuityType type);
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
void signalEOS(status_t finalResult);
sp<MediaSource> getSource(SourceType type);
@@ -83,7 +86,9 @@
unsigned payload_unit_start_indicator,
ABitReader *br);
- void signalDiscontinuity(DiscontinuityType type);
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
void signalEOS(status_t finalResult);
sp<MediaSource> getSource(SourceType type);
@@ -100,6 +105,7 @@
sp<AnotherPacketSource> mSource;
bool mPayloadStarted;
DiscontinuityType mPendingDiscontinuity;
+ sp<AMessage> mPendingDiscontinuityExtra;
ElementaryStreamQueue mQueue;
@@ -112,7 +118,8 @@
void extractAACFrames(const sp<ABuffer> &buffer);
- void deferDiscontinuity(DiscontinuityType type);
+ void deferDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -150,9 +157,10 @@
return true;
}
-void ATSParser::Program::signalDiscontinuity(DiscontinuityType type) {
+void ATSParser::Program::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
for (size_t i = 0; i < mStreams.size(); ++i) {
- mStreams.editValueAt(i)->signalDiscontinuity(type);
+ mStreams.editValueAt(i)->signalDiscontinuity(type, extra);
}
}
@@ -283,7 +291,8 @@
mStreams.add(info.mPID, stream);
if (PIDsChanged) {
- stream->signalDiscontinuity(DISCONTINUITY_FORMATCHANGE);
+ sp<AMessage> extra;
+ stream->signalDiscontinuity(DISCONTINUITY_FORMATCHANGE, extra);
}
}
}
@@ -366,7 +375,8 @@
mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
}
-void ATSParser::Stream::signalDiscontinuity(DiscontinuityType type) {
+void ATSParser::Stream::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
mPayloadStarted = false;
mBuffer->setRange(0, 0);
@@ -378,10 +388,21 @@
mQueue.clear(!isASeek);
+ uint64_t resumeAtPTS;
+ if (extra != NULL
+ && extra->findInt64(
+ IStreamListener::kKeyResumeAtPTS,
+ (int64_t *)&resumeAtPTS)) {
+ int64_t resumeAtMediaTimeUs =
+ mProgram->convertPTSToTimestamp(resumeAtPTS);
+
+ extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+ }
+
if (mSource != NULL) {
- mSource->queueDiscontinuity(type);
+ mSource->queueDiscontinuity(type, extra);
} else {
- deferDiscontinuity(type);
+ deferDiscontinuity(type, extra);
}
break;
}
@@ -392,10 +413,12 @@
}
}
-void ATSParser::Stream::deferDiscontinuity(DiscontinuityType type) {
+void ATSParser::Stream::deferDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
if (type > mPendingDiscontinuity) {
// Only upgrade discontinuities.
mPendingDiscontinuity = type;
+ mPendingDiscontinuityExtra = extra;
}
}
@@ -596,8 +619,10 @@
mSource = new AnotherPacketSource(meta);
if (mPendingDiscontinuity != DISCONTINUITY_NONE) {
- mSource->queueDiscontinuity(mPendingDiscontinuity);
+ mSource->queueDiscontinuity(
+ mPendingDiscontinuity, mPendingDiscontinuityExtra);
mPendingDiscontinuity = DISCONTINUITY_NONE;
+ mPendingDiscontinuityExtra.clear();
}
mSource->queueAccessUnit(accessUnit);
@@ -639,9 +664,10 @@
parseTS(&br);
}
-void ATSParser::signalDiscontinuity(DiscontinuityType type) {
+void ATSParser::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
for (size_t i = 0; i < mPrograms.size(); ++i) {
- mPrograms.editItemAt(i)->signalDiscontinuity(type);
+ mPrograms.editItemAt(i)->signalDiscontinuity(type, extra);
}
}
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 455f9d5..3936f05 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -41,7 +41,10 @@
ATSParser();
void feedTSPacket(const void *data, size_t size);
- void signalDiscontinuity(DiscontinuityType type);
+
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
void signalEOS(status_t finalResult);
enum SourceType {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 0ad883b..59de17e 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -136,9 +136,11 @@
}
void AnotherPacketSource::queueDiscontinuity(
- ATSParser::DiscontinuityType type) {
+ ATSParser::DiscontinuityType type,
+ const sp<AMessage> &extra) {
sp<ABuffer> buffer = new ABuffer(0);
buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
+ buffer->meta()->setMessage("extra", extra);
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 6fe93f8..439c7853 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -46,7 +46,10 @@
status_t nextBufferTime(int64_t *timeUs);
void queueAccessUnit(const sp<ABuffer> &buffer);
- void queueDiscontinuity(ATSParser::DiscontinuityType type);
+
+ void queueDiscontinuity(
+ ATSParser::DiscontinuityType type, const sp<AMessage> &extra);
+
void signalEOS(status_t result);
status_t dequeueAccessUnit(sp<ABuffer> *buffer);