summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/mediaplayer.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp20
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.h12
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp82
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h15
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp131
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h23
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp18
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerSource.h12
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.h8
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp18
-rw-r--r--media/libstagefright/include/LiveSession.h2
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp12
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.h2
15 files changed, 313 insertions, 45 deletions
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 178f0db..88b0c3e 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -36,7 +36,6 @@ enum media_event_type {
MEDIA_BUFFERING_UPDATE = 3,
MEDIA_SEEK_COMPLETE = 4,
MEDIA_SET_VIDEO_SIZE = 5,
- MEDIA_RESET_COMPLETE = 6, // not visible on java side
MEDIA_ERROR = 100,
MEDIA_INFO = 200,
};
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 29e4971..b81e0e9 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -128,5 +128,25 @@ status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
return source->dequeueAccessUnit(accessUnit);
}
+status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
+ return mLiveSession->getDuration(durationUs);
+}
+
+status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
+ // We need to make sure we're not seeking until we have seen the very first
+ // PTS timestamp in the whole stream (from the beginning of the stream).
+ while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData()) {
+ usleep(100000);
+ }
+
+ mLiveSession->seekTo(seekTimeUs);
+
+ return OK;
+}
+
+bool NuPlayer::HTTPLiveSource::isSeekable() {
+ return mLiveSession->isSeekable();
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 1b97699..f3f539a 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -29,13 +29,17 @@ struct LiveSession;
struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
HTTPLiveSource(const char *url);
- void start();
+ virtual void start();
// Returns true iff more data was available, false on EOS.
- bool feedMoreTSData();
+ virtual bool feedMoreTSData();
- sp<MetaData> getFormat(bool audio);
- status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(int64_t seekTimeUs);
+ virtual bool isSeekable();
protected:
virtual ~HTTPLiveSource();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 9a8cff3..a607b31 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -22,6 +22,7 @@
#include "HTTPLiveSource.h"
#include "NuPlayerDecoder.h"
+#include "NuPlayerDriver.h"
#include "NuPlayerRenderer.h"
#include "NuPlayerSource.h"
#include "StreamingSource.h"
@@ -55,8 +56,8 @@ NuPlayer::NuPlayer()
NuPlayer::~NuPlayer() {
}
-void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
- mListener = listener;
+void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
+ mDriver = driver;
}
void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
@@ -90,10 +91,24 @@ void NuPlayer::start() {
(new AMessage(kWhatStart, id()))->post();
}
+void NuPlayer::pause() {
+ // XXX to be implemented
+}
+
+void NuPlayer::resume() {
+ // XXX to be implemented
+}
+
void NuPlayer::resetAsync() {
(new AMessage(kWhatReset, id()))->post();
}
+void NuPlayer::seekToAsync(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatSeek, id());
+ msg->setInt64("seekTimeUs", seekTimeUs);
+ msg->post();
+}
+
// static
bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
switch (state) {
@@ -153,6 +168,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatStart:
{
+ LOGV("kWhatStart");
+
mAudioEOS = false;
mVideoEOS = false;
@@ -179,6 +196,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mScanSourcesPending = false;
+ LOGV("scanning sources haveAudio=%d, haveVideo=%d",
+ mAudioDecoder != NULL, mVideoDecoder != NULL);
+
instantiateDecoder(false, &mVideoDecoder);
if (mAudioSink != NULL) {
@@ -312,6 +332,16 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
&& (mVideoEOS || mVideoDecoder == NULL)) {
notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
}
+ } else if (what == Renderer::kWhatPosition) {
+ int64_t positionUs;
+ CHECK(msg->findInt64("positionUs", &positionUs));
+
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyPosition(positionUs);
+ }
+ }
} else {
CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
@@ -359,6 +389,26 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatSeek:
+ {
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+
+ LOGI("kWhatSeek seekTimeUs=%lld us (%.2f secs)",
+ seekTimeUs, seekTimeUs / 1E6);
+
+ mSource->seekTo(seekTimeUs);
+
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifySeekComplete();
+ }
+ }
+
+ break;
+ }
+
default:
TRESPASS();
break;
@@ -415,7 +465,12 @@ void NuPlayer::finishReset() {
mRenderer.clear();
mSource.clear();
- notifyListener(MEDIA_RESET_COMPLETE, 0, 0);
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyResetComplete();
+ }
+ }
}
void NuPlayer::postScanSources() {
@@ -450,6 +505,14 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
(*decoder)->configure(meta);
+ int64_t durationUs;
+ if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyDuration(durationUs);
+ }
+ }
+
return OK;
}
@@ -488,7 +551,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
return OK;
}
- LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
+ // LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
#if 0
int64_t mediaTimeUs;
@@ -505,7 +568,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
}
void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
- LOGV("renderBuffer %s", audio ? "audio" : "video");
+ // LOGV("renderBuffer %s", audio ? "audio" : "video");
sp<AMessage> reply;
CHECK(msg->findMessage("reply", &reply));
@@ -519,22 +582,23 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
}
void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
- if (mListener == NULL) {
+ if (mDriver == NULL) {
return;
}
- sp<MediaPlayerBase> listener = mListener.promote();
+ sp<NuPlayerDriver> driver = mDriver.promote();
- if (listener == NULL) {
+ if (driver == NULL) {
return;
}
- listener->sendEvent(msg, ext1, ext2);
+ driver->sendEvent(msg, ext1, ext2);
}
void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
// Make sure we don't continue to scan sources until we finish flushing.
++mScanSourcesGeneration;
+ mScanSourcesPending = false;
(audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
mRenderer->flush(audio);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 1cf2f60..339b628 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -25,11 +25,12 @@ namespace android {
struct ACodec;
struct MetaData;
+struct NuPlayerDriver;
struct NuPlayer : public AHandler {
NuPlayer();
- void setListener(const wp<MediaPlayerBase> &listener);
+ void setDriver(const wp<NuPlayerDriver> &driver);
void setDataSource(const sp<IStreamSource> &source);
@@ -40,10 +41,15 @@ struct NuPlayer : public AHandler {
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
void start();
- // Will notify the listener that reset() has completed
- // with code MEDIA_RESET_COMPLETE.
+ void pause();
+ void resume();
+
+ // Will notify the driver through "notifyResetComplete" once finished.
void resetAsync();
+ // Will notify the driver through "notifySeekComplete" once finished.
+ void seekToAsync(int64_t seekTimeUs);
+
protected:
virtual ~NuPlayer();
@@ -68,9 +74,10 @@ private:
kWhatAudioNotify,
kWhatRendererNotify,
kWhatReset,
+ kWhatSeek,
};
- wp<MediaPlayerBase> mListener;
+ wp<NuPlayerDriver> mDriver;
sp<Source> mSource;
sp<Surface> mSurface;
sp<MediaPlayerBase::AudioSink> mAudioSink;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 4988d24..ac19a2f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -29,8 +29,11 @@ namespace android {
NuPlayerDriver::NuPlayerDriver()
: mResetInProgress(false),
+ mDurationUs(-1),
+ mPositionUs(-1),
mLooper(new ALooper),
- mPlayer(false) {
+ mState(UNINITIALIZED),
+ mStartupSeekTimeUs(-1) {
mLooper->setName("NuPlayerDriver Looper");
mLooper->start(
@@ -41,7 +44,7 @@ NuPlayerDriver::NuPlayerDriver()
mPlayer = new NuPlayer;
mLooper->registerHandler(mPlayer);
- mPlayer->setListener(this);
+ mPlayer->setDriver(this);
}
NuPlayerDriver::~NuPlayerDriver() {
@@ -54,8 +57,12 @@ status_t NuPlayerDriver::initCheck() {
status_t NuPlayerDriver::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
mPlayer->setDataSource(url, headers);
+ mState = STOPPED;
+
return OK;
}
@@ -64,8 +71,12 @@ status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
}
status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
mPlayer->setDataSource(source);
+ mState = STOPPED;
+
return OK;
}
@@ -86,38 +97,110 @@ status_t NuPlayerDriver::prepareAsync() {
}
status_t NuPlayerDriver::start() {
- mPlayer->start();
- mPlaying = true;
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ {
+ mPlayer->start();
+
+ if (mStartupSeekTimeUs >= 0) {
+ mPlayer->seekToAsync(mStartupSeekTimeUs);
+ mStartupSeekTimeUs = -1;
+ }
+ break;
+ }
+ case PLAYING:
+ return OK;
+ default:
+ {
+ CHECK_EQ((int)mState, (int)PAUSED);
+
+ mPlayer->resume();
+ break;
+ }
+ }
+
+ mState = PLAYING;
return OK;
}
status_t NuPlayerDriver::stop() {
- mPlaying = false;
- return OK;
+ return pause();
}
status_t NuPlayerDriver::pause() {
- mPlaying = false;
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ return OK;
+ case PLAYING:
+ mPlayer->pause();
+ break;
+ default:
+ {
+ CHECK_EQ((int)mState, (int)PAUSED);
+ return OK;
+ }
+ }
+
+ mState = PAUSED;
+
return OK;
}
bool NuPlayerDriver::isPlaying() {
- return mPlaying;
+ return mState == PLAYING;
}
status_t NuPlayerDriver::seekTo(int msec) {
- return INVALID_OPERATION;
+ int64_t seekTimeUs = msec * 1000ll;
+
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ {
+ mStartupSeekTimeUs = seekTimeUs;
+ break;
+ }
+ case PLAYING:
+ case PAUSED:
+ {
+ mPlayer->seekToAsync(seekTimeUs);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+
+ return OK;
}
status_t NuPlayerDriver::getCurrentPosition(int *msec) {
- *msec = 0;
+ Mutex::Autolock autoLock(mLock);
+
+ if (mPositionUs < 0) {
+ *msec = 0;
+ } else {
+ *msec = (mPositionUs + 500ll) / 1000;
+ }
return OK;
}
status_t NuPlayerDriver::getDuration(int *msec) {
- *msec = 0;
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDurationUs < 0) {
+ *msec = 0;
+ } else {
+ *msec = (mDurationUs + 500ll) / 1000;
+ }
return OK;
}
@@ -132,6 +215,11 @@ status_t NuPlayerDriver::reset() {
mCondition.wait(mLock);
}
+ mDurationUs = -1;
+ mPositionUs = -1;
+ mState = UNINITIALIZED;
+ mStartupSeekTimeUs = -1;
+
return OK;
}
@@ -156,16 +244,25 @@ status_t NuPlayerDriver::getMetadata(
return INVALID_OPERATION;
}
-void NuPlayerDriver::sendEvent(int msg, int ext1, int ext2) {
- if (msg != MEDIA_RESET_COMPLETE) {
- MediaPlayerInterface::sendEvent(msg, ext1, ext2);
- return;
- }
-
+void NuPlayerDriver::notifyResetComplete() {
Mutex::Autolock autoLock(mLock);
CHECK(mResetInProgress);
mResetInProgress = false;
mCondition.broadcast();
}
+void NuPlayerDriver::notifyDuration(int64_t durationUs) {
+ Mutex::Autolock autoLock(mLock);
+ mDurationUs = durationUs;
+}
+
+void NuPlayerDriver::notifyPosition(int64_t positionUs) {
+ Mutex::Autolock autoLock(mLock);
+ mPositionUs = positionUs;
+}
+
+void NuPlayerDriver::notifySeekComplete() {
+ sendEvent(MEDIA_SEEK_COMPLETE);
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index f153af4..e3a5de4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -54,7 +54,10 @@ struct NuPlayerDriver : public MediaPlayerInterface {
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
- virtual void sendEvent(int msg, int ext1 = 0, int ext2 = 0);
+ void notifyResetComplete();
+ void notifyDuration(int64_t durationUs);
+ void notifyPosition(int64_t positionUs);
+ void notifySeekComplete();
protected:
virtual ~NuPlayerDriver();
@@ -62,11 +65,27 @@ protected:
private:
Mutex mLock;
Condition mCondition;
+
+ // The following are protected through "mLock"
+ // >>>
bool mResetInProgress;
+ int64_t mDurationUs;
+ int64_t mPositionUs;
+ // <<<
sp<ALooper> mLooper;
sp<NuPlayer> mPlayer;
- bool mPlaying;
+
+ enum State {
+ UNINITIALIZED,
+ STOPPED,
+ PLAYING,
+ PAUSED
+ };
+
+ State mState;
+
+ int64_t mStartupSeekTimeUs;
DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 00cbec2..5833697 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -249,6 +249,8 @@ void NuPlayer::Renderer::onDrainAudioQueue() {
numBytesAvailableToWrite -= copy;
mNumFramesWritten += copy / mAudioSink->frameSize();
}
+
+ notifyPosition();
}
void NuPlayer::Renderer::postDrainVideoQueue() {
@@ -322,6 +324,8 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
entry->mNotifyConsumed->post();
mVideoQueue.erase(mVideoQueue.begin());
entry = NULL;
+
+ notifyPosition();
}
void NuPlayer::Renderer::notifyEOS(bool audio) {
@@ -510,5 +514,19 @@ void NuPlayer::Renderer::onAudioSinkChanged() {
mNumFramesWritten = 0;
}
+void NuPlayer::Renderer::notifyPosition() {
+ if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
+ return;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatPosition);
+ notify->setInt64("positionUs", positionUs);
+ notify->post();
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index fb3903c..dbf3ecf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -44,6 +44,7 @@ struct NuPlayer::Renderer : public AHandler {
enum {
kWhatEOS,
kWhatFlushComplete,
+ kWhatPosition,
};
protected:
@@ -103,6 +104,7 @@ private:
void notifyEOS(bool audio);
void notifyFlushComplete(bool audio);
+ void notifyPosition();
void flushQueue(List<QueueEntry> *queue);
bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 044e202..5e55487 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -37,6 +37,18 @@ struct NuPlayer::Source : public RefBase {
virtual status_t dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) = 0;
+ virtual status_t getDuration(int64_t *durationUs) {
+ return INVALID_OPERATION;
+ }
+
+ virtual status_t seekTo(int64_t seekTimeUs) {
+ return INVALID_OPERATION;
+ }
+
+ virtual bool isSeekable() {
+ return false;
+ }
+
protected:
virtual ~Source() {}
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
index 5f0a9dd..7abce84 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.h
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -29,13 +29,13 @@ struct ATSParser;
struct NuPlayer::StreamingSource : public NuPlayer::Source {
StreamingSource(const sp<IStreamSource> &source);
- void start();
+ virtual void start();
// Returns true iff more data was available, false on EOS.
- bool feedMoreTSData();
+ virtual bool feedMoreTSData();
- sp<MetaData> getFormat(bool audio);
- status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
protected:
virtual ~StreamingSource();
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 5b1f14d..51ab7a1 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -395,10 +395,17 @@ void LiveSession::onDownloadNext() {
int64_t index = seekTimeSecs / targetDuration;
if (index >= 0 && index < mPlaylist->size()) {
- mSeqNumber = firstSeqNumberInPlaylist + index;
- mDataSource->reset();
+ int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
- explicitDiscontinuity = true;
+ if (newSeqNumber != mSeqNumber) {
+ LOGI("seeking to seq no %d", newSeqNumber);
+
+ mSeqNumber = newSeqNumber;
+
+ mDataSource->reset();
+
+ explicitDiscontinuity = true;
+ }
}
}
@@ -463,6 +470,8 @@ void LiveSession::onDownloadNext() {
return;
}
+ CHECK(buffer != NULL);
+
CHECK_EQ((status_t)OK,
decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer));
@@ -482,6 +491,9 @@ void LiveSession::onDownloadNext() {
if (explicitDiscontinuity || bandwidthChanged) {
// Signal discontinuity.
+ LOGI("queueing discontinuity (explicit=%d, bandwidthChanged=%d)",
+ explicitDiscontinuity, bandwidthChanged);
+
sp<ABuffer> tmp = new ABuffer(188);
memset(tmp->data(), 0, tmp->size());
tmp->data()[1] = bandwidthChanged;
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 3873d5d..41f5ad0 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -49,7 +49,7 @@ protected:
private:
enum {
- kMaxNumQueuedFragments = 2,
+ kMaxNumQueuedFragments = 3,
kMaxNumRetries = 5,
};
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 7c81ffd..84a3860 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -56,6 +56,10 @@ struct ATSParser::Program : public RefBase {
int64_t convertPTSToTimestamp(uint64_t PTS);
+ bool PTSTimeDeltaEstablished() const {
+ return mFirstPTSValid;
+ }
+
private:
ATSParser *mParser;
unsigned mProgramMapPID;
@@ -734,4 +738,12 @@ sp<MediaSource> ATSParser::getSource(SourceType type) {
return NULL;
}
+bool ATSParser::PTSTimeDeltaEstablished() {
+ if (mPrograms.isEmpty()) {
+ return false;
+ }
+
+ return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
+}
+
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index ef78c77..fe31981 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -50,6 +50,8 @@ struct ATSParser : public RefBase {
};
sp<MediaSource> getSource(SourceType type);
+ bool PTSTimeDeltaEstablished();
+
protected:
virtual ~ATSParser();