mTryFakeRTCP(false),
mReceivedFirstRTCPPacket(false),
mReceivedFirstRTPPacket(false),
- mSeekable(false),
+ mSeekable(true),
mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs),
mKeepAliveGeneration(0) {
mNetLooper->setName("rtsp net");
return true;
}
+ static bool isLiveStream(const sp<ASessionDescription> &desc) {
+ AString attrLiveStream;
+ if (desc->findAttribute(0, "a=LiveStream", &attrLiveStream)) {
+ ssize_t semicolonPos = attrLiveStream.find(";", 2);
+
+ const char* liveStreamValue;
+ if (semicolonPos < 0) {
+ liveStreamValue = attrLiveStream.c_str();
+ } else {
+ AString valString;
+ valString.setTo(attrLiveStream,
+ semicolonPos + 1,
+ attrLiveStream.size() - semicolonPos - 1);
+ liveStreamValue = valString.c_str();
+ }
+
+ uint32_t value = strtoul(liveStreamValue, NULL, 10);
+ if (value == 1) {
+ ALOGV("found live stream");
+ return true;
+ }
+ } else {
+ // It is a live stream if no duration is returned
+ int64_t durationUs;
+ if (!desc->getDurationUs(&durationUs)) {
+ ALOGV("No duration found, assume live stream");
+ return true;
+ }
+ }
+
+ return false;
+ }
+
virtual void onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case 'conn':
}
}
+ mSeekable = !isLiveStream(mSessionDesc);
+
if (!mBaseURL.startsWith("rtsp://")) {
// Some misbehaving servers specify a relative
// URL in one of the locations above, combine
} else {
mBaseURL = mSessionURL;
+ mSeekable = !isLiveStream(mSessionDesc);
+
if (mSessionDesc->countTracks() < 2) {
// There's no actual tracks in this session.
// The first "track" is merely session meta
mNumAccessUnitsReceived = 0;
mReceivedFirstRTCPPacket = false;
mReceivedFirstRTPPacket = false;
- mSeekable = false;
+ mSeekable = true;
sp<AMessage> reply = new AMessage('tear', id());
}
void parsePlayResponse(const sp<ARTSPResponse> &response) {
- mSeekable = false;
if (mTracks.size() == 0) {
ALOGV("parsePlayResponse: late packets ignored.");
return;
++n;
}
-
- mSeekable = true;
}
sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale) {