VT: Add auto downgrade function

Some network requires force-downgrading to audio call when video packet status is bad.

1. ARTPSource reports bitrate value for every unit time.
   If low bitrate duration stays long, ARTPConnection triggers auto downgrading message.
   The way of passing message is same as TSFB & PSFB.

2. Add auto downgrade callback message when connection lost.

Merged-in: I04e3f4e1955852c61540f35c763a40be3e7b639b
Change-Id: I04e3f4e1955852c61540f35c763a40be3e7b639b
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 4d33b4e..44423f8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2848,6 +2848,7 @@
     switch (payloadType) {
         case NuPlayer::RTPSource::RTCP_TSFB:   // RTCP TSFB
         case NuPlayer::RTPSource::RTCP_PSFB:   // RTCP PSFB
+        case NuPlayer::RTPSource::RTP_AUTODOWN:
         {
             int32_t feedbackType, id;
             CHECK(msg->findInt32("feedback-type", &feedbackType));
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/RTPSource.h
index d7084d4..efbf6d2 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.h
@@ -57,6 +57,7 @@
         RTCP_TSFB = 205,
         RTCP_PSFB = 206,
         RTP_CVO = 300,
+        RTP_AUTODOWN = 400,
     };
 
     virtual status_t getBufferingSettings(
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 90d1a8f..07ece6a 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -416,6 +416,12 @@
 
             if (err == -ECONNRESET) {
                 // socket failure, this stream is dead, Jim.
+                sp<AMessage> notify = it->mNotifyMsg->dup();
+                notify->setInt32("IMS-Rx-notice", 1);
+                notify->setInt32("payload-type", 400);
+                notify->setInt32("feedback-type", 1);
+                notify->setInt32("sender", it->mSources.valueAt(0)->getSelfID());
+                notify->post();
 
                 ALOGW("failed to receive RTP/RTCP datagram.");
                 it = mStreams.erase(it);
@@ -1016,8 +1022,17 @@
 
             for (size_t i = 0; i < s->mSources.size(); ++i) {
                 sp<ARTPSource> source = s->mSources.valueAt(i);
+                source->setBitrateData(bitrate, nowUs);
                 source->setTargetBitrate();
                 source->addTMMBR(buffer);
+                if (source->isNeedToDowngrade()) {
+                    sp<AMessage> notify = s->mNotifyMsg->dup();
+                    notify->setInt32("IMS-Rx-notice", 1);
+                    notify->setInt32("payload-type", 400);
+                    notify->setInt32("feedback-type", 1);
+                    notify->setInt32("sender", source->getSelfID());
+                    notify->post();
+                }
             }
             if (buffer->size() > 0) {
                 ALOGV("Sending TMMBR...");
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 33b1772..ee4b7c2 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -379,6 +379,10 @@
     mQualManager.setMinMaxBitrate(min, max);
 }
 
+void ARTPSource::setBitrateData(int32_t bitrate, int64_t time) {
+    mQualManager.setBitrateData(bitrate, time);
+}
+
 void ARTPSource::setTargetBitrate() {
     uint8_t fraction = 0;
 
@@ -403,6 +407,10 @@
     return (intervalReceived > 0) ? true : false;
 }
 
+bool ARTPSource::isNeedToDowngrade() {
+    return mQualManager.isNeedToDowngrade();
+}
+
 void ARTPSource::noticeAbandonBuffer(int cnt) {
     mNumBuffersReceived -= cnt;
 }
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 5b1ae73..652e753 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -50,9 +50,11 @@
     uint32_t getSelfID();
     void setSelfID(const uint32_t selfID);
     void setMinMaxBitrate(int32_t min, int32_t max);
+    void setBitrateData(int32_t bitrate, int64_t time);
     void setTargetBitrate();
 
     bool isNeedToReport();
+    bool isNeedToDowngrade();
 
     void noticeAbandonBuffer(int cnt=1);
 
diff --git a/media/libstagefright/rtsp/QualManager.h b/media/libstagefright/rtsp/QualManager.h
index f6671ba..ee2fb40 100644
--- a/media/libstagefright/rtsp/QualManager.h
+++ b/media/libstagefright/rtsp/QualManager.h
@@ -24,6 +24,7 @@
 public:
     QualManager() : mMinBitrate(-1), mMaxBitrate(-1), mTargetBitrate(512000),
                     mLastTargetBitrate(-1), mLastSetBitrateTime(0),
+                    mLowBitrateStartTime(0), mAutoDowngrade(false),
                     mIsNewTargetBitrate(false){};
 
     int32_t getTargetBitrate() {
@@ -36,6 +37,10 @@
         }
     }
 
+    bool isNeedToDowngrade() {
+        return mAutoDowngrade;
+    }
+
     void setTargetBitrate(uint8_t fraction, int64_t nowUs) {
         if (fraction <= (256 * 2 /100)) {           // loss less than 2%
             mTargetBitrate += mBitrateStep;
@@ -46,6 +51,9 @@
         if (mTargetBitrate > mMaxBitrate) {
             mTargetBitrate = mMaxBitrate;
         } else if (mTargetBitrate < mMinBitrate) {
+            if (mLowBitrateStartTime != 0) {
+                mLowBitrateStartTime = nowUs;
+            }
             mTargetBitrate = mMinBitrate;
         }
 
@@ -60,6 +68,25 @@
         mMaxBitrate = max;
         mBitrateStep = (max - min) / 8;
     };
+
+    void setBitrateData(int32_t bitrate, int64_t now) {
+        int64_t lowBitrateDuration = 0;
+        if (bitrate < mMinBitrate)
+        {
+            if (mLowBitrateStartTime == 0) {
+                mLowBitrateStartTime = now;
+            } else {
+                lowBitrateDuration = now - mLowBitrateStartTime;
+            }
+        } else {
+            mLowBitrateStartTime = 0;
+        }
+        if (lowBitrateDuration > mPatientTime) {
+            mAutoDowngrade = true;
+        } else {
+            mAutoDowngrade = false;
+        }
+    }
 private:
     int32_t mMinBitrate;
     int32_t mMaxBitrate;
@@ -70,6 +97,10 @@
 
     int64_t mLastSetBitrateTime;
 
+    const int64_t mPatientTime = 10000000ll;    // 10 sec
+    int64_t mLowBitrateStartTime;
+
+    bool mAutoDowngrade;
     bool mIsNewTargetBitrate;
 };