Various changes to improve rtsp networking, reduce packet loss and adapt to ALooper API changes.

Change-Id: I110e19d5ce33e597add3ffbd3e3ff3815862396d
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index f74240f..4a1d27b 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -25,6 +25,8 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include "include/ARTSPController.h"
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/JPEGSource.h>
@@ -365,6 +367,9 @@
     gPlaybackAudio = false;
     gWriteMP4 = false;
 
+    sp<ALooper> looper;
+    sp<ARTSPController> rtspController;
+
     int res;
     while ((res = getopt(argc, argv, "han:lm:b:ptsow:k")) >= 0) {
         switch (res) {
@@ -576,7 +581,8 @@
 
         sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
 
-        if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) {
+        if ((strncasecmp(filename, "sine:", 5)
+                && strncasecmp(filename, "rtsp://", 7)) && dataSource == NULL) {
             fprintf(stderr, "Unable to create data source.\n");
             return 1;
         }
@@ -601,10 +607,28 @@
             }
             mediaSource = new SineSource(sampleRate, 1);
         } else {
-            sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
-            if (extractor == NULL) {
-                fprintf(stderr, "could not create extractor.\n");
-                return -1;
+            sp<MediaExtractor> extractor;
+
+            if (!strncasecmp("rtsp://", filename, 7)) {
+                if (looper == NULL) {
+                    looper = new ALooper;
+                    looper->start();
+                }
+
+                rtspController = new ARTSPController(looper);
+                status_t err = rtspController->connect(filename);
+                if (err != OK) {
+                    fprintf(stderr, "could not connect to rtsp server.\n");
+                    return -1;
+                }
+
+                extractor = rtspController.get();
+            } else {
+                extractor = MediaExtractor::Create(dataSource);
+                if (extractor == NULL) {
+                    fprintf(stderr, "could not create extractor.\n");
+                    return -1;
+                }
             }
 
             size_t numTracks = extractor->countTracks();
@@ -654,6 +678,13 @@
         } else {
             playSource(&client, mediaSource);
         }
+
+        if (rtspController != NULL) {
+            rtspController->disconnect();
+            rtspController.clear();
+
+            sleep(3);
+        }
     }
 
     client.disconnect();
diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h
index 194f1fc..153ead9 100644
--- a/include/media/stagefright/foundation/ALooper.h
+++ b/include/media/stagefright/foundation/ALooper.h
@@ -41,7 +41,9 @@
 
     status_t start(
             bool runOnCallingThread = false,
-            bool canCallJava = false);
+            bool canCallJava = false,
+            int32_t priority = PRIORITY_DEFAULT
+            );
 
     status_t stop();
 
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index cd4f349..77afb01 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -73,7 +73,8 @@
     gLooperRoster.unregisterHandler(handlerID);
 }
 
-status_t ALooper::start(bool runOnCallingThread, bool canCallJava) {
+status_t ALooper::start(
+        bool runOnCallingThread, bool canCallJava, int32_t priority) {
     if (runOnCallingThread) {
         {
             Mutex::Autolock autoLock(mLock);
@@ -99,7 +100,7 @@
 
     mThread = new LooperThread(this, canCallJava);
 
-    status_t err = mThread->run("ALooper");
+    status_t err = mThread->run("ALooper", priority);
     if (err != OK) {
         mThread.clear();
     }
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index 0549d84..7e55106 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -144,6 +144,11 @@
 
     accessUnit->meta()->setInt64("ntp-time", ntpTime);
 
+#if 0
+    printf(mAccessUnitDamaged ? "X" : ".");
+    fflush(stdout);
+#endif
+
     if (mAccessUnitDamaged) {
         accessUnit->meta()->setInt32("damaged", true);
     }
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index 7b87d429..195323e 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -38,6 +38,8 @@
     }
 
     mHandler = new MyHandler(url, mLooper);
+    mHandler->connect();
+
     sleep(10);
 
     return OK;
@@ -48,6 +50,7 @@
         return;
     }
 
+    mHandler->disconnect();
     mHandler.clear();
 }
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 74bb798..044393f 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -34,19 +34,33 @@
 struct MyHandler : public AHandler {
     MyHandler(const char *url, const sp<ALooper> &looper)
         : mLooper(looper),
+          mNetLooper(new ALooper),
           mConn(new ARTSPConnection),
           mRTPConn(new ARTPConnection),
           mSessionURL(url),
           mSetupTracksSuccessful(false),
           mFirstAccessUnit(true),
           mFirstAccessUnitNTP(-1) {
+
+        mNetLooper->start(false /* runOnCallingThread */,
+                          false /* canCallJava */,
+                          PRIORITY_HIGHEST);
+    }
+
+    void connect() {
         mLooper->registerHandler(this);
         mLooper->registerHandler(mConn);
-        mLooper->registerHandler(mRTPConn);
+        (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn);
         sp<AMessage> reply = new AMessage('conn', id());
+
         mConn->connect(mSessionURL.c_str(), reply);
     }
 
+    void disconnect() {
+        sp<AMessage> reply = new AMessage('disc', id());
+        mConn->disconnect(reply);
+    }
+
     virtual void onMessageReceived(const sp<AMessage> &msg) {
         switch (msg->what()) {
             case 'conn':
@@ -290,7 +304,6 @@
 
             case 'quit':
             {
-                mLooper->stop();
                 break;
             }
 
@@ -320,8 +333,17 @@
 
                 accessUnit->meta()->setInt64("ntp-time", ntpTime);
 
-                TrackInfo *track = &mTracks.editItemAt(trackIndex);
-                track->mPacketSource->queueAccessUnit(accessUnit);
+#if 0
+                int32_t damaged;
+                if (accessUnit->meta()->findInt32("damaged", &damaged)
+                        && damaged != 0) {
+                    LOG(INFO) << "ignoring damaged AU";
+                } else
+#endif
+                {
+                    TrackInfo *track = &mTracks.editItemAt(trackIndex);
+                    track->mPacketSource->queueAccessUnit(accessUnit);
+                }
                 break;
             }
 
@@ -344,6 +366,7 @@
 
 private:
     sp<ALooper> mLooper;
+    sp<ALooper> mNetLooper;
     sp<ARTSPConnection> mConn;
     sp<ARTPConnection> mRTPConn;
     sp<ASessionDescription> mSessionDesc;