Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0610341f authored by Leena Winterrowd's avatar Leena Winterrowd Committed by Gerrit - the friendly Code Review server
Browse files

httplive: Resolve buffering standoff in HLS

It is possible for the HLS stack to accumulate more data for one
stream than the other over time. Once the buffering for this stream
exceeds the HLS buffering threshold, buffering is stopped for all
streams, even if the other active streams have no data buffered.

In such a case, dequeue of the fully-buffered stream is blocked
waiting for a packet to exist in the 'other stream' (eg the video
stream if dequeueing audio), but due to the aforementioned buffering
threshold, no additional data will ever be fetched.

Since the TS parser is aware of the existing streams once startup
is complete (at least 1 packet from each source type has been found),
require all streams, instead of just one stream, to meet the buffering
requirements once startup is complete. Retain the 'largest buffered
stream' requirement during startup only to ensure that we do not wait
for a stream type that is not present.

CRs-Fixed: 803835
Change-Id: I597664b508b7539d9fe0ee4fc7cee986df2970ae
parent 0c52765e
Loading
Loading
Loading
Loading
+17 −6
Original line number Original line Diff line number Diff line
@@ -627,7 +627,7 @@ void PlaylistFetcher::onMonitorQueue() {
        durationToBufferUs = kMinBufferedDurationUs;
        durationToBufferUs = kMinBufferedDurationUs;
    }
    }


    int64_t bufferedDurationUs = 0ll;
    int64_t bufferedDurationUs = -1ll;
    status_t finalResult = NOT_ENOUGH_DATA;
    status_t finalResult = NOT_ENOUGH_DATA;
    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
    if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
        sp<AnotherPacketSource> packetSource =
        sp<AnotherPacketSource> packetSource =
@@ -637,7 +637,10 @@ void PlaylistFetcher::onMonitorQueue() {
                packetSource->getBufferedDurationUs(&finalResult);
                packetSource->getBufferedDurationUs(&finalResult);
        finalResult = OK;
        finalResult = OK;
    } else {
    } else {
        // Use max stream duration to prevent us from waiting on a non-existent stream;
        // In steady-state playback, the TS parser will ensure that mStreamTypeMask
        // correctly reflects the streams that are present. In this case, use min stream
        // duration to ensure that all streams are buffered. Otherwise (when mStartup is set)
        // use max stream duration to prevent us from waiting on a non-existent stream;
        // when we cannot make out from the manifest what streams are included in a playlist
        // when we cannot make out from the manifest what streams are included in a playlist
        // we might assume extra streams.
        // we might assume extra streams.
        for (size_t i = 0; i < mPacketSources.size(); ++i) {
        for (size_t i = 0; i < mPacketSources.size(); ++i) {
@@ -647,11 +650,19 @@ void PlaylistFetcher::onMonitorQueue() {


            int64_t bufferedStreamDurationUs =
            int64_t bufferedStreamDurationUs =
                mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
                mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
            ALOGV("buffered %" PRId64 " for stream %d",
            ALOGV("buffered %" PRId64 " for stream %d (startup = %s)",
                    bufferedStreamDurationUs, mPacketSources.keyAt(i));
                    bufferedStreamDurationUs, mPacketSources.keyAt(i),
                    mStartup ? "true" : "false");
            if (mStartup) {
                if (bufferedStreamDurationUs > bufferedDurationUs) {
                if (bufferedStreamDurationUs > bufferedDurationUs) {
                    bufferedDurationUs = bufferedStreamDurationUs;
                    bufferedDurationUs = bufferedStreamDurationUs;
                }
                }
            } else {
                if (bufferedDurationUs < 0 ||
                        bufferedStreamDurationUs < bufferedDurationUs) {
                    bufferedDurationUs = bufferedStreamDurationUs;
                }
            }
        }
        }
    }
    }
    downloadMore = (bufferedDurationUs < durationToBufferUs);
    downloadMore = (bufferedDurationUs < durationToBufferUs);