Merge "Support for ID3 V2.4 tags." into froyo
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index b5d1e7a..ea31942 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -54,7 +54,7 @@
 
 private:
     enum {
-        kBufferSize = 32 * 1024,
+        kBufferSize = 64 * 1024,
 
         // If we encounter a socket-read error we'll try reconnecting
         // and restarting the read for at most this many times.
@@ -77,9 +77,6 @@
     int mStartingPort;
 
     HTTPStream *mHttp;
-    char *mHost;
-    int mPort;
-    char *mPath;
 
     void *mBuffer;
     size_t mBufferLength;
@@ -95,6 +92,8 @@
     ssize_t sendRangeRequest(size_t offset);
     void initHeaders(const KeyedVector<String8, String8> *overrides);
 
+    status_t connectWithRedirectsAndRange(off_t rangeStart);
+
     HTTPDataSource(const HTTPDataSource &);
     HTTPDataSource &operator=(const HTTPDataSource &);
 };
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e7022f4..63dfa67 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1091,7 +1091,7 @@
         }
 
         dataSource = new CachingDataSource(
-                mConnectingDataSource, 32 * 1024, 20);
+                mConnectingDataSource, 64 * 1024, 10);
 
         mConnectingDataSource.clear();
     } else {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 284e3bc..86e4bfe 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -105,7 +105,7 @@
         if (httpSource->connect() != OK) {
             return NULL;
         }
-        source = new CachingDataSource(httpSource, 32 * 1024, 20);
+        source = new CachingDataSource(httpSource, 64 * 1024, 10);
     } else {
         // Assume it's a filename.
         source = new FileSource(uri);
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 61ffa8d..a0b1993 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -29,71 +29,101 @@
 
 namespace android {
 
-// Given a connected HTTPStream, determine if the given path redirects
-// somewhere else, if so, disconnect the stream, update host path and port
-// accordingly and return true, otherwise return false and leave the stream
-// connected.
-static bool PerformRedirectIfNecessary(
-        HTTPStream *http, const String8 &headers,
-        string *host, string *path, int *port) {
-    String8 request;
-    request.append("GET ");
-    request.append(path->c_str());
-    request.append(" HTTP/1.1\r\n");
-    request.append(headers);
-    request.append("Host: ");
-    request.append(host->c_str());
-    request.append("\r\n\r\n");
+status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {
+    string host = mStartingHost.string();
+    string path = mStartingPath.string();
+    int port = mStartingPort;
 
-    status_t err = http->send(request.string());
+    LOGV("Connecting to host '%s', port %d, path '%s'",
+         host.c_str(), port, path.c_str());
 
-    int http_status;
-    if (err == OK) {
-        err = http->receive_header(&http_status);
+    int numRedirectsRemaining = 5;
+    while (numRedirectsRemaining-- > 0) {
+        status_t err = mHttp->connect(host.c_str(), port);
+
+        if (err != OK) {
+            return err;
+        }
+
+        String8 request;
+        request.append("GET ");
+        request.append(path.c_str());
+        request.append(" HTTP/1.1\r\n");
+        request.append(mHeaders);
+        request.append("Host: ");
+        request.append(host.c_str());
+        request.append("\r\n");
+
+        if (rangeStart > 0) {
+            char range[128];
+            sprintf(range, "Range: bytes=%ld-\r\n", rangeStart);
+
+            request.append(range);
+        }
+
+        request.append("\r\n");
+
+        err = mHttp->send(request.string());
+
+        if (err != OK) {
+            return err;
+        }
+
+        int httpStatus;
+        err = mHttp->receive_header(&httpStatus);
+
+        if (err != OK) {
+            return err;
+        }
+
+        if (httpStatus >= 200 && httpStatus < 300) {
+            return OK;
+        }
+
+        if (httpStatus != 301 && httpStatus != 302) {
+            LOGE("HTTP request failed w/ http status %d", httpStatus);
+            return ERROR_IO;
+        }
+
+        string location;
+        CHECK(mHttp->find_header_value("Location", &location));
+
+        CHECK(string(location, 0, 7) == "http://");
+        location.erase(0, 7);
+        string::size_type slashPos = location.find('/');
+        if (slashPos == string::npos) {
+            slashPos = location.size();
+            location += '/';
+        }
+
+        mHttp->disconnect();
+
+        LOGV("Redirecting to %s\n", location.c_str());
+
+        host = string(location, 0, slashPos);
+
+        string::size_type colonPos = host.find(':');
+        if (colonPos != string::npos) {
+            const char *start = host.c_str() + colonPos + 1;
+            char *end;
+            long tmp = strtol(start, &end, 10);
+            CHECK(end > start && (*end == '\0'));
+
+            port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
+
+            host.erase(colonPos, host.size() - colonPos);
+        } else {
+            port = 80;
+        }
+
+        path = string(location, slashPos);
+
+        mStartingHost = host.c_str();
+        mStartingPath = path.c_str();
+        mStartingPort = port;
     }
 
-    if (err != OK) {
-        return false;
-    }
-
-    if (http_status != 301 && http_status != 302) {
-        return false;
-    }
-
-    string location;
-    CHECK(http->find_header_value("Location", &location));
-
-    CHECK(string(location, 0, 7) == "http://");
-    location.erase(0, 7);
-    string::size_type slashPos = location.find('/');
-    if (slashPos == string::npos) {
-        slashPos = location.size();
-        location += '/';
-    }
-
-    http->disconnect();
-
-    LOGI("Redirecting to %s\n", location.c_str());
-
-    *host = string(location, 0, slashPos);
-
-    string::size_type colonPos = host->find(':');
-    if (colonPos != string::npos) {
-        const char *start = host->c_str() + colonPos + 1;
-        char *end;
-        long tmp = strtol(start, &end, 10);
-        CHECK(end > start && (*end == '\0'));
-
-        *port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
-
-        host->erase(colonPos, host->size() - colonPos);
-    } else {
-        *port = 80;
-    }
-
-    *path = string(location, slashPos);
-
-    return true;
+    return ERROR_IO;
 }
 
 HTTPDataSource::HTTPDataSource(
@@ -147,10 +177,6 @@
     mState = DISCONNECTED;
     mHttp = new HTTPStream;
 
-    mHost = NULL;
-    mPort = 0;
-    mPath = NULL;
-
     initHeaders(headers);
 
     mBuffer = malloc(kBufferSize);
@@ -173,29 +199,18 @@
     mBufferOffset = 0;
     mContentLengthValid = false;
 
-    string host = mStartingHost.string();
-    string path = mStartingPath.string();
-    int port = mStartingPort;
+    status_t err = connectWithRedirectsAndRange(0);
 
-    LOGI("Connecting to host '%s', port %d, path '%s'",
-         host.c_str(), port, path.c_str());
+    if (err != OK) {
+        Mutex::Autolock autoLock(mStateLock);
 
-    int numRedirectsRemaining = 5;
-    do {
-        status_t err = mHttp->connect(host.c_str(), port);
-
-        if (err != OK) {
-            Mutex::Autolock autoLock(mStateLock);
-
-            if (mState != CONNECTING) {
-                LOGV("connect() cancelled");
-            }
-            mState = DISCONNECTED;
-
-            return err;
+        if (mState != CONNECTING) {
+            LOGV("connect() cancelled");
         }
-    } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
-             && numRedirectsRemaining-- > 0);
+        mState = DISCONNECTED;
+
+        return err;
+    }
 
     string value;
     if (mHttp->find_header_value("Content-Length", &value)) {
@@ -204,10 +219,6 @@
         mContentLengthValid = true;
     }
 
-    mHost = strdup(host.c_str());
-    mPort = port;
-    mPath = strdup(path.c_str());
-
     Mutex::Autolock autoLock(mStateLock);
 
     if (mState != CONNECTING) {
@@ -219,6 +230,7 @@
     }
 
     mState = CONNECTED;
+
     return OK;
 }
 
@@ -264,56 +276,13 @@
 
     free(mBuffer);
     mBuffer = NULL;
-
-    if (mPath) {
-        free(mPath);
-        mPath = NULL;
-    }
-
-    if (mHost) {
-        free(mHost);
-        mHost = NULL;
-    }
 }
 
 ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
-    char host[128];
-    sprintf(host, "Host: %s\r\n", mHost);
+    status_t err = connectWithRedirectsAndRange(offset);
 
-    char range[128];
-    if (offset > 0) {
-        sprintf(range, "Range: bytes=%d-\r\n\r\n", offset);
-    } else {
-        range[0] = '\0';
-    }
-
-    int http_status;
-
-    status_t err;
-    int attempt = 1;
-    for (;;) {
-        if ((err = mHttp->send("GET ")) != OK
-            || (err = mHttp->send(mPath)) != OK
-            || (err = mHttp->send(" HTTP/1.1\r\n")) != OK
-            || (err = mHttp->send(mHeaders.string())) != OK
-            || (err = mHttp->send(host)) != OK
-            || (err = mHttp->send(range)) != OK
-            || (err = mHttp->send("\r\n")) != OK
-            || (err = mHttp->receive_header(&http_status)) != OK) {
-
-            if (attempt == 3) {
-                return err;
-            }
-
-            mHttp->connect(mHost, mPort);
-            ++attempt;
-        } else {
-            break;
-        }
-    }
-
-    if ((http_status / 100) != 2) {
-        return UNKNOWN_ERROR;
+    if (err != OK) {
+        return err;
     }
 
     string value;
@@ -349,6 +318,10 @@
 
         memcpy(data, (const char *)mBuffer + (offset - mBufferOffset), copy);
 
+        if (copy < size) {
+            LOGV("short read (1), returning %d vs. %d requested", copy, size);
+        }
+
         return copy;
     }
 
@@ -388,8 +361,10 @@
     if (num_bytes_received < 0
             || (mContentLengthValid && num_bytes_received < contentLength)) {
         if (mNumRetriesLeft-- > 0) {
-            disconnect();
-            if (connect() == OK) {
+            mHttp->disconnect();
+            mBufferLength = 0;
+            num_bytes_received = connectWithRedirectsAndRange(mBufferOffset);
+            if (num_bytes_received == OK) {
                 LOGI("retrying connection succeeded.");
                 goto rinse_repeat;
             }