diff options
-rw-r--r-- | include/media/mediaplayer.h | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp | 20 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/HTTPLiveSource.h | 12 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 82 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.h | 15 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp | 131 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDriver.h | 23 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 18 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerSource.h | 12 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/StreamingSource.h | 8 | ||||
-rw-r--r-- | media/libstagefright/httplive/LiveSession.cpp | 18 | ||||
-rw-r--r-- | media/libstagefright/include/LiveSession.h | 2 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/ATSParser.cpp | 12 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/ATSParser.h | 2 |
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(); |