Loading media/libstagefright/NuHTTPDataSource.cpp +102 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,9 @@ NuHTTPDataSource::NuHTTPDataSource() mPort(0), mOffset(0), mContentLength(0), mContentLengthValid(false) { mContentLengthValid(false), mHasChunkedTransferEncoding(false), mChunkDataBytesLeft(0) { } NuHTTPDataSource::~NuHTTPDataSource() { Loading Loading @@ -184,6 +186,30 @@ status_t NuHTTPDataSource::connect( return ERROR_IO; } mHasChunkedTransferEncoding = false; { string value; if (mHTTP.find_header_value("Transfer-Encoding", &value) || 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; } } } applyTimeoutResponse(); if (offset == 0) { Loading @@ -193,8 +219,17 @@ status_t NuHTTPDataSource::connect( && ParseSingleUnsignedLong(value.c_str(), &x)) { mContentLength = (off_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; } string value; unsigned long x; if (mHTTP.find_header_value(string("Content-Range"), &value)) { Loading Loading @@ -222,6 +257,71 @@ 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(off_t offset, void *data, size_t size) { LOGV("readAt offset %ld, size %d", offset, size); Loading Loading @@ -250,7 +350,7 @@ ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) { size_t numBytesRead = 0; while (numBytesRead < size) { ssize_t n = mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead); internalRead((uint8_t *)data + numBytesRead, size - numBytesRead); if (n < 0) { return n; Loading media/libstagefright/httplive/LiveSource.cpp +28 −7 Original line number Diff line number Diff line Loading @@ -318,20 +318,41 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) { status_t err = source->getSize(&size); if (err != OK) { return err; size = 65536; } sp<ABuffer> buffer = new ABuffer(size); size_t offset = 0; while (offset < (size_t)size) { buffer->setRange(0, 0); for (;;) { size_t bufferRemaining = buffer->capacity() - buffer->size(); if (bufferRemaining == 0) { bufferRemaining = 32768; LOGV("increasing download buffer to %d bytes", buffer->size() + bufferRemaining); sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining); memcpy(copy->data(), buffer->data(), buffer->size()); copy->setRange(0, buffer->size()); buffer = copy; } ssize_t n = source->readAt( offset, buffer->data() + offset, size - offset); buffer->size(), buffer->data() + buffer->size(), bufferRemaining); if (n <= 0) { return ERROR_IO; if (n < 0) { return err; } if (n == 0) { break; } offset += n; buffer->setRange(0, buffer->size() + (size_t)n); } *out = buffer; Loading media/libstagefright/include/HTTPStream.h +4 −4 Original line number Diff line number Diff line Loading @@ -55,6 +55,10 @@ public: // 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); private: enum State { READY, Loading @@ -68,10 +72,6 @@ private: KeyedVector<string, string> mHeaders; // 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); HTTPStream(const HTTPStream &); HTTPStream &operator=(const HTTPStream &); }; Loading media/libstagefright/include/NuHTTPDataSource.h +8 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,11 @@ private: off_t mOffset; off_t mContentLength; bool mContentLengthValid; bool mHasChunkedTransferEncoding; // The number of data bytes in the current chunk before any subsequent // chunk header (or -1 if no more chunks). ssize_t mChunkDataBytesLeft; status_t connect( const char *uri, const String8 &headers, off_t offset); Loading @@ -58,6 +63,9 @@ private: const String8 &headers, off_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( Loading Loading
media/libstagefright/NuHTTPDataSource.cpp +102 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,9 @@ NuHTTPDataSource::NuHTTPDataSource() mPort(0), mOffset(0), mContentLength(0), mContentLengthValid(false) { mContentLengthValid(false), mHasChunkedTransferEncoding(false), mChunkDataBytesLeft(0) { } NuHTTPDataSource::~NuHTTPDataSource() { Loading Loading @@ -184,6 +186,30 @@ status_t NuHTTPDataSource::connect( return ERROR_IO; } mHasChunkedTransferEncoding = false; { string value; if (mHTTP.find_header_value("Transfer-Encoding", &value) || 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; } } } applyTimeoutResponse(); if (offset == 0) { Loading @@ -193,8 +219,17 @@ status_t NuHTTPDataSource::connect( && ParseSingleUnsignedLong(value.c_str(), &x)) { mContentLength = (off_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; } string value; unsigned long x; if (mHTTP.find_header_value(string("Content-Range"), &value)) { Loading Loading @@ -222,6 +257,71 @@ 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(off_t offset, void *data, size_t size) { LOGV("readAt offset %ld, size %d", offset, size); Loading Loading @@ -250,7 +350,7 @@ ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) { size_t numBytesRead = 0; while (numBytesRead < size) { ssize_t n = mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead); internalRead((uint8_t *)data + numBytesRead, size - numBytesRead); if (n < 0) { return n; Loading
media/libstagefright/httplive/LiveSource.cpp +28 −7 Original line number Diff line number Diff line Loading @@ -318,20 +318,41 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) { status_t err = source->getSize(&size); if (err != OK) { return err; size = 65536; } sp<ABuffer> buffer = new ABuffer(size); size_t offset = 0; while (offset < (size_t)size) { buffer->setRange(0, 0); for (;;) { size_t bufferRemaining = buffer->capacity() - buffer->size(); if (bufferRemaining == 0) { bufferRemaining = 32768; LOGV("increasing download buffer to %d bytes", buffer->size() + bufferRemaining); sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining); memcpy(copy->data(), buffer->data(), buffer->size()); copy->setRange(0, buffer->size()); buffer = copy; } ssize_t n = source->readAt( offset, buffer->data() + offset, size - offset); buffer->size(), buffer->data() + buffer->size(), bufferRemaining); if (n <= 0) { return ERROR_IO; if (n < 0) { return err; } if (n == 0) { break; } offset += n; buffer->setRange(0, buffer->size() + (size_t)n); } *out = buffer; Loading
media/libstagefright/include/HTTPStream.h +4 −4 Original line number Diff line number Diff line Loading @@ -55,6 +55,10 @@ public: // 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); private: enum State { READY, Loading @@ -68,10 +72,6 @@ private: KeyedVector<string, string> mHeaders; // 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); HTTPStream(const HTTPStream &); HTTPStream &operator=(const HTTPStream &); }; Loading
media/libstagefright/include/NuHTTPDataSource.h +8 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,11 @@ private: off_t mOffset; off_t mContentLength; bool mContentLengthValid; bool mHasChunkedTransferEncoding; // The number of data bytes in the current chunk before any subsequent // chunk header (or -1 if no more chunks). ssize_t mChunkDataBytesLeft; status_t connect( const char *uri, const String8 &headers, off_t offset); Loading @@ -58,6 +63,9 @@ private: const String8 &headers, off_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( Loading