summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-07-14 09:09:07 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-07-14 09:09:07 -0700
commit49c8340bd83cc5d64b1fcaed4afbda5fd4d74a3e (patch)
tree6a24d306f6b16e2e70ebc7318bad26a616983c42 /media
parent0ee92ffd74ac8594b68aa3c73b341dc0c6330b3f (diff)
parentdab718bba3945332dc75e268e1e7f0fe2eb91c4a (diff)
downloadframeworks_av-49c8340bd83cc5d64b1fcaed4afbda5fd4d74a3e.zip
frameworks_av-49c8340bd83cc5d64b1fcaed4afbda5fd4d74a3e.tar.gz
frameworks_av-49c8340bd83cc5d64b1fcaed4afbda5fd4d74a3e.tar.bz2
Merge "Remove legacy http support from stagefright, chromium is the new hotness."
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/Android.mk3
-rw-r--r--media/libstagefright/HTTPBase.cpp19
-rw-r--r--media/libstagefright/HTTPStream.cpp623
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp560
-rw-r--r--media/libstagefright/ShoutcastSource.cpp157
-rw-r--r--media/libstagefright/include/HTTPBase.h2
-rw-r--r--media/libstagefright/include/HTTPStream.h91
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h114
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp4
-rw-r--r--media/libstagefright/rtsp/MyHandler.h6
10 files changed, 19 insertions, 1560 deletions
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 0b998b9..e17e1e8 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -22,7 +22,6 @@ LOCAL_SRC_FILES:= \
FileSource.cpp \
FLACExtractor.cpp \
HTTPBase.cpp \
- HTTPStream.cpp \
JPEGSource.cpp \
MP3Extractor.cpp \
MPEG2TSWriter.cpp \
@@ -36,13 +35,11 @@ LOCAL_SRC_FILES:= \
MediaSourceSplitter.cpp \
MetaData.cpp \
NuCachedSource2.cpp \
- NuHTTPDataSource.cpp \
OMXClient.cpp \
OMXCodec.cpp \
OggExtractor.cpp \
SampleIterator.cpp \
SampleTable.cpp \
- ShoutcastSource.cpp \
StagefrightMediaScanner.cpp \
StagefrightMetadataRetriever.cpp \
ThrottledSource.cpp \
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 0d24551..f9d8501 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -24,10 +24,11 @@
#include "include/ChromiumHTTPDataSource.h"
#endif
-#include "include/NuHTTPDataSource.h"
-
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
+
#include <cutils/properties.h>
+#include <cutils/qtaguid.h>
namespace android {
@@ -44,14 +45,12 @@ HTTPBase::HTTPBase()
// static
sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
#if CHROMIUM_AVAILABLE
- char value[PROPERTY_VALUE_MAX];
- if (!property_get("media.stagefright.use-chromium", value, NULL)
- || (strcasecmp("false", value) && strcmp("0", value))) {
return new ChromiumHTTPDataSource(flags);
- } else
#endif
{
- return new NuHTTPDataSource(flags);
+ TRESPASS();
+
+ return NULL;
}
}
@@ -135,4 +134,10 @@ bool HTTPBase::getUID(uid_t *uid) const {
return true;
}
+// static
+void HTTPBase::RegisterSocketUser(int s, uid_t uid) {
+ static const uint32_t kTag = 0xdeadbeef;
+ set_qtaguid(s, kTag, uid);
+}
+
} // namespace android
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
deleted file mode 100644
index d526ebd..0000000
--- a/media/libstagefright/HTTPStream.cpp
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "HTTPStream"
-#include <utils/Log.h>
-
-#include "include/HTTPStream.h"
-
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-#include <openssl/ssl.h>
-
-namespace android {
-
-// static
-const char *HTTPStream::kStatusKey = ":status:"; // MUST be lowercase.
-
-HTTPStream::HTTPStream()
- : mState(READY),
- mUIDValid(false),
- mSocket(-1),
- mSSLContext(NULL),
- mSSL(NULL) {
-}
-
-HTTPStream::~HTTPStream() {
- disconnect();
-
- if (mSSLContext != NULL) {
- SSL_CTX_free((SSL_CTX *)mSSLContext);
- mSSLContext = NULL;
- }
-}
-
-void HTTPStream::setUID(uid_t uid) {
- mUIDValid = true;
- mUID = uid;
-}
-
-static bool MakeSocketBlocking(int s, bool blocking) {
- // Make socket non-blocking.
- int flags = fcntl(s, F_GETFL, 0);
- if (flags == -1) {
- return false;
- }
-
- if (blocking) {
- flags &= ~O_NONBLOCK;
- } else {
- flags |= O_NONBLOCK;
- }
-
- return fcntl(s, F_SETFL, flags) != -1;
-}
-
-static status_t MyConnect(
- int s, const struct sockaddr *addr, socklen_t addrlen) {
- status_t result = UNKNOWN_ERROR;
-
- MakeSocketBlocking(s, false);
-
- if (connect(s, addr, addrlen) == 0) {
- result = OK;
- } else if (errno != EINPROGRESS) {
- result = -errno;
- } else {
- for (;;) {
- fd_set rs, ws;
- FD_ZERO(&rs);
- FD_ZERO(&ws);
- FD_SET(s, &rs);
- FD_SET(s, &ws);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000ll;
-
- int nfds = ::select(s + 1, &rs, &ws, NULL, &tv);
-
- if (nfds < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- }
-
- if (FD_ISSET(s, &ws) && !FD_ISSET(s, &rs)) {
- result = OK;
- break;
- }
-
- if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
- // Get the pending error.
- int error = 0;
- socklen_t errorLen = sizeof(error);
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errorLen) == -1) {
- // Couldn't get the real error, so report why not.
- result = -errno;
- } else {
- result = -error;
- }
- break;
- }
-
- // Timeout expired. Try again.
- }
- }
-
- MakeSocketBlocking(s, true);
-
- return result;
-}
-
-// Apparently under out linux closing a socket descriptor from one thread
-// will not unblock a pending send/recv on that socket on another thread.
-static ssize_t MySendReceive(
- int s, void *data, size_t size, int flags, bool sendData) {
- ssize_t result = 0;
-
- if (s < 0) {
- return -1;
- }
- while (size > 0) {
- fd_set rs, ws, es;
- FD_ZERO(&rs);
- FD_ZERO(&ws);
- FD_ZERO(&es);
- FD_SET(s, sendData ? &ws : &rs);
- FD_SET(s, &es);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000ll;
-
- int nfds = ::select(
- s + 1,
- sendData ? NULL : &rs,
- sendData ? &ws : NULL,
- &es,
- &tv);
-
- if (nfds < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- } else if (nfds == 0) {
- // timeout
-
- continue;
- }
-
- CHECK_EQ(nfds, 1);
-
- ssize_t nbytes =
- sendData ? send(s, data, size, flags) : recv(s, data, size, flags);
-
- if (nbytes < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- } else if (nbytes == 0) {
- result = 0;
- break;
- }
-
- data = (uint8_t *)data + nbytes;
- size -= nbytes;
-
- result = nbytes;
- break;
- }
-
- return result;
-}
-
-static ssize_t MySend(int s, const void *data, size_t size, int flags) {
- return MySendReceive(
- s, const_cast<void *>(data), size, flags, true /* sendData */);
-}
-
-static ssize_t MyReceive(int s, void *data, size_t size, int flags) {
- return MySendReceive(s, data, size, flags, false /* sendData */);
-}
-
-status_t HTTPStream::connect(const char *server, int port, bool https) {
- if (port < 0) {
- port = https ? 443 : 80;
- }
-
- Mutex::Autolock autoLock(mLock);
-
- status_t err = OK;
-
- if (mState == CONNECTED) {
- return ERROR_ALREADY_CONNECTED;
- }
-
- if (port < 0 || port > (int) USHRT_MAX) {
- return UNKNOWN_ERROR;
- }
-
- char service[sizeof("65536")];
- sprintf(service, "%d", port);
- struct addrinfo hints, *ai;
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
- hints.ai_socktype = SOCK_STREAM;
-
- int ret = getaddrinfo(server, service, &hints, &ai);
- if (ret) {
- return ERROR_UNKNOWN_HOST;
- }
-
- CHECK_EQ(mSocket, -1);
-
- mState = CONNECTING;
- status_t res = -1;
- struct addrinfo *tmp;
- for (tmp = ai; tmp; tmp = tmp->ai_next) {
- mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
- if (mSocket < 0) {
- continue;
- }
-
- if (mUIDValid) {
- RegisterSocketUser(mSocket, mUID);
- }
-
- setReceiveTimeout(30); // Time out reads after 30 secs by default.
-
- int s = mSocket;
-
- mLock.unlock();
-
- res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen);
-
- mLock.lock();
-
- if (mState != CONNECTING) {
- close(s);
- freeaddrinfo(ai);
- return UNKNOWN_ERROR;
- }
-
- if (res == OK) {
- break;
- }
-
- close(s);
- }
-
- freeaddrinfo(ai);
-
- if (res != OK) {
- close(mSocket);
- mSocket = -1;
-
- mState = READY;
- return res;
- }
-
- if (https) {
- CHECK(mSSL == NULL);
-
- if (mSSLContext == NULL) {
- SSL_library_init();
-
- mSSLContext = SSL_CTX_new(TLSv1_client_method());
-
- if (mSSLContext == NULL) {
- LOGE("failed to create SSL context");
- mState = READY;
- return ERROR_IO;
- }
- }
-
- mSSL = SSL_new((SSL_CTX *)mSSLContext);
-
- if (mSSL == NULL) {
- LOGE("failed to create SSL session");
-
- mState = READY;
- return ERROR_IO;
- }
-
- int res = SSL_set_fd((SSL *)mSSL, mSocket);
-
- if (res == 1) {
- res = SSL_connect((SSL *)mSSL);
- }
-
- if (res != 1) {
- SSL_free((SSL *)mSSL);
- mSSL = NULL;
-
- LOGE("failed to connect over SSL");
- mState = READY;
-
- return ERROR_IO;
- }
- }
-
- mState = CONNECTED;
-
- return OK;
-}
-
-status_t HTTPStream::disconnect() {
- Mutex::Autolock autoLock(mLock);
-
- if (mState != CONNECTED && mState != CONNECTING) {
- return ERROR_NOT_CONNECTED;
- }
-
- if (mSSL != NULL) {
- SSL_shutdown((SSL *)mSSL);
-
- SSL_free((SSL *)mSSL);
- mSSL = NULL;
- }
-
- CHECK(mSocket >= 0);
- close(mSocket);
- mSocket = -1;
-
- mState = READY;
-
- return OK;
-}
-
-status_t HTTPStream::send(const char *data, size_t size) {
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
-
- while (size > 0) {
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_write((SSL *)mSSL, data, size);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MySend(mSocket, data, size, 0);
- }
-
- if (n < 0) {
- disconnect();
-
- return n;
- } else if (n == 0) {
- disconnect();
-
- return ERROR_CONNECTION_LOST;
- }
-
- size -= (size_t)n;
- data += (size_t)n;
- }
-
- return OK;
-}
-
-status_t HTTPStream::send(const char *data) {
- return send(data, strlen(data));
-}
-
-// A certain application spawns a local webserver that sends invalid responses,
-// specifically it terminates header line with only a newline instead of the
-// CRLF (carriage-return followed by newline) required by the HTTP specs.
-// The workaround accepts both behaviours but could potentially break
-// legitimate responses that use a single newline to "fold" headers, which is
-// why it's not yet on by default.
-#define WORKAROUND_FOR_MISSING_CR 1
-
-status_t HTTPStream::receive_line(char *line, size_t size) {
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
-
- bool saw_CR = false;
- size_t length = 0;
-
- for (;;) {
- char c;
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_read((SSL *)mSSL, &c, 1);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MyReceive(mSocket, &c, 1, 0);
- }
-
- if (n < 0) {
- disconnect();
-
- return ERROR_IO;
- } else if (n == 0) {
- disconnect();
-
- return ERROR_CONNECTION_LOST;
- }
-
-#if WORKAROUND_FOR_MISSING_CR
- if (c == '\n') {
- // We have a complete line.
-
- line[saw_CR ? length - 1 : length] = '\0';
- return OK;
- }
-#else
- if (saw_CR && c == '\n') {
- // We have a complete line.
-
- line[length - 1] = '\0';
- return OK;
- }
-#endif
-
- saw_CR = (c == '\r');
-
- if (length + 1 >= size) {
- return ERROR_MALFORMED;
- }
- line[length++] = c;
- }
-}
-
-status_t HTTPStream::receive_header(int *http_status) {
- *http_status = -1;
- mHeaders.clear();
-
- char line[2048];
- status_t err = receive_line(line, sizeof(line));
- if (err != OK) {
- return err;
- }
-
- mHeaders.add(AString(kStatusKey), AString(line));
-
- char *spacePos = strchr(line, ' ');
- if (spacePos == NULL) {
- // Malformed response?
- return UNKNOWN_ERROR;
- }
-
- char *status_start = spacePos + 1;
- char *status_end = status_start;
- while (isdigit(*status_end)) {
- ++status_end;
- }
-
- if (status_end == status_start) {
- // Malformed response, status missing?
- return UNKNOWN_ERROR;
- }
-
- memmove(line, status_start, status_end - status_start);
- line[status_end - status_start] = '\0';
-
- long tmp = strtol(line, NULL, 10);
- if (tmp < 0 || tmp > 999) {
- return UNKNOWN_ERROR;
- }
-
- *http_status = (int)tmp;
-
- for (;;) {
- err = receive_line(line, sizeof(line));
- if (err != OK) {
- return err;
- }
-
- if (*line == '\0') {
- // Empty line signals the end of the header.
- break;
- }
-
- // puts(line);
-
- char *colonPos = strchr(line, ':');
- if (colonPos == NULL) {
- AString key = line;
- key.tolower();
-
- mHeaders.add(key, AString());
- } else {
- char *end_of_key = colonPos;
- while (end_of_key > line && isspace(end_of_key[-1])) {
- --end_of_key;
- }
-
- char *start_of_value = colonPos + 1;
- while (isspace(*start_of_value)) {
- ++start_of_value;
- }
-
- *end_of_key = '\0';
-
- AString key = line;
- key.tolower();
-
- mHeaders.add(key, AString(start_of_value));
- }
- }
-
- return OK;
-}
-
-ssize_t HTTPStream::receive(void *data, size_t size) {
- size_t total = 0;
- while (total < size) {
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_read((SSL *)mSSL, (char *)data + total, size - total);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MyReceive(mSocket, (char *)data + total, size - total, 0);
- }
-
- if (n < 0) {
- LOGE("recv failed, errno = %d (%s)", (int)n, strerror(-n));
-
- disconnect();
- return (ssize_t)ERROR_IO;
- } else if (n == 0) {
- disconnect();
-
- LOGE("recv failed, server is gone, total received: %d bytes",
- total);
-
- return total == 0 ? (ssize_t)ERROR_CONNECTION_LOST : total;
- }
-
- total += (size_t)n;
- }
-
- return (ssize_t)total;
-}
-
-bool HTTPStream::find_header_value(const AString &key, AString *value) const {
- AString key_lower = key;
- key_lower.tolower();
-
- ssize_t index = mHeaders.indexOfKey(key_lower);
- if (index < 0) {
- value->clear();
- return false;
- }
-
- *value = mHeaders.valueAt(index);
-
- return true;
-}
-
-void HTTPStream::setReceiveTimeout(int seconds) {
- if (seconds < 0) {
- // Disable the timeout.
- seconds = 0;
- }
-
- struct timeval tv;
- tv.tv_usec = 0;
- tv.tv_sec = seconds;
- CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
-}
-
-// static
-void HTTPStream::RegisterSocketUser(int s, uid_t uid) {
- // Lower bits MUST be 0.
- static const uint64_t kTag = 0xdeadbeef00000000ll;
-
- AString line = StringPrintf("t %d %llu %d", s, kTag, uid);
-
- int fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY);
- write(fd, line.c_str(), line.size());
- close(fd);
- fd = -1;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
deleted file mode 100644
index 2949767..0000000
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "NuHTTPDataSource"
-#include <utils/Log.h>
-
-#include "include/NuHTTPDataSource.h"
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-static bool ParseSingleUnsignedLong(
- const char *from, unsigned long *x) {
- char *end;
- *x = strtoul(from, &end, 10);
-
- if (end == from || *end != '\0') {
- return false;
- }
-
- return true;
-}
-
-static bool ParseURL(
- const char *url, String8 *host, unsigned *port,
- String8 *path, bool *https) {
- host->setTo("");
- *port = 0;
- path->setTo("");
-
- size_t hostStart;
- if (!strncasecmp("http://", url, 7)) {
- hostStart = 7;
- *https = false;
- } else if (!strncasecmp("https://", url, 8)) {
- hostStart = 8;
- *https = true;
- } else {
- return false;
- }
-
- const char *slashPos = strchr(&url[hostStart], '/');
-
- if (slashPos == NULL) {
- host->setTo(&url[hostStart]);
- path->setTo("/");
- } else {
- host->setTo(&url[hostStart], slashPos - &url[hostStart]);
- path->setTo(slashPos);
- }
-
- const char *colonPos = strchr(host->string(), ':');
-
- if (colonPos != NULL) {
- unsigned long x;
- if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
- return false;
- }
-
- *port = x;
-
- size_t colonOffset = colonPos - host->string();
- String8 tmp(host->string(), colonOffset);
- *host = tmp;
- } else {
- *port = (*https) ? 443 : 80;
- }
-
- return true;
-}
-
-NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
- : mFlags(flags),
- mState(DISCONNECTED),
- mPort(0),
- mHTTPS(false),
- mOffset(0),
- mContentLength(0),
- mContentLengthValid(false),
- mHasChunkedTransferEncoding(false),
- mChunkDataBytesLeft(0),
- mDecryptHandle(NULL),
- mDrmManagerClient(NULL) {
-}
-
-NuHTTPDataSource::~NuHTTPDataSource() {
- if (mDecryptHandle != NULL) {
- // To release mDecryptHandle
- CHECK(mDrmManagerClient);
- mDrmManagerClient->closeDecryptSession(mDecryptHandle);
- mDecryptHandle = NULL;
- }
-
- if (mDrmManagerClient != NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
- }
-}
-
-status_t NuHTTPDataSource::connect(
- const char *uri,
- const KeyedVector<String8, String8> *overrides,
- off64_t offset) {
- String8 headers;
- MakeFullHeaders(overrides, &headers);
-
- return connect(uri, headers, offset);
-}
-
-status_t NuHTTPDataSource::connect(
- const char *uri,
- const String8 &headers,
- off64_t offset) {
- String8 host, path;
- unsigned port;
-
- mUri = uri;
- mContentType = String8("application/octet-stream");
-
- bool https;
- if (!ParseURL(uri, &host, &port, &path, &https)) {
- return ERROR_MALFORMED;
- }
-
- uid_t uid;
- if (getUID(&uid)) {
- mHTTP.setUID(uid);
- }
-
- return connect(host, port, path, https, headers, offset);
-}
-
-static bool IsRedirectStatusCode(int httpStatus) {
- return httpStatus == 301 || httpStatus == 302
- || httpStatus == 303 || httpStatus == 307;
-}
-
-status_t NuHTTPDataSource::connect(
- const char *host, unsigned port, const char *path,
- bool https,
- const String8 &headers,
- off64_t offset) {
- if (!(mFlags & kFlagIncognito)) {
- LOGI("connect to %s:%u%s @%lld", host, port, path, offset);
- } else {
- LOGI("connect to <URL suppressed> @%lld", offset);
- }
-
- bool needsToReconnect = true;
-
- if (mState == CONNECTED && host == mHost && port == mPort
- && https == mHTTPS && offset == mOffset) {
- if (mContentLengthValid && mOffset == mContentLength) {
- LOGI("Didn't have to reconnect, old one's still good.");
- needsToReconnect = false;
- }
- }
-
- mHost = host;
- mPort = port;
- mPath = path;
- mHTTPS = https;
- mHeaders = headers;
-
- status_t err = OK;
-
- mState = CONNECTING;
-
- if (needsToReconnect) {
- mHTTP.disconnect();
- err = mHTTP.connect(host, port, https);
- }
-
- if (err != OK) {
- mState = DISCONNECTED;
- } else if (mState != CONNECTING) {
- err = UNKNOWN_ERROR;
- } else {
- mState = CONNECTED;
-
- mOffset = offset;
- mContentLength = 0;
- mContentLengthValid = false;
-
- String8 request("GET ");
- request.append(mPath);
- request.append(" HTTP/1.1\r\n");
- request.append("Host: ");
- request.append(mHost);
- if (mPort != 80) {
- request.append(StringPrintf(":%u", mPort).c_str());
- }
- request.append("\r\n");
-
- if (offset != 0) {
- char rangeHeader[128];
- sprintf(rangeHeader, "Range: bytes=%lld-\r\n", offset);
- request.append(rangeHeader);
- }
-
- request.append(mHeaders);
- request.append("\r\n");
-
- int httpStatus;
- if ((err = mHTTP.send(request.string(), request.size())) != OK
- || (err = mHTTP.receive_header(&httpStatus)) != OK) {
- mHTTP.disconnect();
- mState = DISCONNECTED;
- return err;
- }
-
- if (IsRedirectStatusCode(httpStatus)) {
- AString value;
- CHECK(mHTTP.find_header_value("Location", &value));
-
- mState = DISCONNECTED;
-
- mHTTP.disconnect();
-
- return connect(value.c_str(), headers, offset);
- }
-
- if (httpStatus < 200 || httpStatus >= 300) {
- mState = DISCONNECTED;
- mHTTP.disconnect();
-
- return ERROR_IO;
- }
-
- mHasChunkedTransferEncoding = false;
-
- {
- AString value;
- if (mHTTP.find_header_value("Transfer-Encoding", &value)) {
- // We don't currently support any transfer encodings but
- // chunked.
-
- if (!strcasecmp(value.c_str(), "chunked")) {
- LOGI("Chunked transfer encoding applied.");
- mHasChunkedTransferEncoding = true;
- mChunkDataBytesLeft = 0;
- } else {
- mState = DISCONNECTED;
- mHTTP.disconnect();
-
- LOGE("We don't support '%s' transfer encoding.", value.c_str());
-
- return ERROR_UNSUPPORTED;
- }
- }
- }
-
- {
- 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) {
- AString value;
- unsigned long x;
- if (mHTTP.find_header_value(AString("Content-Length"), &value)
- && ParseSingleUnsignedLong(value.c_str(), &x)) {
- mContentLength = (off64_t)x;
- mContentLengthValid = true;
- } else {
- LOGW("Server did not give us the content length!");
- }
- } else {
- if (httpStatus != 206 /* Partial Content */) {
- // We requested a range but the server didn't support that.
- LOGE("We requested a range but the server didn't "
- "support that.");
- return ERROR_UNSUPPORTED;
- }
-
- AString value;
- unsigned long x;
- if (mHTTP.find_header_value(AString("Content-Range"), &value)) {
- const char *slashPos = strchr(value.c_str(), '/');
- if (slashPos != NULL
- && ParseSingleUnsignedLong(slashPos + 1, &x)) {
- mContentLength = x;
- mContentLengthValid = true;
- }
- }
- }
- }
-
- return err;
-}
-
-void NuHTTPDataSource::disconnect() {
- if (mState == CONNECTING || mState == CONNECTED) {
- mHTTP.disconnect();
- }
- mState = DISCONNECTED;
-}
-
-status_t NuHTTPDataSource::initCheck() const {
- return mState == CONNECTED ? OK : NO_INIT;
-}
-
-ssize_t NuHTTPDataSource::internalRead(void *data, size_t size) {
- if (!mHasChunkedTransferEncoding) {
- return mHTTP.receive(data, size);
- }
-
- if (mChunkDataBytesLeft < 0) {
- return 0;
- } else if (mChunkDataBytesLeft == 0) {
- char line[1024];
- status_t err = mHTTP.receive_line(line, sizeof(line));
-
- if (err != OK) {
- return err;
- }
-
- LOGV("line = '%s'", line);
-
- char *end;
- unsigned long n = strtoul(line, &end, 16);
-
- if (end == line || (*end != ';' && *end != '\0')) {
- LOGE("malformed HTTP chunk '%s'", line);
- return ERROR_MALFORMED;
- }
-
- mChunkDataBytesLeft = n;
- LOGV("chunk data size = %lu", n);
-
- if (mChunkDataBytesLeft == 0) {
- mChunkDataBytesLeft = -1;
- return 0;
- }
-
- // fall through
- }
-
- if (size > (size_t)mChunkDataBytesLeft) {
- size = mChunkDataBytesLeft;
- }
-
- ssize_t n = mHTTP.receive(data, size);
-
- if (n < 0) {
- return n;
- }
-
- mChunkDataBytesLeft -= (size_t)n;
-
- if (mChunkDataBytesLeft == 0) {
- char line[1024];
- status_t err = mHTTP.receive_line(line, sizeof(line));
-
- if (err != OK) {
- return err;
- }
-
- if (line[0] != '\0') {
- LOGE("missing HTTP chunk terminator.");
- return ERROR_MALFORMED;
- }
- }
-
- return n;
-}
-
-ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
- LOGV("readAt offset %ld, size %d", offset, size);
-
- Mutex::Autolock autoLock(mLock);
-
- if (offset != mOffset) {
- String8 host = mHost;
- String8 path = mPath;
- String8 headers = mHeaders;
- status_t err = connect(host, mPort, path, mHTTPS, headers, offset);
-
- if (err != OK) {
- return err;
- }
- }
-
- if (mContentLengthValid) {
- size_t avail =
- (offset >= mContentLength) ? 0 : mContentLength - offset;
-
- if (size > avail) {
- size = avail;
- }
- }
-
- size_t numBytesRead = 0;
- while (numBytesRead < size) {
- int64_t startTimeUs = ALooper::GetNowUs();
-
- ssize_t n =
- internalRead((uint8_t *)data + numBytesRead, size - numBytesRead);
-
- if (n < 0) {
- if (numBytesRead == 0 || mContentLengthValid) {
- return n;
- }
-
- // If there was an error we want to at least return the data
- // we've already successfully read. The next call to read will
- // then return the error.
- n = 0;
- }
-
- int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
- addBandwidthMeasurement(n, delayUs);
-
- numBytesRead += (size_t)n;
-
- if (n == 0) {
- if (mContentLengthValid) {
- // We know the content length and made sure not to read beyond
- // it and yet the server closed the connection on us.
- return ERROR_IO;
- }
-
- break;
- }
- }
-
- mOffset += numBytesRead;
-
- return numBytesRead;
-}
-
-status_t NuHTTPDataSource::getSize(off64_t *size) {
- *size = 0;
-
- if (mState != CONNECTED) {
- return ERROR_IO;
- }
-
- if (mContentLengthValid) {
- *size = mContentLength;
- return OK;
- }
-
- return ERROR_UNSUPPORTED;
-}
-
-uint32_t NuHTTPDataSource::flags() {
- return kWantsPrefetching | kIsHTTPBasedSource;
-}
-
-// static
-void NuHTTPDataSource::MakeFullHeaders(
- const KeyedVector<String8, String8> *overrides, String8 *headers) {
- headers->setTo("");
-
- headers->append("User-Agent: stagefright/1.1 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.build.version.release", value, "Unknown");
- headers->append(value);
- headers->append(")\r\n");
-
- if (overrides == NULL) {
- return;
- }
-
- for (size_t i = 0; i < overrides->size(); ++i) {
- String8 line;
- line.append(overrides->keyAt(i));
- line.append(": ");
- line.append(overrides->valueAt(i));
- line.append("\r\n");
-
- headers->append(line);
- }
-}
-
-void NuHTTPDataSource::applyTimeoutResponse() {
- AString timeout;
- if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) {
- const char *s = timeout.c_str();
- char *end;
- long tmp = strtol(s, &end, 10);
- if (end == s || *end != '\0') {
- LOGW("Illegal X-SocketTimeout value given.");
- return;
- }
-
- LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
- mHTTP.setReceiveTimeout(tmp);
- }
-}
-
-sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
- if (mDrmManagerClient == NULL) {
- mDrmManagerClient = new DrmManagerClient();
- }
-
- if (mDrmManagerClient == NULL) {
- return NULL;
- }
-
- if (mDecryptHandle == NULL) {
- /* Note if redirect occurs, mUri is the redirect uri instead of the
- * original one
- */
- mDecryptHandle = mDrmManagerClient->openDecryptSession(mUri);
- }
-
- if (mDecryptHandle == NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
- }
-
- return mDecryptHandle;
-}
-
-void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
- handle = mDecryptHandle;
-
- *client = mDrmManagerClient;
-}
-
-String8 NuHTTPDataSource::getUri() {
- return mUri;
-}
-
-String8 NuHTTPDataSource::getMIMEType() const {
- return mContentType;
-}
-
-} // namespace android
diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
deleted file mode 100644
index 783f2d0..0000000
--- a/media/libstagefright/ShoutcastSource.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "include/HTTPStream.h"
-
-#include <stdlib.h>
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/ShoutcastSource.h>
-
-namespace android {
-
-ShoutcastSource::ShoutcastSource(HTTPStream *http)
- : mHttp(http),
- mMetaDataOffset(0),
- mBytesUntilMetaData(0),
- mGroup(NULL),
- mStarted(false) {
- AString metaint;
- if (mHttp->find_header_value("icy-metaint", &metaint)) {
- char *end;
- const char *start = metaint.c_str();
- mMetaDataOffset = strtol(start, &end, 10);
- CHECK(end > start && *end == '\0');
- CHECK(mMetaDataOffset > 0);
-
- mBytesUntilMetaData = mMetaDataOffset;
- }
-}
-
-ShoutcastSource::~ShoutcastSource() {
- if (mStarted) {
- stop();
- }
-
- delete mHttp;
- mHttp = NULL;
-}
-
-status_t ShoutcastSource::start(MetaData *) {
- CHECK(!mStarted);
-
- mGroup = new MediaBufferGroup;
- mGroup->add_buffer(new MediaBuffer(4096)); // XXX
-
- mStarted = true;
-
- return OK;
-}
-
-status_t ShoutcastSource::stop() {
- CHECK(mStarted);
-
- delete mGroup;
- mGroup = NULL;
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> ShoutcastSource::getFormat() {
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
- meta->setInt32(kKeySampleRate, 44100);
- meta->setInt32(kKeyChannelCount, 2); // XXX
-
- return meta;
-}
-
-status_t ShoutcastSource::read(
- MediaBuffer **out, const ReadOptions *options) {
- CHECK(mStarted);
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- return ERROR_UNSUPPORTED;
- }
-
- MediaBuffer *buffer;
- status_t err = mGroup->acquire_buffer(&buffer);
- if (err != OK) {
- return err;
- }
-
- *out = buffer;
-
- size_t num_bytes = buffer->size();
- if (mMetaDataOffset > 0 && num_bytes > mBytesUntilMetaData) {
- num_bytes = mBytesUntilMetaData;
- }
-
- ssize_t n = mHttp->receive(buffer->data(), num_bytes);
-
- if (n <= 0) {
- return (status_t)n;
- }
-
- buffer->set_range(0, n);
-
- mBytesUntilMetaData -= (size_t)n;
-
- if (mBytesUntilMetaData == 0) {
- unsigned char num_16_byte_blocks = 0;
- n = mHttp->receive((char *)&num_16_byte_blocks, 1);
- CHECK_EQ(n, 1);
-
- char meta[255 * 16];
- size_t meta_size = num_16_byte_blocks * 16;
- size_t meta_length = 0;
- while (meta_length < meta_size) {
- n = mHttp->receive(&meta[meta_length], meta_size - meta_length);
- if (n <= 0) {
- return (status_t)n;
- }
-
- meta_length += (size_t) n;
- }
-
- while (meta_length > 0 && meta[meta_length - 1] == '\0') {
- --meta_length;
- }
-
- if (meta_length > 0) {
- // Technically we should probably attach this meta data to the
- // next buffer. XXX
- buffer->meta_data()->setData('shou', 'shou', meta, meta_length);
- }
-
- mBytesUntilMetaData = mMetaDataOffset;
- }
-
- return OK;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 2e25dd9..0e9af69 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -53,6 +53,8 @@ struct HTTPBase : public DataSource {
static sp<HTTPBase> Create(uint32_t flags = 0);
+ static void RegisterSocketUser(int s, uid_t uid);
+
protected:
void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
deleted file mode 100644
index 88ba9d6..0000000
--- a/media/libstagefright/include/HTTPStream.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HTTP_STREAM_H_
-
-#define HTTP_STREAM_H_
-
-#include <sys/types.h>
-
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class HTTPStream {
-public:
- HTTPStream();
- ~HTTPStream();
-
- void setUID(uid_t uid);
-
- status_t connect(const char *server, int port = -1, bool https = false);
- status_t disconnect();
-
- status_t send(const char *data, size_t size);
-
- // Assumes data is a '\0' terminated string.
- status_t send(const char *data);
-
- // Receive up to "size" bytes of data.
- ssize_t receive(void *data, size_t size);
-
- status_t receive_header(int *http_status);
-
- // The header key used to retrieve the status line.
- static const char *kStatusKey;
-
- bool find_header_value(
- const AString &key, AString *value) const;
-
- // Pass a negative value to disable the timeout.
- void setReceiveTimeout(int seconds);
-
- // Receive a line of data terminated by CRLF, line will be '\0' terminated
- // _excluding_ the termianting CRLF.
- status_t receive_line(char *line, size_t size);
-
- static void RegisterSocketUser(int s, uid_t uid);
-
-private:
- enum State {
- READY,
- CONNECTING,
- CONNECTED
- };
-
- State mState;
- Mutex mLock;
-
- bool mUIDValid;
- uid_t mUID;
-
- int mSocket;
-
- KeyedVector<AString, AString> mHeaders;
-
- void *mSSLContext;
- void *mSSL;
-
- HTTPStream(const HTTPStream &);
- HTTPStream &operator=(const HTTPStream &);
-};
-
-} // namespace android
-
-#endif // HTTP_STREAM_H_
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
deleted file mode 100644
index c265b3a..0000000
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NU_HTTP_DATA_SOURCE_H_
-
-#define NU_HTTP_DATA_SOURCE_H_
-
-#include <utils/List.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-
-#include "HTTPStream.h"
-#include "include/HTTPBase.h"
-
-namespace android {
-
-struct NuHTTPDataSource : public HTTPBase {
- NuHTTPDataSource(uint32_t flags = 0);
-
- virtual status_t connect(
- const char *uri,
- const KeyedVector<String8, String8> *headers = NULL,
- off64_t offset = 0);
-
- virtual void disconnect();
-
- virtual status_t initCheck() const;
-
- virtual ssize_t readAt(off64_t offset, void *data, size_t size);
- virtual status_t getSize(off64_t *size);
- virtual uint32_t flags();
-
- virtual sp<DecryptHandle> DrmInitialization();
- virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
- virtual String8 getUri();
-
- virtual String8 getMIMEType() const;
-
-protected:
- virtual ~NuHTTPDataSource();
-
-private:
- enum State {
- DISCONNECTED,
- CONNECTING,
- CONNECTED
- };
-
- Mutex mLock;
-
- uint32_t mFlags;
-
- State mState;
-
- String8 mHost;
- unsigned mPort;
- String8 mPath;
- bool mHTTPS;
- String8 mHeaders;
- String8 mUri;
-
- HTTPStream mHTTP;
- off64_t mOffset;
- off64_t mContentLength;
- 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;
-
- sp<DecryptHandle> mDecryptHandle;
- DrmManagerClient *mDrmManagerClient;
-
- status_t connect(
- const char *uri, const String8 &headers, off64_t offset);
-
- status_t connect(
- const char *host, unsigned port, const char *path,
- bool https,
- const String8 &headers,
- off64_t offset);
-
- // Read up to "size" bytes of data, respect transfer encoding.
- ssize_t internalRead(void *data, size_t size);
-
- void applyTimeoutResponse();
-
- static void MakeFullHeaders(
- const KeyedVector<String8, String8> *overrides,
- String8 *headers);
-
- NuHTTPDataSource(const NuHTTPDataSource &);
- NuHTTPDataSource &operator=(const NuHTTPDataSource &);
-};
-
-} // namespace android
-
-#endif // NU_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 072d6b2..b398c9d 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -34,7 +34,7 @@
#include <openssl/md5.h>
#include <sys/socket.h>
-#include "HTTPStream.h"
+#include "HTTPBase.h"
namespace android {
@@ -251,7 +251,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
mSocket = socket(AF_INET, SOCK_STREAM, 0);
if (mUIDValid) {
- HTTPStream::RegisterSocketUser(mSocket, mUID);
+ HTTPBase::RegisterSocketUser(mSocket, mUID);
}
MakeSocketBlocking(mSocket, false);
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 3188959..71d68f6 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -40,7 +40,7 @@
#include <sys/socket.h>
#include <netdb.h>
-#include "HTTPStream.h"
+#include "HTTPBase.h"
// If no access units are received within 5 secs, assume that the rtp
// stream has ended and signal end of stream.
@@ -1181,8 +1181,8 @@ private:
&info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
if (mUIDValid) {
- HTTPStream::RegisterSocketUser(info->mRTPSocket, mUID);
- HTTPStream::RegisterSocketUser(info->mRTCPSocket, mUID);
+ HTTPBase::RegisterSocketUser(info->mRTPSocket, mUID);
+ HTTPBase::RegisterSocketUser(info->mRTCPSocket, mUID);
}
request.append("Transport: RTP/AVP/UDP;unicast;client_port=");