Stagefright DataSources now expose the underlying content mime type.

Use that mime type to determine if we should do upfront buffering at the start of
playback and don't for audio streams to ensure playback starts fairly instantly.

Change-Id: If21e36d1b024f0e5c723911bceadaa2e0307ab42
related-to-bug: 4090916
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index d30e908..6b6fcdf 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -84,6 +84,8 @@
         return String8();
     }
 
+    virtual String8 getMIMEType() const;
+
 protected:
     virtual ~DataSource() {}
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7940de0..759bd86 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1693,29 +1693,37 @@
 
         dataSource = mCachedSource;
 
-        // 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.
+        String8 contentType = dataSource->getMIMEType();
 
-        mLock.unlock();
+        if (strncasecmp(contentType.string(), "audio/", 6)) {
+            // We're not doing this for streams that appear to be audio-only
+            // streams to ensure that even low bandwidth streams start
+            // playing back fairly instantly.
 
-        for (;;) {
-            status_t finalStatus;
-            size_t cachedDataRemaining =
-                mCachedSource->approxDataRemaining(&finalStatus);
+            // 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.
 
-            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
-                    || (mFlags & PREPARE_CANCELLED)) {
-                break;
+            mLock.unlock();
+
+            for (;;) {
+                status_t finalStatus;
+                size_t cachedDataRemaining =
+                    mCachedSource->approxDataRemaining(&finalStatus);
+
+                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;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index b5c51f4..7c2096e 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -144,4 +144,8 @@
     return source;
 }
 
+String8 DataSource::getMIMEType() const {
+    return String8("application/octet-stream");
+}
+
 }  // namespace android
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 3c99d1c..c1aa46e 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -493,4 +493,8 @@
     return mSource->getUri();
 }
 
+String8 NuCachedSource2::getMIMEType() const {
+    return mSource->getMIMEType();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 73daf12..5c43a5b 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -136,6 +136,7 @@
     unsigned port;
 
     mUri = uri;
+    mContentType = String8("application/octet-stream");
 
     bool https;
     if (!ParseURL(uri, &host, &port, &path, &https)) {
@@ -265,6 +266,15 @@
             }
         }
 
+        {
+            AString value;
+            if (mHTTP.find_header_value("Content-Type", &value)) {
+                mContentType = String8(value.c_str());
+            } else {
+                mContentType = String8("application/octet-stream");
+            }
+        }
+
         applyTimeoutResponse();
 
         if (offset == 0) {
@@ -564,4 +574,8 @@
     return mUri;
 }
 
+String8 NuHTTPDataSource::getMIMEType() const {
+    return mContentType;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 949a5e4..1096717 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -79,6 +79,7 @@
     }
 
     mURI = uri;
+    mContentType = String8("application/octet-stream");
 
     if (headers != NULL) {
         mHeaders = *headers;
@@ -99,10 +100,12 @@
     return mState == CONNECTED ? OK : mIOResult;
 }
 
-void ChromiumHTTPDataSource::onConnectionEstablished(int64_t contentSize) {
+void ChromiumHTTPDataSource::onConnectionEstablished(
+        int64_t contentSize, const char *contentType) {
     Mutex::Autolock autoLock(mLock);
     mState = CONNECTED;
     mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+    mContentType = String8(contentType);
     mCondition.broadcast();
 }
 
@@ -314,6 +317,12 @@
     return String8(mURI.c_str());
 }
 
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+    Mutex::Autolock autoLock(mLock);
+
+    return mContentType;
+}
+
 void ChromiumHTTPDataSource::clearDRMState_l() {
     if (mDecryptHandle != NULL) {
         // To release mDecryptHandle
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index 7ac56e8..af2f6ac 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -253,7 +253,11 @@
 
     MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
 
-    mOwner->onConnectionEstablished(request->GetExpectedContentSize());
+    std::string contentType;
+    request->GetResponseHeaderByName("Content-Type", &contentType);
+
+    mOwner->onConnectionEstablished(
+            request->GetExpectedContentSize(), contentType.c_str());
 }
 
 void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index af49059..0e2927d 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -51,6 +51,8 @@
 
     virtual String8 getUri();
 
+    virtual String8 getMIMEType() const;
+
 protected:
     virtual ~ChromiumHTTPDataSource();
 
@@ -90,6 +92,8 @@
 
     int64_t mContentSize;
 
+    String8 mContentType;
+
     List<BandwidthEntry> mBandwidthHistory;
     size_t mNumBandwidthHistoryItems;
     int64_t mTotalTransferTimeUs;
@@ -110,7 +114,9 @@
 
     void initiateRead(void *data, size_t size);
 
-    void onConnectionEstablished(int64_t contentSize);
+    void onConnectionEstablished(
+            int64_t contentSize, const char *contentType);
+
     void onConnectionFailed(status_t err);
     void onReadCompleted(ssize_t size);
     void onDisconnectComplete();
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 02d5817..2128682 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -40,6 +40,9 @@
     virtual sp<DecryptHandle> DrmInitialization();
     virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
+
+    virtual String8 getMIMEType() const;
+
     ////////////////////////////////////////////////////////////////////////////
 
     size_t cachedSize();
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 7dd5d59..2ab1f19 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -51,6 +51,8 @@
     virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
 
+    virtual String8 getMIMEType() const;
+
 protected:
     virtual ~NuHTTPDataSource();
 
@@ -85,6 +87,8 @@
     bool mContentLengthValid;
     bool mHasChunkedTransferEncoding;
 
+    String8 mContentType;
+
     // The number of data bytes in the current chunk before any subsequent
     // chunk header (or -1 if no more chunks).
     ssize_t mChunkDataBytesLeft;