mirror of
https://github.com/samsonjs/media.git
synced 2026-04-18 13:25:47 +00:00
Make FakeRenderer more realistic
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=183643457
This commit is contained in:
parent
91c52a4730
commit
67a812c1c2
5 changed files with 70 additions and 24 deletions
|
|
@ -379,10 +379,12 @@ public class DefaultMediaClockTest {
|
|||
|
||||
private static class MediaClockRenderer extends FakeMediaClockRenderer {
|
||||
|
||||
public long positionUs;
|
||||
public PlaybackParameters playbackParameters;
|
||||
|
||||
private final boolean playbackParametersAreMutable;
|
||||
private final boolean isReady;
|
||||
private final boolean isEnded;
|
||||
|
||||
public PlaybackParameters playbackParameters;
|
||||
public long positionUs;
|
||||
|
||||
public MediaClockRenderer() throws ExoPlaybackException {
|
||||
this(PlaybackParameters.DEFAULT, false, true, false, false);
|
||||
|
|
@ -403,11 +405,11 @@ public class DefaultMediaClockTest {
|
|||
boolean playbackParametersAreMutable, boolean isReady, boolean isEnded,
|
||||
boolean hasReadStreamToEnd)
|
||||
throws ExoPlaybackException {
|
||||
this.positionUs = TEST_POSITION_US;
|
||||
this.playbackParameters = playbackParameters;
|
||||
this.playbackParametersAreMutable = playbackParametersAreMutable;
|
||||
this.isReady = isReady;
|
||||
this.isEnded = isEnded;
|
||||
this.positionUs = TEST_POSITION_US;
|
||||
if (!hasReadStreamToEnd) {
|
||||
resetPosition(0);
|
||||
}
|
||||
|
|
@ -436,6 +438,10 @@ public class DefaultMediaClockTest {
|
|||
return isReady;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnded() {
|
||||
return isEnded;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public final class ExoPlayerTest {
|
|||
testRunner.assertNoPositionDiscontinuities();
|
||||
testRunner.assertTimelinesEqual(timeline);
|
||||
assertThat(renderer.formatReadCount).isEqualTo(0);
|
||||
assertThat(renderer.bufferReadCount).isEqualTo(0);
|
||||
assertThat(renderer.sampleBufferReadCount).isEqualTo(0);
|
||||
assertThat(renderer.isEnded).isFalse();
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ public final class ExoPlayerTest {
|
|||
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
||||
assertThat(renderer.formatReadCount).isEqualTo(1);
|
||||
assertThat(renderer.bufferReadCount).isEqualTo(1);
|
||||
assertThat(renderer.sampleBufferReadCount).isEqualTo(1);
|
||||
assertThat(renderer.isEnded).isTrue();
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ public final class ExoPlayerTest {
|
|||
testRunner.assertTimelinesEqual(timeline);
|
||||
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||
assertThat(renderer.formatReadCount).isEqualTo(3);
|
||||
assertThat(renderer.bufferReadCount).isEqualTo(1);
|
||||
assertThat(renderer.sampleBufferReadCount).isEqualTo(3);
|
||||
assertThat(renderer.isEnded).isTrue();
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ public final class ExoPlayerTest {
|
|||
testRunner.assertTimelinesEqual(timeline);
|
||||
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||
assertThat(renderer.formatReadCount).isEqualTo(100);
|
||||
assertThat(renderer.bufferReadCount).isEqualTo(1);
|
||||
assertThat(renderer.sampleBufferReadCount).isEqualTo(100);
|
||||
assertThat(renderer.isEnded).isTrue();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,13 @@ public class SimpleDecoderAudioRendererTest {
|
|||
|
||||
@Test
|
||||
public void testImmediatelyReadEndOfStreamPlaysAudioSinkToEndOfStream() throws Exception {
|
||||
audioRenderer.enable(RendererConfiguration.DEFAULT, new Format[] {FORMAT},
|
||||
new FakeSampleStream(FORMAT), 0, false, 0);
|
||||
audioRenderer.enable(
|
||||
RendererConfiguration.DEFAULT,
|
||||
new Format[] {FORMAT},
|
||||
new FakeSampleStream(FORMAT, false),
|
||||
0,
|
||||
false,
|
||||
0);
|
||||
audioRenderer.setCurrentStreamFinal();
|
||||
when(mockAudioSink.isEnded()).thenReturn(true);
|
||||
while (!audioRenderer.isEnded()) {
|
||||
|
|
@ -116,7 +121,7 @@ public class SimpleDecoderAudioRendererTest {
|
|||
|
||||
@Override
|
||||
protected DecoderInputBuffer createInputBuffer() {
|
||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
|
||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.google.android.exoplayer2.Format;
|
|||
import com.google.android.exoplayer2.FormatHolder;
|
||||
import com.google.android.exoplayer2.Renderer;
|
||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -35,51 +36,72 @@ import java.util.List;
|
|||
*/
|
||||
public class FakeRenderer extends BaseRenderer {
|
||||
|
||||
/**
|
||||
* The amount of time ahead of the current playback position that the renderer reads from the
|
||||
* source. A real renderer will typically read ahead by a small amount due to pipelining through
|
||||
* decoders and the media output path.
|
||||
*/
|
||||
private static final long SOURCE_READAHEAD_US = 250000;
|
||||
|
||||
private final List<Format> expectedFormats;
|
||||
private final DecoderInputBuffer buffer;
|
||||
private final FormatHolder formatHolder;
|
||||
|
||||
private long playbackPositionUs;
|
||||
private long lastSamplePositionUs;
|
||||
|
||||
public boolean isEnded;
|
||||
public int positionResetCount;
|
||||
public int formatReadCount;
|
||||
public int bufferReadCount;
|
||||
public boolean isEnded;
|
||||
public boolean isReady;
|
||||
public int sampleBufferReadCount;
|
||||
|
||||
public FakeRenderer(Format... expectedFormats) {
|
||||
super(expectedFormats.length == 0 ? C.TRACK_TYPE_UNKNOWN
|
||||
: MimeTypes.getTrackType(expectedFormats[0].sampleMimeType));
|
||||
this.expectedFormats = Collections.unmodifiableList(Arrays.asList(expectedFormats));
|
||||
this.buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||
formatHolder = new FormatHolder();
|
||||
lastSamplePositionUs = Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||
playbackPositionUs = positionUs;
|
||||
lastSamplePositionUs = Long.MIN_VALUE;
|
||||
positionResetCount++;
|
||||
isEnded = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||
if (!isEnded) {
|
||||
// Verify the format matches the expected format.
|
||||
FormatHolder formatHolder = new FormatHolder();
|
||||
if (isEnded) {
|
||||
return;
|
||||
}
|
||||
playbackPositionUs = positionUs;
|
||||
while (lastSamplePositionUs < positionUs + SOURCE_READAHEAD_US) {
|
||||
formatHolder.format = null;
|
||||
buffer.clear();
|
||||
int result = readSource(formatHolder, buffer, false);
|
||||
buffer.data = null;
|
||||
if (result == C.RESULT_FORMAT_READ) {
|
||||
formatReadCount++;
|
||||
assertThat(expectedFormats).contains(formatHolder.format);
|
||||
} else if (result == C.RESULT_BUFFER_READ) {
|
||||
bufferReadCount++;
|
||||
if (buffer.isEndOfStream()) {
|
||||
isEnded = true;
|
||||
return;
|
||||
}
|
||||
lastSamplePositionUs = buffer.timeUs;
|
||||
sampleBufferReadCount++;
|
||||
} else {
|
||||
Assertions.checkState(result == C.RESULT_NOTHING_READ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
isReady = buffer.timeUs >= positionUs || hasReadStreamToEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return isReady || isSourceReady();
|
||||
return lastSamplePositionUs >= playbackPositionUs || isSourceReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -23,17 +23,23 @@ import com.google.android.exoplayer2.source.SampleStream;
|
|||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Fake {@link SampleStream} that outputs a given {@link Format} then sets the end of stream flag
|
||||
* on its input buffer.
|
||||
* Fake {@link SampleStream} that outputs a given {@link Format}, an optional sample containing a
|
||||
* single zero byte, then end of stream.
|
||||
*/
|
||||
public final class FakeSampleStream implements SampleStream {
|
||||
|
||||
private final Format format;
|
||||
|
||||
private boolean readFormat;
|
||||
private boolean readSample;
|
||||
|
||||
public FakeSampleStream(Format format) {
|
||||
this(format, true);
|
||||
}
|
||||
|
||||
public FakeSampleStream(Format format, boolean shouldOutputSample) {
|
||||
this.format = format;
|
||||
readSample = !shouldOutputSample;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -48,6 +54,13 @@ public final class FakeSampleStream implements SampleStream {
|
|||
formatHolder.format = format;
|
||||
readFormat = true;
|
||||
return C.RESULT_FORMAT_READ;
|
||||
} else if (!readSample) {
|
||||
buffer.timeUs = 0;
|
||||
buffer.ensureSpaceForWrite(1);
|
||||
buffer.data.put((byte) 0);
|
||||
buffer.flip();
|
||||
readSample = true;
|
||||
return C.RESULT_BUFFER_READ;
|
||||
} else {
|
||||
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
||||
return C.RESULT_BUFFER_READ;
|
||||
|
|
|
|||
Loading…
Reference in a new issue