Loading media/libstagefright/httplive/LiveSession.cpp +36 −5 Original line number Diff line number Diff line Loading @@ -215,7 +215,9 @@ void LiveSession::onDisconnect() { mDisconnectPending = false; } status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { status_t LiveSession::fetchFile( const char *url, sp<ABuffer> *out, int64_t range_offset, int64_t range_length) { *out = NULL; sp<DataSource> source; Loading @@ -234,8 +236,18 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { } } status_t err = mHTTPDataSource->connect( url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders); KeyedVector<String8, String8> headers = mExtraHeaders; if (range_offset > 0 || range_length >= 0) { headers.add( String8("Range"), String8( StringPrintf( "bytes=%lld-%s", range_offset, range_length < 0 ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str())); } status_t err = mHTTPDataSource->connect(url, &headers); if (err != OK) { return err; Loading Loading @@ -270,9 +282,21 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { buffer = copy; } size_t maxBytesToRead = bufferRemaining; if (range_length >= 0) { int64_t bytesLeftInRange = range_length - buffer->size(); if (bytesLeftInRange < maxBytesToRead) { maxBytesToRead = bytesLeftInRange; if (bytesLeftInRange == 0) { break; } } } ssize_t n = source->readAt( buffer->size(), buffer->data() + buffer->size(), bufferRemaining); maxBytesToRead); if (n < 0) { return n; Loading Loading @@ -659,8 +683,15 @@ rinse_repeat: explicitDiscontinuity = true; } int64_t range_offset, range_length; if (!itemMeta->findInt64("range-offset", &range_offset) || !itemMeta->findInt64("range-length", &range_length)) { range_offset = 0; range_length = -1; } sp<ABuffer> buffer; status_t err = fetchFile(uri.c_str(), &buffer); status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length); if (err != OK) { LOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); mDataSource->queueEOS(err); Loading media/libstagefright/httplive/M3UParser.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ status_t M3UParser::parse(const void *_data, size_t size) { const char *data = (const char *)_data; size_t offset = 0; uint64_t segmentRangeOffset = 0; while (offset < size) { size_t offsetLF = offset; while (offsetLF < size && data[offsetLF] != '\n') { Loading Loading @@ -218,6 +219,24 @@ status_t M3UParser::parse(const void *_data, size_t size) { } mIsVariantPlaylist = true; err = parseStreamInf(line, &itemMeta); } else if (line.startsWith("#EXT-X-BYTERANGE")) { if (mIsVariantPlaylist) { return ERROR_MALFORMED; } uint64_t length, offset; err = parseByteRange(line, segmentRangeOffset, &length, &offset); if (err == OK) { if (itemMeta == NULL) { itemMeta = new AMessage; } itemMeta->setInt64("range-offset", offset); itemMeta->setInt64("range-length", length); segmentRangeOffset = offset + length; } } if (err != OK) { Loading Loading @@ -446,6 +465,52 @@ status_t M3UParser::parseCipherInfo( return OK; } // static status_t M3UParser::parseByteRange( const AString &line, uint64_t curOffset, uint64_t *length, uint64_t *offset) { ssize_t colonPos = line.find(":"); if (colonPos < 0) { return ERROR_MALFORMED; } ssize_t atPos = line.find("@", colonPos + 1); AString lenStr; if (atPos < 0) { lenStr = AString(line, colonPos + 1, line.size() - colonPos - 1); } else { lenStr = AString(line, colonPos + 1, atPos - colonPos - 1); } lenStr.trim(); const char *s = lenStr.c_str(); char *end; *length = strtoull(s, &end, 10); if (s == end || *end != '\0') { return ERROR_MALFORMED; } if (atPos >= 0) { AString offStr = AString(line, atPos + 1, line.size() - atPos - 1); offStr.trim(); const char *s = offStr.c_str(); *offset = strtoull(s, &end, 10); if (s == end || *end != '\0') { return ERROR_MALFORMED; } } else { *offset = curOffset; } return OK; } // static status_t M3UParser::ParseInt32(const char *s, int32_t *x) { char *end; Loading media/libstagefright/include/LiveSession.h +4 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,10 @@ private: void onMonitorQueue(); void onSeek(const sp<AMessage> &msg); status_t fetchFile(const char *url, sp<ABuffer> *out); status_t fetchFile( const char *url, sp<ABuffer> *out, int64_t range_offset = 0, int64_t range_length = -1); sp<M3UParser> fetchPlaylist(const char *url, bool *unchanged); size_t getBandwidthIndex(); Loading media/libstagefright/include/M3UParser.h +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ private: static status_t parseCipherInfo( const AString &line, sp<AMessage> *meta, const AString &baseURI); static status_t parseByteRange( const AString &line, uint64_t curOffset, uint64_t *length, uint64_t *offset); static status_t ParseInt32(const char *s, int32_t *x); static status_t ParseDouble(const char *s, double *x); Loading Loading
media/libstagefright/httplive/LiveSession.cpp +36 −5 Original line number Diff line number Diff line Loading @@ -215,7 +215,9 @@ void LiveSession::onDisconnect() { mDisconnectPending = false; } status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { status_t LiveSession::fetchFile( const char *url, sp<ABuffer> *out, int64_t range_offset, int64_t range_length) { *out = NULL; sp<DataSource> source; Loading @@ -234,8 +236,18 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { } } status_t err = mHTTPDataSource->connect( url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders); KeyedVector<String8, String8> headers = mExtraHeaders; if (range_offset > 0 || range_length >= 0) { headers.add( String8("Range"), String8( StringPrintf( "bytes=%lld-%s", range_offset, range_length < 0 ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str())); } status_t err = mHTTPDataSource->connect(url, &headers); if (err != OK) { return err; Loading Loading @@ -270,9 +282,21 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { buffer = copy; } size_t maxBytesToRead = bufferRemaining; if (range_length >= 0) { int64_t bytesLeftInRange = range_length - buffer->size(); if (bytesLeftInRange < maxBytesToRead) { maxBytesToRead = bytesLeftInRange; if (bytesLeftInRange == 0) { break; } } } ssize_t n = source->readAt( buffer->size(), buffer->data() + buffer->size(), bufferRemaining); maxBytesToRead); if (n < 0) { return n; Loading Loading @@ -659,8 +683,15 @@ rinse_repeat: explicitDiscontinuity = true; } int64_t range_offset, range_length; if (!itemMeta->findInt64("range-offset", &range_offset) || !itemMeta->findInt64("range-length", &range_length)) { range_offset = 0; range_length = -1; } sp<ABuffer> buffer; status_t err = fetchFile(uri.c_str(), &buffer); status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length); if (err != OK) { LOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); mDataSource->queueEOS(err); Loading
media/libstagefright/httplive/M3UParser.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ status_t M3UParser::parse(const void *_data, size_t size) { const char *data = (const char *)_data; size_t offset = 0; uint64_t segmentRangeOffset = 0; while (offset < size) { size_t offsetLF = offset; while (offsetLF < size && data[offsetLF] != '\n') { Loading Loading @@ -218,6 +219,24 @@ status_t M3UParser::parse(const void *_data, size_t size) { } mIsVariantPlaylist = true; err = parseStreamInf(line, &itemMeta); } else if (line.startsWith("#EXT-X-BYTERANGE")) { if (mIsVariantPlaylist) { return ERROR_MALFORMED; } uint64_t length, offset; err = parseByteRange(line, segmentRangeOffset, &length, &offset); if (err == OK) { if (itemMeta == NULL) { itemMeta = new AMessage; } itemMeta->setInt64("range-offset", offset); itemMeta->setInt64("range-length", length); segmentRangeOffset = offset + length; } } if (err != OK) { Loading Loading @@ -446,6 +465,52 @@ status_t M3UParser::parseCipherInfo( return OK; } // static status_t M3UParser::parseByteRange( const AString &line, uint64_t curOffset, uint64_t *length, uint64_t *offset) { ssize_t colonPos = line.find(":"); if (colonPos < 0) { return ERROR_MALFORMED; } ssize_t atPos = line.find("@", colonPos + 1); AString lenStr; if (atPos < 0) { lenStr = AString(line, colonPos + 1, line.size() - colonPos - 1); } else { lenStr = AString(line, colonPos + 1, atPos - colonPos - 1); } lenStr.trim(); const char *s = lenStr.c_str(); char *end; *length = strtoull(s, &end, 10); if (s == end || *end != '\0') { return ERROR_MALFORMED; } if (atPos >= 0) { AString offStr = AString(line, atPos + 1, line.size() - atPos - 1); offStr.trim(); const char *s = offStr.c_str(); *offset = strtoull(s, &end, 10); if (s == end || *end != '\0') { return ERROR_MALFORMED; } } else { *offset = curOffset; } return OK; } // static status_t M3UParser::ParseInt32(const char *s, int32_t *x) { char *end; Loading
media/libstagefright/include/LiveSession.h +4 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,10 @@ private: void onMonitorQueue(); void onSeek(const sp<AMessage> &msg); status_t fetchFile(const char *url, sp<ABuffer> *out); status_t fetchFile( const char *url, sp<ABuffer> *out, int64_t range_offset = 0, int64_t range_length = -1); sp<M3UParser> fetchPlaylist(const char *url, bool *unchanged); size_t getBandwidthIndex(); Loading
media/libstagefright/include/M3UParser.h +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ private: static status_t parseCipherInfo( const AString &line, sp<AMessage> *meta, const AString &baseURI); static status_t parseByteRange( const AString &line, uint64_t curOffset, uint64_t *length, uint64_t *offset); static status_t ParseInt32(const char *s, int32_t *x); static status_t ParseDouble(const char *s, double *x); Loading