Merge "implement [2396050] Add ETC1 texture support to AGL"
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 25a90bf..98ebc48 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -63,7 +63,6 @@
void *mBuffer;
size_t mBufferLength;
off_t mBufferOffset;
- bool mFirstRequest;
bool mContentLengthValid;
unsigned long long mContentLength;
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index bb3b43c..4b630b9 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -34,7 +34,7 @@
HTTPStream *http, const String8 &headers,
string *host, string *path, int *port) {
String8 request;
- request.append("HEAD ");
+ request.append("GET ");
request.append(path->c_str());
request.append(" HTTP/1.1\r\n");
request.append(headers);
@@ -142,7 +142,6 @@
mBuffer = malloc(kBufferSize);
mBufferLength = 0;
mBufferOffset = 0;
- mFirstRequest = true;
mContentLengthValid = false;
initHeaders(headers);
@@ -153,13 +152,15 @@
LOGI("Connecting to host '%s', port %d, path '%s'",
host.c_str(), port, path.c_str());
+ int numRedirectsRemaining = 5;
do {
mInitCheck = mHttp->connect(host.c_str(), port);
if (mInitCheck != OK) {
return;
}
- } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port));
+ } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
+ && numRedirectsRemaining-- > 0);
string value;
if (mHttp->find_header_value("Content-Length", &value)) {
@@ -280,14 +281,11 @@
}
ssize_t contentLength = 0;
- if (mFirstRequest || offset != (off_t)(mBufferOffset + mBufferLength)) {
- if (!mFirstRequest) {
- LOGV("new range offset=%ld (old=%ld)",
- offset, mBufferOffset + mBufferLength);
+ if (offset != (off_t)(mBufferOffset + mBufferLength)) {
+ LOGV("new range offset=%ld (old=%ld)",
+ offset, mBufferOffset + mBufferLength);
- mHttp->disconnect();
- }
- mFirstRequest = false;
+ mHttp->disconnect();
contentLength = sendRangeRequest(offset);
@@ -306,6 +304,12 @@
ssize_t num_bytes_received = mHttp->receive(mBuffer, contentLength);
+ if (num_bytes_received < 0) {
+ mBufferLength = 0;
+
+ return num_bytes_received;
+ }
+
mBufferLength = (size_t)num_bytes_received;
size_t copy = mBufferLength;
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 02f9439..3711aca 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -52,7 +52,7 @@
CHECK_EQ(mSocket, -1);
mSocket = socket(AF_INET, SOCK_STREAM, 0);
-
+
if (mSocket < 0) {
return UNKNOWN_ERROR;
}
@@ -132,6 +132,14 @@
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 0
+
status_t HTTPStream::receive_line(char *line, size_t size) {
if (mState != CONNECTED) {
return ERROR_NOT_CONNECTED;
@@ -157,16 +165,27 @@
return ERROR_CONNECTION_LOST;
}
- if (saw_CR && c == '\n') {
+#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');
- CHECK(length + 1 < size);
+ if (length + 1 >= size) {
+ return ERROR_MALFORMED;
+ }
line[length++] = c;
}
}
@@ -175,7 +194,7 @@
*http_status = -1;
mHeaders.clear();
- char line[1024];
+ char line[2048];
status_t err = receive_line(line, sizeof(line));
if (err != OK) {
return err;
@@ -257,11 +276,11 @@
}
disconnect();
- return ERROR_IO;
+ return total == 0 ? ERROR_IO : total;
} else if (n == 0) {
disconnect();
- return ERROR_CONNECTION_LOST;
+ return total == 0 ? ERROR_CONNECTION_LOST : total;
}
total += (size_t)n;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index aee4d15..2cf0ddf 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -38,7 +38,7 @@
void stop();
bool reachedEOS();
- int64_t getDuration() const;
+ int64_t getDurationUs() const;
void writeTrackHeader(int32_t trackID);
private:
@@ -46,6 +46,7 @@
sp<MetaData> mMeta;
sp<MediaSource> mSource;
volatile bool mDone;
+ int64_t mMaxTimeStampUs;
pthread_t mThread;
@@ -140,7 +141,7 @@
it != mTracks.end(); ++it) {
(*it)->stop();
- int64_t duration = (*it)->getDuration();
+ int64_t duration = (*it)->getDurationUs();
if (duration > max_duration) {
max_duration = duration;
}
@@ -162,7 +163,7 @@
writeInt32(now); // creation time
writeInt32(now); // modification time
writeInt32(1000); // timescale
- writeInt32(max_duration);
+ writeInt32(max_duration / 1000);
writeInt32(0x10000); // rate
writeInt16(0x100); // volume
writeInt16(0); // reserved
@@ -316,6 +317,7 @@
mMeta(source->getFormat()),
mSource(source),
mDone(false),
+ mMaxTimeStampUs(0),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mReachedEOS(false) {
@@ -343,6 +345,7 @@
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
mDone = false;
+ mMaxTimeStampUs = 0;
mReachedEOS = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
@@ -483,6 +486,10 @@
int64_t timestampUs;
CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs));
+ if (timestampUs > mMaxTimeStampUs) {
+ mMaxTimeStampUs = timestampUs;
+ }
+
// Our timestamp is in ms.
info.timestamp = (timestampUs + 500) / 1000;
@@ -495,8 +502,8 @@
mReachedEOS = true;
}
-int64_t MPEG4Writer::Track::getDuration() const {
- return 10000; // XXX
+int64_t MPEG4Writer::Track::getDurationUs() const {
+ return mMaxTimeStampUs;
}
void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
@@ -516,7 +523,7 @@
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(trackID);
mOwner->writeInt32(0); // reserved
- mOwner->writeInt32(getDuration());
+ mOwner->writeInt32(getDurationUs() / 1000);
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // layer
@@ -555,7 +562,7 @@
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(1000); // timescale
- mOwner->writeInt32(getDuration());
+ mOwner->writeInt32(getDurationUs() / 1000);
mOwner->writeInt16(0); // language code XXX
mOwner->writeInt16(0); // predefined
mOwner->endBox();