summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-02-15 11:49:03 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2011-02-15 11:49:03 -0800
commite0c9f2757b0ebd291fec89ebb520878aacd3f7dc (patch)
treee8969b38e8ae79c9dbf7aec20889412a7c53086d
parentb269346ca333a975d37ac50fec0c7b6a4c39a3de (diff)
parentd1ba051a465518fa4325c364ed77025fc1a2a794 (diff)
downloadframeworks_base-e0c9f2757b0ebd291fec89ebb520878aacd3f7dc.zip
frameworks_base-e0c9f2757b0ebd291fec89ebb520878aacd3f7dc.tar.gz
frameworks_base-e0c9f2757b0ebd291fec89ebb520878aacd3f7dc.tar.bz2
am d1ba051a: DO NOT MERGE: Work around several issues with non-compliant RTSP servers.
* commit 'd1ba051a465518fa4325c364ed77025fc1a2a794': DO NOT MERGE: Work around several issues with non-compliant RTSP servers.
-rw-r--r--media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp2
-rw-r--r--media/libstagefright/rtsp/APacketSource.cpp2
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp4
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp2
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp5
-rw-r--r--media/libstagefright/rtsp/MyHandler.h91
6 files changed, 81 insertions, 25 deletions
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 13988cd..9f6bd29 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -104,7 +104,7 @@ AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
mNextExpectedSeqNoValid(false),
mNextExpectedSeqNo(0),
mAccessUnitDamaged(false) {
- mIsGeneric = desc.startsWith("mpeg4-generic/");
+ mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
if (mIsGeneric) {
AString value;
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 10cc88b..7f09248 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -627,7 +627,7 @@ APacketSource::APacketSource(
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
- } else if (!strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
AString val;
if (!GetAttribute(params.c_str(), "mode", &val)
|| (strcasecmp(val.c_str(), "AAC-lbr")
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 5a1ea5c..72943ff 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -123,7 +123,7 @@ void ARTPConnection::MakePortPair(
struct sockaddr_in addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (bind(*rtpSocket,
@@ -346,6 +346,8 @@ void ARTPConnection::onPollStreams() {
}
status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
+ LOGV("receiving %s", receiveRTP ? "RTP" : "RTCP");
+
CHECK(!s->mIsInjected);
sp<ABuffer> buffer = new ABuffer(65536);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 5aae4e7..87b5a7e 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -67,7 +67,7 @@ ARTPSource::ARTPSource(
} else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
mAssembler = new AAMRAssembler(notify, true /* isWide */, params);
} else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)
- || !strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ || !strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params);
mIssueFIRRequests = true;
} else {
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 3e710dc..f03f7a2 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -71,6 +71,11 @@ bool ASessionDescription::parse(const void *data, size_t size) {
line.setTo(desc, i, eolPos - i);
}
+ if (line.empty()) {
+ i = eolPos + 1;
+ continue;
+ }
+
if (line.size() < 2 || line.c_str()[1] != '=') {
return false;
}
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 306a9c1..9c0d2c2 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -246,7 +246,7 @@ struct MyHandler : public AHandler {
// In case we're behind NAT, fire off two UDP packets to the remote
// rtp/rtcp ports to poke a hole into the firewall for future incoming
// packets. We're going to send an RR/SDES RTCP packet to both of them.
- void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+ bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
AString source;
AString server_port;
if (!GetAttribute(transport.c_str(),
@@ -255,16 +255,25 @@ struct MyHandler : public AHandler {
|| !GetAttribute(transport.c_str(),
"server_port",
&server_port)) {
- return;
+ return false;
}
int rtpPort, rtcpPort;
if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
|| rtpPort <= 0 || rtpPort > 65535
|| rtcpPort <=0 || rtcpPort > 65535
- || rtcpPort != rtpPort + 1
- || (rtpPort & 1) != 0) {
- return;
+ || rtcpPort != rtpPort + 1) {
+ LOGE("Server picked invalid RTP/RTCP port pair %s,"
+ " RTP port must be even, RTCP port must be one higher.",
+ server_port.c_str());
+
+ return false;
+ }
+
+ if (rtpPort & 1) {
+ LOGW("Server picked an odd RTP port, it should've picked an "
+ "even one, we'll let it pass for now, but this may break "
+ "in the future.");
}
struct sockaddr_in addr;
@@ -273,7 +282,12 @@ struct MyHandler : public AHandler {
addr.sin_addr.s_addr = inet_addr(source.c_str());
if (addr.sin_addr.s_addr == INADDR_NONE) {
- return;
+ return true;
+ }
+
+ if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
+ // No firewalls to traverse on the loopback interface.
+ return true;
}
// Make up an RR/SDES RTCP packet.
@@ -287,16 +301,26 @@ struct MyHandler : public AHandler {
ssize_t n = sendto(
rtpSocket, buf->data(), buf->size(), 0,
(const sockaddr *)&addr, sizeof(addr));
- CHECK_EQ(n, (ssize_t)buf->size());
+
+ if (n < (ssize_t)buf->size()) {
+ LOGE("failed to poke a hole for RTP packets");
+ return false;
+ }
addr.sin_port = htons(rtcpPort);
n = sendto(
rtcpSocket, buf->data(), buf->size(), 0,
(const sockaddr *)&addr, sizeof(addr));
- CHECK_EQ(n, (ssize_t)buf->size());
+
+ if (n < (ssize_t)buf->size()) {
+ LOGE("failed to poke a hole for RTCP packets");
+ return false;
+ }
LOGV("successfully poked holes.");
+
+ return true;
}
virtual void onMessageReceived(const sp<AMessage> &msg) {
@@ -379,6 +403,7 @@ struct MyHandler : public AHandler {
response->mContent->size());
if (!mSessionDesc->isValid()) {
+ LOGE("Failed to parse session description.");
result = ERROR_MALFORMED;
} else {
ssize_t i = response->mHeaders.indexOfKey("content-base");
@@ -393,6 +418,25 @@ struct MyHandler : public AHandler {
}
}
+ if (!mBaseURL.startsWith("rtsp://")) {
+ // Some misbehaving servers specify a relative
+ // URL in one of the locations above, combine
+ // it with the absolute session URL to get
+ // something usable...
+
+ LOGW("Server specified a non-absolute base URL"
+ ", combining it with the session URL to "
+ "get something usable...");
+
+ AString tmp;
+ CHECK(MakeURL(
+ mSessionURL.c_str(),
+ mBaseURL.c_str(),
+ &tmp));
+
+ mBaseURL = tmp;
+ }
+
CHECK_GT(mSessionDesc->countTracks(), 1u);
setupTrack(1);
}
@@ -453,17 +497,22 @@ struct MyHandler : public AHandler {
if (!track->mUsingInterleavedTCP) {
AString transport = response->mHeaders.valueAt(i);
- pokeAHole(track->mRTPSocket,
- track->mRTCPSocket,
- transport);
+ if (!pokeAHole(
+ track->mRTPSocket,
+ track->mRTCPSocket,
+ transport)) {
+ result = UNKNOWN_ERROR;
+ }
}
- mRTPConn->addStream(
- track->mRTPSocket, track->mRTCPSocket,
- mSessionDesc, index,
- notify, track->mUsingInterleavedTCP);
+ if (result == OK) {
+ mRTPConn->addStream(
+ track->mRTPSocket, track->mRTCPSocket,
+ mSessionDesc, index,
+ notify, track->mUsingInterleavedTCP);
- mSetupTracksSuccessful = true;
+ mSetupTracksSuccessful = true;
+ }
}
}
@@ -865,10 +914,7 @@ struct MyHandler : public AHandler {
case 'tiou':
{
if (!mReceivedFirstRTCPPacket) {
- if (mTryFakeRTCP) {
- LOGW("Never received any data, disconnecting.");
- (new AMessage('abor', id()))->post();
- } else if (mTryTCPInterleaving && mReceivedFirstRTPPacket) {
+ if (mReceivedFirstRTPPacket && !mTryFakeRTCP) {
LOGW("We received RTP packets but no RTCP packets, "
"using fake timestamps.");
@@ -876,7 +922,7 @@ struct MyHandler : public AHandler {
mReceivedFirstRTCPPacket = true;
mRTPConn->fakeTimestamps();
- } else {
+ } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
LOGW("Never received any data, switching transports.");
mTryTCPInterleaving = true;
@@ -884,6 +930,9 @@ struct MyHandler : public AHandler {
sp<AMessage> msg = new AMessage('abor', id());
msg->setInt32("reconnect", true);
msg->post();
+ } else {
+ LOGW("Never received any data, disconnecting.");
+ (new AMessage('abor', id()))->post();
}
}
break;