From c67f18764f038f8a39a1c6aaacea5458f136427d Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 18 Jul 2019 13:45:00 +0100 Subject: [PATCH] Move Format equality check back to write side of sample queue PiperOrigin-RevId: 258752996 --- .../source/SampleMetadataQueue.java | 19 +++++++++--- .../exoplayer2/source/SampleQueueTest.java | 31 +++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java index 89160f45f3..09bc438f90 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java @@ -62,6 +62,7 @@ import com.google.android.exoplayer2.util.Util; private boolean upstreamKeyframeRequired; private boolean upstreamFormatRequired; private Format upstreamFormat; + private Format upstreamCommittedFormat; private int upstreamSourceId; public SampleMetadataQueue() { @@ -96,6 +97,7 @@ import com.google.android.exoplayer2.util.Util; largestDiscardedTimestampUs = Long.MIN_VALUE; largestQueuedTimestampUs = Long.MIN_VALUE; isLastSampleQueued = false; + upstreamCommittedFormat = null; if (resetUpstreamFormat) { upstreamFormat = null; upstreamFormatRequired = true; @@ -227,7 +229,7 @@ import com.google.android.exoplayer2.util.Util; return SampleQueue.PEEK_RESULT_NOTHING; } int relativeReadIndex = getRelativeIndex(readPosition); - if (!formats[relativeReadIndex].equals(downstreamFormat)) { + if (formats[relativeReadIndex] != downstreamFormat) { return SampleQueue.PEEK_RESULT_FORMAT; } else { return (flags[relativeReadIndex] & C.BUFFER_FLAG_ENCRYPTED) != 0 @@ -274,8 +276,7 @@ import com.google.android.exoplayer2.util.Util; if (loadingFinished || isLastSampleQueued) { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; - } else if (upstreamFormat != null - && (formatRequired || !upstreamFormat.equals(downstreamFormat))) { + } else if (upstreamFormat != null && (formatRequired || upstreamFormat != downstreamFormat)) { formatHolder.format = upstreamFormat; return C.RESULT_FORMAT_READ; } else { @@ -284,7 +285,7 @@ import com.google.android.exoplayer2.util.Util; } int relativeReadIndex = getRelativeIndex(readPosition); - if (formatRequired || !formats[relativeReadIndex].equals(downstreamFormat)) { + if (formatRequired || formats[relativeReadIndex] != downstreamFormat) { formatHolder.format = formats[relativeReadIndex]; return C.RESULT_FORMAT_READ; } @@ -422,7 +423,16 @@ import com.google.android.exoplayer2.util.Util; } upstreamFormatRequired = false; if (Util.areEqual(format, upstreamFormat)) { + // The format is unchanged. If format and upstreamFormat are different objects, we keep the + // current upstreamFormat so we can detect format changes in read() using cheap referential + // equality. return false; + } else if (Util.areEqual(format, upstreamCommittedFormat)) { + // The format has changed back to the format of the last committed sample. If they are + // different objects, we revert back to using upstreamCommittedFormat as the upstreamFormat so + // we can detect format changes in read() using cheap referential equality. + upstreamFormat = upstreamCommittedFormat; + return true; } else { upstreamFormat = format; return true; @@ -450,6 +460,7 @@ import com.google.android.exoplayer2.util.Util; cryptoDatas[relativeEndIndex] = cryptoData; formats[relativeEndIndex] = upstreamFormat; sourceIds[relativeEndIndex] = upstreamSourceId; + upstreamCommittedFormat = upstreamFormat; length++; if (length == capacity) { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java index bfc6bb52c9..6812e08ef7 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -129,10 +129,10 @@ public final class SampleQueueTest { } @Test - public void testReadFormatDeduplicated() { + public void testEqualFormatsDeduplicated() { sampleQueue.format(FORMAT_1); assertReadFormat(false, FORMAT_1); - // If the same format is input then it should be de-duplicated (i.e. not output again). + // If the same format is written then it should not cause a format change on the read side. sampleQueue.format(FORMAT_1); assertNoSamplesToRead(FORMAT_1); // The same applies for a format that's equal (but a different object). @@ -140,6 +140,33 @@ public final class SampleQueueTest { assertNoSamplesToRead(FORMAT_1); } + @Test + public void testMultipleFormatsDeduplicated() { + sampleQueue.format(FORMAT_1); + sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE); + sampleQueue.sampleMetadata(0, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null); + // Writing multiple formats should not cause a format change on the read side, provided the last + // format to be written is equal to the format of the previous sample. + sampleQueue.format(FORMAT_2); + sampleQueue.format(FORMAT_1_COPY); + sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE); + sampleQueue.sampleMetadata(1000, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null); + + assertReadFormat(false, FORMAT_1); + assertReadSample(0, true, DATA, 0, ALLOCATION_SIZE); + // Assert the second sample is read without a format change. + assertReadSample(1000, true, DATA, 0, ALLOCATION_SIZE); + + // The same applies if the queue is empty when the formats are written. + sampleQueue.format(FORMAT_2); + sampleQueue.format(FORMAT_1); + sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE); + sampleQueue.sampleMetadata(2000, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null); + + // Assert the third sample is read without a format change. + assertReadSample(2000, true, DATA, 0, ALLOCATION_SIZE); + } + @Test public void testReadSingleSamples() { sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);