summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Jönsson <roger1.jonsson@sonymobile.com>2013-01-21 16:26:41 +0100
committerAndreas Huber <andih@google.com>2013-02-06 13:32:55 -0800
commitb50e83eca302a12f0fced6e7bab1b8617d63deaa (patch)
tree58992eeb6e5b4edef4a76e180c4e99be694754d9
parent0df36ec3303c2c6bf9b42c07945ac8bd234153f3 (diff)
downloadframeworks_av-b50e83eca302a12f0fced6e7bab1b8617d63deaa.zip
frameworks_av-b50e83eca302a12f0fced6e7bab1b8617d63deaa.tar.gz
frameworks_av-b50e83eca302a12f0fced6e7bab1b8617d63deaa.tar.bz2
RTSP buffering improvements
Added buffering start and end notifications for RTSP. MEDIA_INFO_BUFFERING_START is sent when buffering is started and MEDIA_INFO_BUFFERING_END is sent when the buffer has filled up. This patch also adds RTSP end of stream handling. EOS is signalled when BYE is received OR when detecting end of stream even if no actual EOS is received. Change-Id: I5cccb6845060ae6afd66d9f735b89da81476cd13
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp12
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerSource.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp80
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.h7
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp20
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.h3
-rw-r--r--media/libstagefright/rtsp/MyHandler.h4
8 files changed, 121 insertions, 13 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index bcefe63..ee25cc6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1293,6 +1293,18 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
break;
}
+ case Source::kWhatBufferingStart:
+ {
+ notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
+ break;
+ }
+
+ case Source::kWhatBufferingEnd:
+ {
+ notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
+ break;
+ }
+
default:
TRESPASS();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 8a75f83..1ba76a5 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -512,9 +512,15 @@ void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
entry.mFinalResult = finalResult;
if (audio) {
+ if (mAudioQueue.empty() && mSyncQueues) {
+ syncQueuesDone();
+ }
mAudioQueue.push_back(entry);
postDrainAudioQueue();
} else {
+ if (mVideoQueue.empty() && mSyncQueues) {
+ syncQueuesDone();
+ }
mVideoQueue.push_back(entry);
postDrainVideoQueue();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index f5d4c38..df84123 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -40,6 +40,8 @@ struct NuPlayer::Source : public AHandler {
kWhatPrepared,
kWhatFlagsChanged,
kWhatVideoSizeChanged,
+ kWhatBufferingStart,
+ kWhatBufferingEnd,
};
// The provides message is used to notify the player about various
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index d787647..b70d550 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -29,6 +29,8 @@
namespace android {
+const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+
NuPlayer::RTSPSource::RTSPSource(
const sp<AMessage> &notify,
const char *url,
@@ -45,8 +47,10 @@ NuPlayer::RTSPSource::RTSPSource(
mState(DISCONNECTED),
mFinalResult(OK),
mDisconnectReplyID(0),
- mStartingUp(true),
- mSeekGeneration(0) {
+ mBuffering(true),
+ mSeekGeneration(0),
+ mEOSTimeoutAudio(0),
+ mEOSTimeoutVideo(0) {
if (headers) {
mExtraHeaders = *headers;
@@ -96,6 +100,10 @@ void NuPlayer::RTSPSource::prepareAsync() {
mHandler->connect();
}
+
+ sp<AMessage> notifyStart = dupNotify();
+ notifyStart->setInt32("what", kWhatBufferingStart);
+ notifyStart->post();
}
void NuPlayer::RTSPSource::start() {
@@ -131,6 +139,13 @@ bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
static const int64_t kMinDurationUs = 2000000ll;
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
+ if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
+ || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
+ return true;
+ }
+
status_t err;
int64_t durationUs;
if (mAudioTrack != NULL
@@ -156,12 +171,16 @@ bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
status_t NuPlayer::RTSPSource::dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) {
- if (mStartingUp) {
+ if (mBuffering) {
if (!haveSufficientDataOnAllTracks()) {
return -EWOULDBLOCK;
}
- mStartingUp = false;
+ mBuffering = false;
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatBufferingEnd);
+ notify->post();
}
sp<AnotherPacketSource> source = getSource(audio);
@@ -172,9 +191,51 @@ status_t NuPlayer::RTSPSource::dequeueAccessUnit(
status_t finalResult;
if (!source->hasBufferAvailable(&finalResult)) {
- return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ if (finalResult == OK) {
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
+ sp<AnotherPacketSource> otherSource = getSource(!audio);
+ status_t otherFinalResult;
+
+ // If other source already signaled EOS, this source should also signal EOS
+ if (otherSource != NULL &&
+ !otherSource->hasBufferAvailable(&otherFinalResult) &&
+ otherFinalResult == ERROR_END_OF_STREAM) {
+ source->signalEOS(ERROR_END_OF_STREAM);
+ return ERROR_END_OF_STREAM;
+ }
+
+ // If this source has detected near end, give it some time to retrieve more
+ // data before signaling EOS
+ if (source->isFinished(mediaDurationUs)) {
+ int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
+ if (eosTimeout == 0) {
+ setEOSTimeout(audio, ALooper::GetNowUs());
+ } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
+ setEOSTimeout(audio, 0);
+ source->signalEOS(ERROR_END_OF_STREAM);
+ return ERROR_END_OF_STREAM;
+ }
+ return -EWOULDBLOCK;
+ }
+
+ if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
+ // We should not enter buffering mode
+ // if any of the sources already have detected EOS.
+ mBuffering = true;
+
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatBufferingStart);
+ notify->post();
+ }
+
+ return -EWOULDBLOCK;
+ }
+ return finalResult;
}
+ setEOSTimeout(audio, 0);
+
return source->dequeueAccessUnit(accessUnit);
}
@@ -189,6 +250,14 @@ sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
return audio ? mAudioTrack : mVideoTrack;
}
+void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
+ if (audio) {
+ mEOSTimeoutAudio = timeout;
+ } else {
+ mEOSTimeoutVideo = timeout;
+ }
+}
+
status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
*durationUs = 0ll;
@@ -289,7 +358,6 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
case MyHandler::kWhatSeekDone:
{
mState = CONNECTED;
- mStartingUp = true;
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index cbb6f90..8451b9e 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -95,7 +95,7 @@ private:
State mState;
status_t mFinalResult;
uint32_t mDisconnectReplyID;
- bool mStartingUp;
+ bool mBuffering;
sp<ALooper> mLooper;
sp<AHandlerReflector<RTSPSource> > mReflector;
@@ -110,6 +110,9 @@ private:
int32_t mSeekGeneration;
+ int64_t mEOSTimeoutAudio;
+ int64_t mEOSTimeoutVideo;
+
sp<AnotherPacketSource> getSource(bool audio);
void onConnected();
@@ -121,6 +124,8 @@ private:
bool haveSufficientDataOnAllTracks();
+ void setEOSTimeout(bool audio, int64_t timeout);
+
DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
};
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index a605a05..3de3a61 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -28,9 +28,12 @@
namespace android {
+const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
+
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
: mIsAudio(false),
mFormat(meta),
+ mLastQueuedTimeUs(0),
mEOSResult(OK) {
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
@@ -141,9 +144,8 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
return;
}
- int64_t timeUs;
- CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
- ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
+ CHECK(buffer->meta()->findInt64("timeUs", &mLastQueuedTimeUs));
+ ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6);
Mutex::Autolock autoLock(mLock);
mBuffers.push_back(buffer);
@@ -171,6 +173,7 @@ void AnotherPacketSource::queueDiscontinuity(
}
mEOSResult = OK;
+ mLastQueuedTimeUs = 0;
sp<ABuffer> buffer = new ABuffer(0);
buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
@@ -247,4 +250,15 @@ status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
return OK;
}
+bool AnotherPacketSource::isFinished(int64_t duration) const {
+ if (duration > 0) {
+ int64_t diff = duration - mLastQueuedTimeUs;
+ if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) {
+ ALOGV("Detecting EOS due to near end");
+ return true;
+ }
+ }
+ return (mEOSResult != OK);
+}
+
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index d685b98..1db4068 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -58,6 +58,8 @@ struct AnotherPacketSource : public MediaSource {
status_t dequeueAccessUnit(sp<ABuffer> *buffer);
+ bool isFinished(int64_t duration) const;
+
protected:
virtual ~AnotherPacketSource();
@@ -67,6 +69,7 @@ private:
bool mIsAudio;
sp<MetaData> mFormat;
+ int64_t mLastQueuedTimeUs;
List<sp<ABuffer> > mBuffers;
status_t mEOSResult;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index aa64060..cfbf501 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -945,9 +945,7 @@ struct MyHandler : public AHandler {
int32_t eos;
if (msg->findInt32("eos", &eos)) {
ALOGI("received BYE on track index %d", trackIndex);
-#if 0
- track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
-#endif
+ postQueueEOS(trackIndex, ERROR_END_OF_STREAM);
return;
}