Merge "Add AAC extractor"
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 18fd90e..f7f2235 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -48,6 +48,7 @@
     kKeyBitRate           = 'brte',  // int32_t (bps)
     kKeyESDS              = 'esds',  // raw data
     kKeyAVCC              = 'avcc',  // raw data
+    kKeyD263              = 'd263',  // raw data
     kKeyVorbisInfo        = 'vinf',  // raw data
     kKeyVorbisBooks       = 'vboo',  // raw data
     kKeyWantsNALFragments = 'NALf',
@@ -118,6 +119,7 @@
 enum {
     kTypeESDS        = 'esds',
     kTypeAVCC        = 'avcc',
+    kTypeD263        = 'd263',
 };
 
 class MetaData : public RefBase {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e368848..ec5e7a8 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -376,14 +376,11 @@
 }
 
 void AwesomePlayer::reset() {
-    LOGI("reset");
-
     Mutex::Autolock autoLock(mLock);
     reset_l();
 }
 
 void AwesomePlayer::reset_l() {
-    LOGI("reset_l");
     mDisplayWidth = 0;
     mDisplayHeight = 0;
 
@@ -399,6 +396,9 @@
         if (mConnectingDataSource != NULL) {
             LOGI("interrupting the connection process");
             mConnectingDataSource->disconnect();
+        } else if (mConnectingRTSPController != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingRTSPController->disconnect();
         }
 
         if (mFlags & PREPARING_CONNECTED) {
@@ -408,10 +408,6 @@
         }
     }
 
-    if (mFlags & PREPARING) {
-        LOGI("waiting until preparation is completes.");
-    }
-
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -435,8 +431,6 @@
     }
     mAudioSource.clear();
 
-    LOGI("audio source cleared");
-
     mTimeSource = NULL;
 
     delete mAudioPlayer;
@@ -473,8 +467,6 @@
         IPCThreadState::self()->flushCommands();
     }
 
-    LOGI("video source cleared");
-
     mDurationUs = -1;
     mFlags = 0;
     mExtractorFlags = 0;
@@ -491,8 +483,6 @@
     mFileSource.clear();
 
     mBitrate = -1;
-
-    LOGI("reset_l completed");
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -1633,7 +1623,13 @@
             mLooper->start();
         }
         mRTSPController = new ARTSPController(mLooper);
+        mConnectingRTSPController = mRTSPController;
+
+        mLock.unlock();
         status_t err = mRTSPController->connect(mUri.string());
+        mLock.lock();
+
+        mConnectingRTSPController.clear();
 
         LOGI("ARTSPController::connect returned %d", err);
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 108a1d1..a973d7e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1164,6 +1164,30 @@
             break;
         }
 
+        case FOURCC('d', '2', '6', '3'):
+        {
+            // d263 contains fixed 7 bytes:
+            // vendor - 4 bytes
+            // version - 1 byte
+            // level - 1 byte
+            // profile - 1 byte
+            char buffer[7];
+            if (chunk_data_size != (off64_t) sizeof(buffer)) {
+                LOGE("Incorrect D263 box size %lld", chunk_data_size);
+                return ERROR_MALFORMED;
+            }
+
+            if (mDataSource->readAt(
+                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
+                return ERROR_IO;
+            }
+
+            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
+
+            *offset += chunk_size;
+            break;
+        }
+
         case FOURCC('m', 'e', 't', 'a'):
         {
             uint8_t buffer[4];
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fccd68c..5d502e7 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3289,7 +3289,7 @@
 }
 
 status_t OMXCodec::stop() {
-    CODEC_LOGI("stop mState=%d", mState);
+    CODEC_LOGV("stop mState=%d", mState);
 
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 797e5ca..98b8c05 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -205,6 +205,7 @@
 
     sp<ALooper> mLooper;
     sp<ARTSPController> mRTSPController;
+    sp<ARTSPController> mConnectingRTSPController;
 
     sp<LiveSession> mLiveSession;
 
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 @@
       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 f0b858d..679dcab 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -637,7 +637,7 @@
 
         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 601f569..47de4e0 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -123,7 +123,7 @@
         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,
@@ -340,6 +340,8 @@
 }
 
 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 893a387..84c666f 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -67,7 +67,7 @@
     } 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/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index a7563ff..1328d2e 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -69,7 +69,14 @@
 void ARTSPController::disconnect() {
     Mutex::Autolock autoLock(mLock);
 
-    if (mState != CONNECTED) {
+    if (mState == CONNECTING) {
+        mState = DISCONNECTED;
+        mConnectionResult = ERROR_IO;
+        mCondition.broadcast();
+
+        mHandler.clear();
+        return;
+    } else if (mState != CONNECTED) {
         return;
     }
 
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 @@
             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 ba7c1b2..d15d9c5 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -38,6 +38,7 @@
 
 #include <arpa/inet.h>
 #include <sys/socket.h>
+#include <netdb.h>
 
 // If no access units are received within 5 secs, assume that the rtp
 // stream has ended and signal end of stream.
@@ -121,9 +122,10 @@
         // want to transmit user/pass in cleartext.
         AString host, path, user, pass;
         unsigned port;
-        if (ARTSPConnection::ParseURL(
-                    mSessionURL.c_str(), &host, &port, &path, &user, &pass)
-                && user.size() > 0) {
+        CHECK(ARTSPConnection::ParseURL(
+                    mSessionURL.c_str(), &host, &port, &path, &user, &pass));
+
+        if (user.size() > 0) {
             mSessionURL.clear();
             mSessionURL.append("rtsp://");
             mSessionURL.append(host);
@@ -133,6 +135,8 @@
 
             LOGI("rewritten session url: '%s'", mSessionURL.c_str());
         }
+
+        mSessionHost = host;
     }
 
     void connect(const sp<AMessage> &doneMsg) {
@@ -248,34 +252,64 @@
     // 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) {
+        struct sockaddr_in addr;
+        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+        addr.sin_family = AF_INET;
+
         AString source;
         AString server_port;
         if (!GetAttribute(transport.c_str(),
                           "source",
-                          &source)
-                || !GetAttribute(transport.c_str(),
+                          &source)) {
+            LOGW("Missing 'source' field in Transport response. Using "
+                 "RTSP endpoint address.");
+
+            struct hostent *ent = gethostbyname(mSessionHost.c_str());
+            if (ent == NULL) {
+                LOGE("Failed to look up address of session host '%s'",
+                     mSessionHost.c_str());
+
+                return false;
+            }
+
+            addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+        } else {
+            addr.sin_addr.s_addr = inet_addr(source.c_str());
+        }
+
+        if (!GetAttribute(transport.c_str(),
                                  "server_port",
                                  &server_port)) {
-            return;
+            LOGI("Missing 'server_port' field in Transport response.");
+            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;
         }
 
-        struct sockaddr_in addr;
-        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
-        addr.sin_family = AF_INET;
-        addr.sin_addr.s_addr = inet_addr(source.c_str());
+        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.");
+        }
 
         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.
@@ -289,16 +323,26 @@
         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) {
@@ -381,6 +425,7 @@
                                 response->mContent->size());
 
                         if (!mSessionDesc->isValid()) {
+                            LOGE("Failed to parse session description.");
                             result = ERROR_MALFORMED;
                         } else {
                             ssize_t i = response->mHeaders.indexOfKey("content-base");
@@ -395,6 +440,25 @@
                                 }
                             }
 
+                            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);
                         }
@@ -455,9 +519,12 @@
                         if (!track->mUsingInterleavedTCP) {
                             AString transport = response->mHeaders.valueAt(i);
 
-                            pokeAHole(track->mRTPSocket,
-                                      track->mRTCPSocket,
-                                      transport);
+                            // We are going to continue even if we were
+                            // unable to poke a hole into the firewall...
+                            pokeAHole(
+                                    track->mRTPSocket,
+                                    track->mRTCPSocket,
+                                    transport);
                         }
 
                         mRTPConn->addStream(
@@ -853,17 +920,16 @@
             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.");
 
                         mTryFakeRTCP = true;
 
                         mReceivedFirstRTCPPacket = true;
-                    } else {
+
+                        fakeTimestamps();
+                    } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
                         LOGW("Never received any data, switching transports.");
 
                         mTryTCPInterleaving = true;
@@ -871,6 +937,9 @@
                         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;
@@ -1016,6 +1085,7 @@
     sp<ASessionDescription> mSessionDesc;
     AString mOriginalSessionURL;  // This one still has user:pass@
     AString mSessionURL;
+    AString mSessionHost;
     AString mBaseURL;
     AString mSessionID;
     bool mSetupTracksSuccessful;
@@ -1158,6 +1228,12 @@
         return true;
     }
 
+    void fakeTimestamps() {
+        for (size_t i = 0; i < mTracks.size(); ++i) {
+            onTimeUpdate(i, 0, 0ll);
+        }
+    }
+
     void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
         LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx",
              trackIndex, rtpTime, ntpTime);
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index fb1b073..4ea8849 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -38,6 +38,7 @@
 
 namespace android {
 
+#if 0
 static bool isMtpDevice(uint16_t vendor, uint16_t product) {
     // Sandisk Sansa Fuze
     if (vendor == 0x0781 && product == 0x74c2)
@@ -47,6 +48,7 @@
         return true;
     return false;
 }
+#endif
 
 MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
     struct usb_device *device = usb_device_new(deviceName, fd);
@@ -91,7 +93,9 @@
                 LOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
                 free(manufacturerName);
                 free(productName);
-            } else {
+            }
+#if 0
+             else {
                 // look for special cased devices based on vendor/product ID
                 // we are doing this mainly for testing purposes
                 uint16_t vendor = usb_device_get_vendor_id(device);
@@ -119,7 +123,7 @@
                     printf("no MTP string\n");
                 }
             }
-
+#endif
             // if we got here, then we have a likely MTP or PTP device
 
             // interface should be followed by three endpoints
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index d3f2cb4..baf99e5 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -153,12 +153,13 @@
 
 #ifdef MTP_HOST
 int MtpPacket::transfer(struct usb_request* request) {
-    if (usb_request_queue(request)) {
-        LOGE("usb_endpoint_queue failed, errno: %d", errno);
-        return -1;
-    }
-    request = usb_request_wait(request->dev);
-    return (request ? request->actual_length : -1);
+    int result = usb_device_bulk_transfer(request->dev,
+                            request->endpoint,
+                            request->buffer,
+                            request->buffer_length,
+                            0);
+    request->actual_length = result;
+    return result;
 }
 #endif
 
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 6a82a59..3082d45 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -610,7 +610,7 @@
         // store time at which the stream was stopped - see isStreamActive()
         outputDesc->mStopTime[stream] = systemTime();
 
-        setOutputDevice(output, getNewDevice(output));
+        setOutputDevice(output, getNewDevice(output), false, outputDesc->mLatency*2);
 
 #ifdef WITH_A2DP
         if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&