Attempt to recover from network stalls by dropping frames on the source side.

Change-Id: I5f9eb4f5acb624a9e5bc0087801fb5a4a9ade35c
diff --git a/media/libstagefright/wifi-display/ANetworkSession.cpp b/media/libstagefright/wifi-display/ANetworkSession.cpp
index 465f4c4..23bb04e 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.cpp
+++ b/media/libstagefright/wifi-display/ANetworkSession.cpp
@@ -104,6 +104,8 @@
 
     AString mInBuffer;
 
+    int64_t mLastStallReportUs;
+
     void notifyError(bool send, status_t err, const char *detail);
     void notify(NotificationReason reason);
 
@@ -137,7 +139,8 @@
       mSocket(s),
       mNotify(notify),
       mSawReceiveFailure(false),
-      mSawSendFailure(false) {
+      mSawSendFailure(false),
+      mLastStallReportUs(-1ll) {
     if (mState == CONNECTED) {
         struct sockaddr_in localAddr;
         socklen_t localAddrLen = sizeof(localAddr);
@@ -508,11 +511,26 @@
         mSawSendFailure = true;
     }
 
-#if 0
+#if 1
     int numBytesQueued;
     int res = ioctl(mSocket, SIOCOUTQ, &numBytesQueued);
-    if (res == 0 && numBytesQueued > 102400) {
-        ALOGI("numBytesQueued = %d", numBytesQueued);
+    if (res == 0 && numBytesQueued > 50 * 1024) {
+        if (numBytesQueued > 409600) {
+            ALOGW("!!! numBytesQueued = %d", numBytesQueued);
+        }
+
+        int64_t nowUs = ALooper::GetNowUs();
+
+        if (mLastStallReportUs < 0ll
+                || nowUs > mLastStallReportUs + 500000ll) {
+            sp<AMessage> msg = mNotify->dup();
+            msg->setInt32("sessionID", mSessionID);
+            msg->setInt32("reason", kWhatNetworkStall);
+            msg->setSize("numBytesQueued", numBytesQueued);
+            msg->post();
+
+            mLastStallReportUs = nowUs;
+        }
     }
 #endif
 
diff --git a/media/libstagefright/wifi-display/ANetworkSession.h b/media/libstagefright/wifi-display/ANetworkSession.h
index c1acdcc..0d7cbd6 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.h
+++ b/media/libstagefright/wifi-display/ANetworkSession.h
@@ -83,6 +83,7 @@
         kWhatData,
         kWhatDatagram,
         kWhatBinaryData,
+        kWhatNetworkStall,
     };
 
 protected:
diff --git a/media/libstagefright/wifi-display/MediaSender.cpp b/media/libstagefright/wifi-display/MediaSender.cpp
index 105c642..e1e957a 100644
--- a/media/libstagefright/wifi-display/MediaSender.cpp
+++ b/media/libstagefright/wifi-display/MediaSender.cpp
@@ -325,6 +325,15 @@
             break;
         }
 
+        case kWhatNetworkStall:
+        {
+            size_t numBytesQueued;
+            CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
+
+            notifyNetworkStall(numBytesQueued);
+            break;
+        }
+
         default:
             TRESPASS();
     }
@@ -344,6 +353,13 @@
     notify->post();
 }
 
+void MediaSender::notifyNetworkStall(size_t numBytesQueued) {
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatNetworkStall);
+    notify->setSize("numBytesQueued", numBytesQueued);
+    notify->post();
+}
+
 status_t MediaSender::packetizeAccessUnit(
         size_t trackIndex,
         sp<ABuffer> accessUnit,
diff --git a/media/libstagefright/wifi-display/MediaSender.h b/media/libstagefright/wifi-display/MediaSender.h
index 9a50f9a..447abf7 100644
--- a/media/libstagefright/wifi-display/MediaSender.h
+++ b/media/libstagefright/wifi-display/MediaSender.h
@@ -42,6 +42,7 @@
     enum {
         kWhatInitDone,
         kWhatError,
+        kWhatNetworkStall,
     };
 
     MediaSender(
@@ -113,6 +114,7 @@
 
     void notifyInitDone(status_t err);
     void notifyError(status_t err);
+    void notifyNetworkStall(size_t numBytesQueued);
 
     status_t packetizeAccessUnit(
             size_t trackIndex,
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
index b60853d..8cd712d 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
@@ -530,6 +530,18 @@
             }
             break;
         }
+
+        case ANetworkSession::kWhatNetworkStall:
+        {
+            size_t numBytesQueued;
+            CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
+
+            notifyNetworkStall(numBytesQueued);
+            break;
+        }
+
+        default:
+            TRESPASS();
     }
 }
 
@@ -699,5 +711,12 @@
     notify->post();
 }
 
+void RTPSender::notifyNetworkStall(size_t numBytesQueued) {
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatNetworkStall);
+    notify->setSize("numBytesQueued", numBytesQueued);
+    notify->post();
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.h b/media/libstagefright/wifi-display/rtp/RTPSender.h
index 2b683a4..83c6223 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.h
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.h
@@ -36,6 +36,7 @@
     enum {
         kWhatInitDone,
         kWhatError,
+        kWhatNetworkStall,
     };
     RTPSender(
             const sp<ANetworkSession> &netSession,
@@ -103,6 +104,7 @@
 
     void notifyInitDone(status_t err);
     void notifyError(status_t err);
+    void notifyNetworkStall(size_t numBytesQueued);
 
     DISALLOW_EVIL_CONSTRUCTORS(RTPSender);
 };
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
index 0d2e347..d635c3a 100644
--- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
+++ b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
@@ -319,7 +319,7 @@
 
             CHECK(mTimeOffsetValid);
 
-            int64_t latencyUs = 300000ll;  // 300ms by default
+            int64_t latencyUs = 200000ll;  // 200ms by default
 
             char val[PROPERTY_VALUE_MAX];
             if (property_get("media.wfd-sink.latency", val, NULL)) {
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 2861aa9..bb8c387 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -55,6 +55,7 @@
       ,mInSilentMode(false)
 #endif
       ,mPrevVideoBitrate(-1)
+      ,mNumFramesToDrop(0)
     {
     AString mime;
     CHECK(mInputFormat->findString("mime", &mime));
@@ -327,6 +328,13 @@
                 sp<ABuffer> accessUnit;
                 CHECK(msg->findBuffer("accessUnit", &accessUnit));
 
+                if (mIsVideo && mNumFramesToDrop) {
+                    --mNumFramesToDrop;
+                    ALOGI("dropping frame.");
+                    ReleaseMediaBufferReference(accessUnit);
+                    break;
+                }
+
 #if 0
                 void *mbuf;
                 if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
@@ -422,6 +430,12 @@
             break;
         }
 
+        case kWhatDropAFrame:
+        {
+            ++mNumFramesToDrop;
+            break;
+        }
+
         default:
             TRESPASS();
     }
@@ -690,4 +704,8 @@
     (new AMessage(kWhatRequestIDRFrame, id()))->post();
 }
 
+void Converter::dropAFrame() {
+    (new AMessage(kWhatDropAFrame, id()))->post();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index 57802bd..a418f69 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -51,6 +51,8 @@
 
     void requestIDRFrame();
 
+    void dropAFrame();
+
     enum {
         kWhatAccessUnit,
         kWhatEOS,
@@ -63,6 +65,7 @@
         kWhatShutdown,
         kWhatMediaPullerNotify,
         kWhatEncoderActivity,
+        kWhatDropAFrame,
     };
 
     void shutdownAsync();
@@ -102,6 +105,8 @@
 
     int32_t mPrevVideoBitrate;
 
+    int32_t mNumFramesToDrop;
+
     status_t initEncoder();
     void releaseEncoder();
 
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index ea195b3..94cb2a4 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -515,6 +515,16 @@
                 }
             } else if (what == MediaSender::kWhatError) {
                 notifySessionDead();
+            } else if (what == MediaSender::kWhatNetworkStall) {
+                size_t numBytesQueued;
+                CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
+
+                if (mVideoTrackIndex >= 0) {
+                    const sp<Track> &videoTrack =
+                        mTracks.valueFor(mVideoTrackIndex);
+
+                    videoTrack->converter()->dropAFrame();
+                }
             } else {
                 TRESPASS();
             }
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index de66bde..c8798c6 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -272,6 +272,11 @@
                     break;
                 }
 
+                case ANetworkSession::kWhatNetworkStall:
+                {
+                    break;
+                }
+
                 default:
                     TRESPASS();
             }