Move Format equality check back to write side of sample queue

PiperOrigin-RevId: 258752996
This commit is contained in:
olly 2019-07-18 13:45:00 +01:00 committed by Oliver Woodman
parent e25340be3d
commit c67f18764f
2 changed files with 44 additions and 6 deletions

View File

@ -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) {

View File

@ -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);