Support the specification of additional HTTP headers in the creation of a DataSource.

related-to-bug: 2393577
This commit is contained in:
Andreas Huber
2010-01-27 16:49:05 -08:00
parent 2fd75f3515
commit 433c9acaf7
10 changed files with 77 additions and 39 deletions

View File

@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
@@ -35,7 +36,9 @@ public:
kWantsPrefetching = 1,
};
static sp<DataSource> CreateFromURI(const char *uri);
static sp<DataSource> CreateFromURI(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
DataSource() {}

View File

@@ -19,6 +19,7 @@
#define HTTP_DATASOURCE_H_
#include <media/stagefright/DataSource.h>
#include <utils/String8.h>
namespace android {
@@ -26,8 +27,13 @@ class HTTPStream;
class HTTPDataSource : public DataSource {
public:
HTTPDataSource(const char *host, int port, const char *path);
HTTPDataSource(const char *uri);
HTTPDataSource(
const char *host, int port, const char *path,
const KeyedVector<String8, String8> *headers = NULL);
HTTPDataSource(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
virtual status_t initCheck() const;
@@ -45,6 +51,8 @@ private:
kBufferSize = 64 * 1024
};
String8 mHeaders;
HTTPStream *mHttp;
char *mHost;
int mPort;
@@ -58,6 +66,7 @@ private:
status_t mInitCheck;
ssize_t sendRangeRequest(size_t offset);
void initHeaders(const KeyedVector<String8, String8> *overrides);
HTTPDataSource(const HTTPDataSource &);
HTTPDataSource &operator=(const HTTPDataSource &);

View File

@@ -31,9 +31,6 @@ public:
static sp<MediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
static sp<MediaExtractor> CreateFromURI(
const char *uri, const char *mime = NULL);
virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;

View File

@@ -29,9 +29,9 @@ status_t StagefrightPlayer::initCheck() {
}
status_t StagefrightPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *) {
const char *url, const KeyedVector<String8, String8> *headers) {
LOGI("setDataSource('%s')", url);
return mPlayer->setDataSource(url);
return mPlayer->setDataSource(url, headers);
}
// Warning: The filedescriptor passed into this method will only be valid until

View File

@@ -152,12 +152,13 @@ void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
mListener = listener;
}
status_t AwesomePlayer::setDataSource(const char *uri) {
status_t AwesomePlayer::setDataSource(
const char *uri, const KeyedVector<String8, String8> *headers) {
Mutex::Autolock autoLock(mLock);
reset_l();
sp<DataSource> dataSource = DataSource::CreateFromURI(uri);
sp<DataSource> dataSource = DataSource::CreateFromURI(uri, headers);
if (dataSource == NULL) {
return UNKNOWN_ERROR;

View File

@@ -95,12 +95,13 @@ void DataSource::RegisterDefaultSniffers() {
}
// static
sp<DataSource> DataSource::CreateFromURI(const char *uri) {
sp<DataSource> DataSource::CreateFromURI(
const char *uri, const KeyedVector<String8, String8> *headers) {
sp<DataSource> source;
if (!strncasecmp("file://", uri, 7)) {
source = new FileSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)) {
source = new HTTPDataSource(uri);
source = new HTTPDataSource(uri, headers);
source = new CachingDataSource(source, 64 * 1024, 10);
} else {
// Assume it's a filename.

View File

@@ -31,14 +31,13 @@ static const char *kUserAgent = "stagefright-http";
// accordingly and return true, otherwise return false and leave the stream
// connected.
static bool PerformRedirectIfNecessary(
HTTPStream *http, string *host, string *path, int *port) {
HTTPStream *http, const String8 &headers,
string *host, string *path, int *port) {
String8 request;
request.append("HEAD ");
request.append(path->c_str());
request.append(" HTTP/1.1\r\n");
request.append("User-Agent: ");
request.append(kUserAgent);
request.append("\r\n");
request.append(headers);
request.append("Host: ");
request.append(host->c_str());
request.append("\r\n\r\n");
@@ -94,7 +93,8 @@ static bool PerformRedirectIfNecessary(
return true;
}
HTTPDataSource::HTTPDataSource(const char *uri)
HTTPDataSource::HTTPDataSource(
const char *uri, const KeyedVector<String8, String8> *headers)
: mHttp(new HTTPStream),
mHost(NULL),
mPort(0),
@@ -105,6 +105,8 @@ HTTPDataSource::HTTPDataSource(const char *uri)
mFirstRequest(true) {
CHECK(!strncasecmp("http://", uri, 7));
initHeaders(headers);
string host;
string path;
int port;
@@ -140,14 +142,16 @@ HTTPDataSource::HTTPDataSource(const char *uri)
if (mInitCheck != OK) {
return;
}
} while (PerformRedirectIfNecessary(mHttp, &host, &path, &port));
} while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port));
mHost = strdup(host.c_str());
mPort = port;
mPath = strdup(path.c_str());
}
HTTPDataSource::HTTPDataSource(const char *_host, int port, const char *_path)
HTTPDataSource::HTTPDataSource(
const char *_host, int port, const char *_path,
const KeyedVector<String8, String8> *headers)
: mHttp(new HTTPStream),
mHost(NULL),
mPort(0),
@@ -156,6 +160,8 @@ HTTPDataSource::HTTPDataSource(const char *_host, int port, const char *_path)
mBufferLength(0),
mBufferOffset(0),
mFirstRequest(true) {
initHeaders(headers);
string host = _host;
string path = _path;
@@ -168,7 +174,7 @@ HTTPDataSource::HTTPDataSource(const char *_host, int port, const char *_path)
if (mInitCheck != OK) {
return;
}
} while (PerformRedirectIfNecessary(mHttp, &host, &path, &port));
} while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port));
mHost = strdup(host.c_str());
mPort = port;
@@ -200,9 +206,6 @@ HTTPDataSource::~HTTPDataSource() {
}
ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
char agent[128];
sprintf(agent, "User-Agent: %s\r\n", kUserAgent);
char host[128];
sprintf(host, "Host: %s\r\n", mHost);
@@ -221,7 +224,7 @@ ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
if ((err = mHttp->send("GET ")) != OK
|| (err = mHttp->send(mPath)) != OK
|| (err = mHttp->send(" HTTP/1.1\r\n")) != OK
|| (err = mHttp->send(agent)) != OK
|| (err = mHttp->send(mHeaders.string())) != OK
|| (err = mHttp->send(host)) != OK
|| (err = mHttp->send(range)) != OK
|| (err = mHttp->send("\r\n")) != OK
@@ -304,5 +307,28 @@ ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
return copy;
}
void HTTPDataSource::initHeaders(
const KeyedVector<String8, String8> *overrides) {
mHeaders = String8();
mHeaders.append("User-Agent: ");
mHeaders.append(kUserAgent);
mHeaders.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");
mHeaders.append(line);
}
}
} // namespace android

View File

@@ -67,16 +67,4 @@ sp<MediaExtractor> MediaExtractor::Create(
return NULL;
}
// static
sp<MediaExtractor> MediaExtractor::CreateFromURI(
const char *uri, const char *mime) {
sp<DataSource> source = DataSource::CreateFromURI(uri);
if (source == NULL || source->initCheck() != OK) {
return NULL;
}
return Create(source, mime);
}
} // namespace android

View File

@@ -49,7 +49,10 @@ struct AwesomePlayer {
void setListener(const wp<MediaPlayerBase> &listener);
status_t setDataSource(const char *uri);
status_t setDataSource(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
status_t setDataSource(int fd, int64_t offset, int64_t length);
void reset();

View File

@@ -245,10 +245,20 @@ private:
NodeReaper &operator=(const NodeReaper &);
};
static sp<MediaExtractor> CreateExtractorFromURI(const char *uri) {
sp<DataSource> source = DataSource::CreateFromURI(uri);
if (source == NULL) {
return NULL;
}
return MediaExtractor::Create(source);
}
static sp<MediaSource> MakeSource(
const char *uri,
const char *mimeType) {
sp<MediaExtractor> extractor = MediaExtractor::CreateFromURI(uri);
sp<MediaExtractor> extractor = CreateExtractorFromURI(uri);
if (extractor == NULL) {
return NULL;
@@ -500,7 +510,7 @@ static sp<MediaSource> CreateSourceForMime(const char *mime) {
const char *url = GetURLForMime(mime);
CHECK(url != NULL);
sp<MediaExtractor> extractor = MediaExtractor::CreateFromURI(url);
sp<MediaExtractor> extractor = CreateExtractorFromURI(url);
CHECK(extractor != NULL);