nuplayer: add widevine support to GenericSource

Bug: 15699665
Change-Id: Ided823bd0b1118bbabb288cf62d6389518f820a9
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index cc0cb01..d75408d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -28,6 +28,7 @@
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
+#include "../../libstagefright/include/WVMExtractor.h"
 
 namespace android {
 
@@ -35,10 +36,16 @@
         const sp<AMessage> &notify,
         const sp<IMediaHTTPService> &httpService,
         const char *url,
-        const KeyedVector<String8, String8> *headers)
+        const KeyedVector<String8, String8> *headers,
+        bool isWidevine,
+        bool uidValid,
+        uid_t uid)
     : Source(notify),
       mDurationUs(0ll),
-      mAudioIsVorbis(false) {
+      mAudioIsVorbis(false),
+      mIsWidevine(isWidevine),
+      mUIDValid(uidValid),
+      mUID(uid) {
     DataSource::RegisterDefaultSniffers();
 
     sp<DataSource> dataSource =
@@ -63,7 +70,31 @@
 
 void NuPlayer::GenericSource::initFromDataSource(
         const sp<DataSource> &dataSource) {
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    sp<MediaExtractor> extractor;
+
+    if (mIsWidevine) {
+        String8 mimeType;
+        float confidence;
+        sp<AMessage> dummy;
+        bool success;
+
+        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
+        if (!success
+                || strcasecmp(
+                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
+            ALOGE("unsupported widevine mime: %s", mimeType.string());
+            return;
+        }
+
+        sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
+        wvmExtractor->setAdaptiveStreamingMode(true);
+        if (mUIDValid) {
+            wvmExtractor->setUID(mUID);
+        }
+        extractor = wvmExtractor;
+    } else {
+        extractor = MediaExtractor::Create(dataSource);
+    }
 
     CHECK(extractor != NULL);
 
@@ -113,6 +144,13 @@
     }
 }
 
+status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
+    if (mIsWidevine && !audio) {
+        return mVideoTrack.mSource->setBuffers(buffers);
+    }
+    return INVALID_OPERATION;
+}
+
 NuPlayer::GenericSource::~GenericSource() {
 }
 
@@ -128,7 +166,8 @@
     }
 
     notifyFlagsChanged(
-            FLAG_CAN_PAUSE
+            (mIsWidevine ? FLAG_SECURE : 0)
+            | FLAG_CAN_PAUSE
             | FLAG_CAN_SEEK_BACKWARD
             | FLAG_CAN_SEEK_FORWARD
             | FLAG_CAN_SEEK);
@@ -180,9 +219,14 @@
         return -EWOULDBLOCK;
     }
 
+    if (mIsWidevine && !audio) {
+        // try to read a buffer as we may not have been able to the last time
+        readBuffer(audio, -1ll);
+    }
+
     status_t finalResult;
     if (!track->mPackets->hasBufferAvailable(&finalResult)) {
-        return finalResult == OK ? -EWOULDBLOCK : finalResult;
+        return (finalResult == OK ? -EWOULDBLOCK : finalResult);
     }
 
     status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
@@ -280,6 +324,10 @@
         seeking = true;
     }
 
+    if (mIsWidevine && !audio) {
+        options.setNonBlocking();
+    }
+
     for (;;) {
         MediaBuffer *mbuf;
         status_t err = track->mSource->read(&mbuf, &options);
@@ -293,11 +341,18 @@
                 outLength += sizeof(int32_t);
             }
 
-            sp<ABuffer> buffer = new ABuffer(outLength);
-
-            memcpy(buffer->data(),
-                   (const uint8_t *)mbuf->data() + mbuf->range_offset(),
-                   mbuf->range_length());
+            sp<ABuffer> buffer;
+            if (mIsWidevine && !audio) {
+                // data is already provided in the buffer
+                buffer = new ABuffer(NULL, mbuf->range_length());
+                buffer->meta()->setPointer("mediaBuffer", mbuf);
+                mbuf->add_ref();
+            } else {
+                buffer = new ABuffer(outLength);
+                memcpy(buffer->data(),
+                       (const uint8_t *)mbuf->data() + mbuf->range_offset(),
+                       mbuf->range_length());
+            }
 
             if (audio && mAudioIsVorbis) {
                 int32_t numPageSamples;
@@ -332,6 +387,8 @@
 
             track->mPackets->queueAccessUnit(buffer);
             break;
+        } else if (err == WOULD_BLOCK) {
+            break;
         } else if (err == INFO_FORMAT_CHANGED) {
 #if 0
             track->mPackets->queueDiscontinuity(
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index e0cd20f..8e0209d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -35,7 +35,10 @@
             const sp<AMessage> &notify,
             const sp<IMediaHTTPService> &httpService,
             const char *url,
-            const KeyedVector<String8, String8> *headers);
+            const KeyedVector<String8, String8> *headers,
+            bool isWidevine = false,
+            bool uidValid = false,
+            uid_t uid = 0);
 
     GenericSource(
             const sp<AMessage> &notify,
@@ -54,6 +57,8 @@
     virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
     virtual status_t seekTo(int64_t seekTimeUs);
 
+    virtual status_t setBuffers(bool audio, Vector<MediaBuffer *> &buffers);
+
 protected:
     virtual ~GenericSource();
 
@@ -73,6 +78,9 @@
 
     int64_t mDurationUs;
     bool mAudioIsVorbis;
+    bool mIsWidevine;
+    bool mUIDValid;
+    uid_t mUID;
 
     void initFromDataSource(const sp<DataSource> &dataSource);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 632c4a6..259925f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -21,11 +21,14 @@
 #include "NuPlayer.h"
 
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Vector.h>
 
 namespace android {
 
 struct ABuffer;
 struct MetaData;
+struct MediaBuffer;
 
 struct NuPlayer::Source : public AHandler {
     enum Flags {
@@ -34,6 +37,7 @@
         FLAG_CAN_SEEK_FORWARD   = 4,  // the "10 sec forward button"
         FLAG_CAN_SEEK           = 8,  // the "seek bar"
         FLAG_DYNAMIC_DURATION   = 16,
+        FLAG_SECURE             = 32,
     };
 
     enum {
@@ -89,6 +93,10 @@
         return INVALID_OPERATION;
     }
 
+    virtual status_t setBuffers(bool /* audio */, Vector<MediaBuffer *> &/* buffers */) {
+        return INVALID_OPERATION;
+    }
+
     virtual bool isRealTime() const {
         return false;
     }