Improve customisability of FakeSampleStream.
PiperOrigin-RevId: 289829592
This commit is contained in:
parent
a225e887fa
commit
96c648c2d6
@ -27,10 +27,12 @@ import com.google.android.exoplayer2.metadata.emsg.EventMessageEncoder;
|
|||||||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
||||||
import com.google.android.exoplayer2.metadata.scte35.TimeSignalCommand;
|
import com.google.android.exoplayer2.metadata.scte35.TimeSignalCommand;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
||||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -141,7 +143,11 @@ public class MetadataRendererTest {
|
|||||||
MetadataRenderer renderer = new MetadataRenderer(metadata::add, /* outputLooper= */ null);
|
MetadataRenderer renderer = new MetadataRenderer(metadata::add, /* outputLooper= */ null);
|
||||||
renderer.replaceStream(
|
renderer.replaceStream(
|
||||||
new Format[] {EMSG_FORMAT},
|
new Format[] {EMSG_FORMAT},
|
||||||
new FakeSampleStream(EMSG_FORMAT, /* eventDispatcher= */ null, input),
|
new FakeSampleStream(
|
||||||
|
EMSG_FORMAT,
|
||||||
|
/* eventDispatcher= */ null,
|
||||||
|
Arrays.asList(new FakeSampleStreamItem(input)),
|
||||||
|
0),
|
||||||
/* offsetUs= */ 0L);
|
/* offsetUs= */ 0L);
|
||||||
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the format
|
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the format
|
||||||
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the data
|
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the data
|
||||||
|
@ -23,20 +23,64 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
|||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.SampleStream;
|
import com.google.android.exoplayer2.source.SampleStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fake {@link SampleStream} that outputs a given {@link Format}, an optional sample containing a
|
* Fake {@link SampleStream} that outputs a given {@link Format}, any amount of {@link
|
||||||
* single zero byte, then end of stream.
|
* FakeSampleStreamItem items}, then end of stream.
|
||||||
*/
|
*/
|
||||||
public final class FakeSampleStream implements SampleStream {
|
public final class FakeSampleStream implements SampleStream {
|
||||||
|
|
||||||
private final Format format;
|
/** Item to customize a return value of {@link FakeSampleStream#readData}. */
|
||||||
@Nullable private final EventDispatcher eventDispatcher;
|
public static final class FakeSampleStreamItem {
|
||||||
private final byte[] sampleData;
|
@Nullable Format format;
|
||||||
|
@Nullable byte[] sampleData;
|
||||||
|
int flags;
|
||||||
|
|
||||||
private boolean notifiedDownstreamFormat;
|
/**
|
||||||
|
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
||||||
|
* return {@link C#RESULT_FORMAT_READ} with the new format.
|
||||||
|
*
|
||||||
|
* @param format The format to be returned.
|
||||||
|
*/
|
||||||
|
public FakeSampleStreamItem(Format format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
||||||
|
* return {@link C#RESULT_BUFFER_READ} with the sample data.
|
||||||
|
*
|
||||||
|
* @param sampleData The sample data to be read.
|
||||||
|
*/
|
||||||
|
public FakeSampleStreamItem(byte[] sampleData) {
|
||||||
|
this.sampleData = sampleData.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
||||||
|
* return {@link C#RESULT_BUFFER_READ} with the sample data.
|
||||||
|
*
|
||||||
|
* @param sampleData The sample data to be read.
|
||||||
|
* @param flags The buffer flags to be set.
|
||||||
|
*/
|
||||||
|
public FakeSampleStreamItem(byte[] sampleData, int flags) {
|
||||||
|
this.sampleData = sampleData.clone();
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ArrayDeque<FakeSampleStreamItem> fakeSampleStreamItems;
|
||||||
|
private final int timeUsIncrement;
|
||||||
|
|
||||||
|
@Nullable private final EventDispatcher eventDispatcher;
|
||||||
|
|
||||||
|
private Format format;
|
||||||
|
private int timeUs;
|
||||||
private boolean readFormat;
|
private boolean readFormat;
|
||||||
private boolean readSample;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates fake sample stream which outputs the given {@link Format}, optionally one sample with
|
* Creates fake sample stream which outputs the given {@link Format}, optionally one sample with
|
||||||
@ -48,23 +92,34 @@ public final class FakeSampleStream implements SampleStream {
|
|||||||
*/
|
*/
|
||||||
public FakeSampleStream(
|
public FakeSampleStream(
|
||||||
Format format, @Nullable EventDispatcher eventDispatcher, boolean shouldOutputSample) {
|
Format format, @Nullable EventDispatcher eventDispatcher, boolean shouldOutputSample) {
|
||||||
this(format, eventDispatcher, new byte[] {0});
|
this(
|
||||||
readSample = !shouldOutputSample;
|
format,
|
||||||
|
eventDispatcher,
|
||||||
|
shouldOutputSample
|
||||||
|
? Arrays.asList(new FakeSampleStreamItem(new byte[] {0}))
|
||||||
|
: Collections.emptyList(),
|
||||||
|
/* timeUsIncrement= */ 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates fake sample stream which outputs the given {@link Format}, one sample with the provided
|
* Creates a fake sample stream which outputs the given {@link Format}, any amount of {@link
|
||||||
* bytes, then end of stream.
|
* FakeSampleStreamItem items}, then end of stream.
|
||||||
*
|
*
|
||||||
* @param format The {@link Format} to output.
|
* @param format The {@link Format} to output.
|
||||||
* @param eventDispatcher An {@link EventDispatcher} to notify of read events.
|
* @param eventDispatcher An {@link EventDispatcher} to notify of read events.
|
||||||
* @param sampleData The sample data to output.
|
* @param fakeSampleStreamItems The list of {@link FakeSampleStreamItem items} to customize the
|
||||||
|
* return values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}.
|
||||||
|
* @param timeUsIncrement The time each sample should increase by, in microseconds.
|
||||||
*/
|
*/
|
||||||
public FakeSampleStream(
|
public FakeSampleStream(
|
||||||
Format format, @Nullable EventDispatcher eventDispatcher, byte[] sampleData) {
|
Format format,
|
||||||
|
@Nullable EventDispatcher eventDispatcher,
|
||||||
|
List<FakeSampleStreamItem> fakeSampleStreamItems,
|
||||||
|
int timeUsIncrement) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
this.sampleData = sampleData;
|
this.fakeSampleStreamItems = new ArrayDeque<>(fakeSampleStreamItems);
|
||||||
|
this.timeUsIncrement = timeUsIncrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,29 +130,34 @@ public final class FakeSampleStream implements SampleStream {
|
|||||||
@Override
|
@Override
|
||||||
public int readData(
|
public int readData(
|
||||||
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) {
|
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) {
|
||||||
if (eventDispatcher != null && !notifiedDownstreamFormat) {
|
if (!readFormat || formatRequired) {
|
||||||
eventDispatcher.downstreamFormatChanged(
|
|
||||||
C.TRACK_TYPE_UNKNOWN,
|
|
||||||
format,
|
|
||||||
C.SELECTION_REASON_UNKNOWN,
|
|
||||||
/* trackSelectionData= */ null,
|
|
||||||
/* mediaTimeUs= */ 0);
|
|
||||||
notifiedDownstreamFormat = true;
|
|
||||||
}
|
|
||||||
if (formatRequired || !readFormat) {
|
|
||||||
formatHolder.format = format;
|
|
||||||
readFormat = true;
|
readFormat = true;
|
||||||
|
formatHolder.format = format;
|
||||||
|
notifyEventDispatcher(formatHolder);
|
||||||
return C.RESULT_FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
} else if (!readSample) {
|
|
||||||
buffer.timeUs = 0;
|
|
||||||
buffer.ensureSpaceForWrite(sampleData.length);
|
|
||||||
buffer.data.put(sampleData);
|
|
||||||
readSample = true;
|
|
||||||
return C.RESULT_BUFFER_READ;
|
|
||||||
} else {
|
|
||||||
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
|
||||||
return C.RESULT_BUFFER_READ;
|
|
||||||
}
|
}
|
||||||
|
if (!fakeSampleStreamItems.isEmpty()) {
|
||||||
|
FakeSampleStreamItem fakeSampleStreamItem = fakeSampleStreamItems.remove();
|
||||||
|
if (fakeSampleStreamItem.format != null) {
|
||||||
|
format = fakeSampleStreamItem.format;
|
||||||
|
formatHolder.format = format;
|
||||||
|
notifyEventDispatcher(formatHolder);
|
||||||
|
return C.RESULT_FORMAT_READ;
|
||||||
|
}
|
||||||
|
if (fakeSampleStreamItem.sampleData != null) {
|
||||||
|
byte[] sampleData = fakeSampleStreamItem.sampleData;
|
||||||
|
buffer.timeUs = timeUs;
|
||||||
|
timeUs += timeUsIncrement;
|
||||||
|
buffer.ensureSpaceForWrite(sampleData.length);
|
||||||
|
buffer.data.put(sampleData);
|
||||||
|
if (fakeSampleStreamItem.flags != 0) {
|
||||||
|
buffer.setFlags(fakeSampleStreamItem.flags);
|
||||||
|
}
|
||||||
|
return C.RESULT_BUFFER_READ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
||||||
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -109,4 +169,15 @@ public final class FakeSampleStream implements SampleStream {
|
|||||||
public int skipData(long positionUs) {
|
public int skipData(long positionUs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyEventDispatcher(FormatHolder formatHolder) {
|
||||||
|
if (eventDispatcher != null) {
|
||||||
|
eventDispatcher.downstreamFormatChanged(
|
||||||
|
C.TRACK_TYPE_UNKNOWN,
|
||||||
|
formatHolder.format,
|
||||||
|
C.SELECTION_REASON_UNKNOWN,
|
||||||
|
/* trackSelectionData= */ null,
|
||||||
|
/* mediaTimeUs= */ timeUs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user