resolved conflicts for merge of a8939e0d to master

Change-Id: I090479ed09618e1aa3685ca79e16202d9c82f523
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b45e5d3..fb7a871 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -24,11 +24,13 @@
 
 #include "include/ARTSPController.h"
 #include "include/AwesomePlayer.h"
+#include "include/DRMExtractor.h"
 #include "include/SoftwareRenderer.h"
 #include "include/NuCachedSource2.h"
 #include "include/ThrottledSource.h"
 #include "include/MPEG2TSExtractor.h"
 #include "include/TimedTextPlayer.h"
+#include "include/WVMExtractor.h"
 
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -447,6 +449,7 @@
 
     cancelPlayerEvents();
 
+    mWVMExtractor.clear();
     mCachedSource.clear();
     mAudioTrack.clear();
     mVideoTrack.clear();
@@ -545,6 +548,11 @@
         *durationUs = cachedDataRemaining * 8000000ll / bitrate;
         *eos = (finalStatus != OK);
         return true;
+    } else if (mWVMExtractor != NULL) {
+        status_t finalStatus;
+        *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
+        *eos = (finalStatus != OK);
+        return true;
     }
 
     return false;
@@ -637,6 +645,30 @@
                 }
             }
         }
+    } else if (mWVMExtractor != NULL) {
+        status_t finalStatus;
+
+        int64_t cachedDurationUs
+            = mWVMExtractor->getCachedDurationUs(&finalStatus);
+
+        bool eos = (finalStatus != OK);
+
+        if (eos) {
+            if (finalStatus == ERROR_END_OF_STREAM) {
+                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+            }
+            if (mFlags & PREPARING) {
+                LOGV("cache has reached EOS, prepare is done.");
+                finishAsyncPrepare_l();
+            }
+        } else {
+            int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+            if (percentage > 100) {
+                percentage = 100;
+            }
+
+            notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+        }
     }
 
     int64_t cachedDurationUs;
@@ -1425,7 +1457,7 @@
             mVideoBuffer = NULL;
         }
 
-        if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
+        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
                 && !(mFlags & SEEK_PREVIEW)) {
             // We're going to seek the video source first, followed by
             // the audio source.
@@ -1760,8 +1792,19 @@
 status_t AwesomePlayer::finishSetDataSource_l() {
     sp<DataSource> dataSource;
 
+    bool isWidevineStreaming = false;
+    if (!strncasecmp("widevine://", mUri.string(), 11)) {
+        isWidevineStreaming = true;
+
+        String8 newURI = String8("http://");
+        newURI.append(mUri.string() + 11);
+
+        mUri = newURI;
+    }
+
     if (!strncasecmp("http://", mUri.string(), 7)
-            || !strncasecmp("https://", mUri.string(), 8)) {
+            || !strncasecmp("https://", mUri.string(), 8)
+            || isWidevineStreaming) {
         mConnectingDataSource = HTTPBase::Create(
                 (mFlags & INCOGNITO)
                     ? HTTPBase::kFlagIncognito
@@ -1778,16 +1821,24 @@
             return err;
         }
 
+        if (!isWidevineStreaming) {
+            // The widevine extractor does its own caching.
+
 #if 0
-        mCachedSource = new NuCachedSource2(
-                new ThrottledSource(
-                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
+            mCachedSource = new NuCachedSource2(
+                    new ThrottledSource(
+                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
 #else
-        mCachedSource = new NuCachedSource2(mConnectingDataSource);
+            mCachedSource = new NuCachedSource2(mConnectingDataSource);
 #endif
+
+            dataSource = mCachedSource;
+        } else {
+            dataSource = mConnectingDataSource;
+        }
+
         mConnectingDataSource.clear();
 
-        dataSource = mCachedSource;
 
         String8 contentType = dataSource->getMIMEType();
 
@@ -1801,28 +1852,35 @@
             // could block on the datasource for a significant amount of time.
             // During that time we'd be unable to abort the preparation phase
             // without this prefill.
+            if (mCachedSource != NULL) {
+                // We're going to prefill the cache before trying to instantiate
+                // the extractor below, as the latter is an operation that otherwise
+                // could block on the datasource for a significant amount of time.
+                // During that time we'd be unable to abort the preparation phase
+                // without this prefill.
 
-            mLock.unlock();
+                mLock.unlock();
 
-            for (;;) {
-                status_t finalStatus;
-                size_t cachedDataRemaining =
-                    mCachedSource->approxDataRemaining(&finalStatus);
+                for (;;) {
+                    status_t finalStatus;
+                    size_t cachedDataRemaining =
+                        mCachedSource->approxDataRemaining(&finalStatus);
 
-                if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
-                        || (mFlags & PREPARE_CANCELLED)) {
-                    break;
+                    if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+                            || (mFlags & PREPARE_CANCELLED)) {
+                        break;
+                    }
+
+                    usleep(200000);
                 }
 
-                usleep(200000);
+                mLock.lock();
             }
 
-            mLock.lock();
-        }
-
-        if (mFlags & PREPARE_CANCELLED) {
-            LOGI("Prepare cancelled while waiting for initial cache fill.");
-            return UNKNOWN_ERROR;
+            if (mFlags & PREPARE_CANCELLED) {
+                LOGI("Prepare cancelled while waiting for initial cache fill.");
+                return UNKNOWN_ERROR;
+            }
         }
     } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
         if (mLooper == NULL) {
@@ -1856,10 +1914,29 @@
         return UNKNOWN_ERROR;
     }
 
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    sp<MediaExtractor> extractor;
 
-    if (extractor == NULL) {
-        return UNKNOWN_ERROR;
+    if (isWidevineStreaming) {
+        String8 mimeType;
+        float confidence;
+        sp<AMessage> dummy;
+        bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
+
+        if (!success
+                || strcasecmp(
+                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
+            return ERROR_UNSUPPORTED;
+        }
+
+        mWVMExtractor = new WVMExtractor(dataSource);
+        mWVMExtractor->setAdaptiveStreamingMode(true);
+        extractor = mWVMExtractor;
+    } else {
+        extractor = MediaExtractor::Create(dataSource);
+
+        if (extractor == NULL) {
+            return UNKNOWN_ERROR;
+        }
     }
 
     dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
@@ -1871,7 +1948,15 @@
         }
     }
 
-    return setDataSource_l(extractor);
+    status_t err = setDataSource_l(extractor);
+
+    if (err != OK) {
+        mWVMExtractor.clear();
+
+        return err;
+    }
+
+    return OK;
 }
 
 void AwesomePlayer::abortPrepare(status_t err) {
@@ -1932,7 +2017,7 @@
 
     mFlags |= PREPARING_CONNECTED;
 
-    if (mCachedSource != NULL || mRTSPController != NULL) {
+    if (isStreamingHTTP() || mRTSPController != NULL) {
         postBufferingEvent_l();
     } else {
         finishAsyncPrepare_l();
@@ -1985,4 +2070,9 @@
 status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
     return OK;
 }
+
+bool AwesomePlayer::isStreamingHTTP() const {
+    return mCachedSource != NULL || mWVMExtractor != NULL;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 7c72852..83a1eaa 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -45,7 +45,8 @@
 static Mutex gWVMutex;
 
 WVMExtractor::WVMExtractor(const sp<DataSource> &source)
-    : mDataSource(source) {
+    : mDataSource(source),
+      mUseAdaptiveStreaming(false) {
     {
         Mutex::Autolock autoLock(gWVMutex);
         if (gVendorLibHandle == NULL) {
@@ -100,5 +101,21 @@
     return mImpl->getMetaData();
 }
 
+int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
+    // TODO: Fill this with life.
+
+    *finalStatus = OK;
+
+    return 0;
+}
+
+void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
+    mUseAdaptiveStreaming = adaptive;
+}
+
+bool WVMExtractor::getAdaptiveStreamingMode() const {
+    return mUseAdaptiveStreaming;
+}
+
 } //namespace android
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 835d2bb..3c9a121 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -45,6 +45,7 @@
 class DecryptHandle;
 
 class TimedTextPlayer;
+struct WVMExtractor;
 
 struct AwesomeRenderer : public RefBase {
     AwesomeRenderer() {}
@@ -231,6 +232,8 @@
     int64_t mLastVideoTimeUs;
     TimedTextPlayer *mTextPlayer;
 
+    sp<WVMExtractor> mWVMExtractor;
+
     status_t setDataSource_l(
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL);
@@ -286,6 +289,8 @@
     void shutdownVideoDecoder_l();
     void setNativeWindow_l(const sp<ANativeWindow> &native);
 
+    bool isStreamingHTTP() const;
+
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index 0da45a8..62e5aa5 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -19,6 +19,7 @@
 #define WVM_EXTRACTOR_H_
 
 #include <media/stagefright/MediaExtractor.h>
+#include <utils/Errors.h>
 
 namespace android {
 
@@ -33,12 +34,31 @@
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
     virtual sp<MetaData> getMetaData();
 
+    // Return the amount of data cached from the current
+    // playback positiion (in us).
+    // While more data is still being fetched *finalStatus == OK,
+    // Once fetching is completed (no more data available), *finalStatus != OK
+    // If fetching completed normally (i.e. reached EOS instead of IO error)
+    // *finalStatus == ERROR_END_OF_STREAM
+    int64_t getCachedDurationUs(status_t *finalStatus);
+
+    // Set to use adaptive streaming mode by the WV component.
+    // If adaptive == true, adaptive streaming mode will be used.
+    // Default mode is non-adaptive streaming mode.
+    // Should set to use adaptive streaming mode only if widevine:// protocol
+    // is used.
+    void setAdaptiveStreamingMode(bool adaptive);
+
+    // Retrieve the adaptive streaming mode used by the WV component.
+    bool getAdaptiveStreamingMode() const;
+
 protected:
     virtual ~WVMExtractor();
 
 private:
     sp<DataSource> mDataSource;
     sp<MediaExtractor> mImpl;
+    bool mUseAdaptiveStreaming;
 
     WVMExtractor(const WVMExtractor &);
     WVMExtractor &operator=(const WVMExtractor &);