mirror of
https://github.com/samsonjs/media.git
synced 2026-04-17 13:15:47 +00:00
Avoid loading first chunk when preparing HLS for non-zero position.
This also fixes a technical mistake where HlsChunkSource is fed seekPositionUs=-1 when obtaining the first chunk. This is wrong, but the usage of this variable within HlsChunkSource enforces that the seek must stay within bounds, so we get away with it. Issue: #385
This commit is contained in:
parent
116a18848f
commit
64cc380fe1
14 changed files with 41 additions and 30 deletions
|
|
@ -57,7 +57,7 @@ import android.widget.TextView;
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
maybeFail();
|
||||
return STATE_PREPARED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ package com.google.android.exoplayer;
|
|||
/**
|
||||
* A {@link TrackRenderer} that does nothing.
|
||||
* <p>
|
||||
* This renderer returns {@link TrackRenderer#STATE_IGNORE} from {@link #doPrepare()} in order to
|
||||
* request that it should be ignored. {@link IllegalStateException} is thrown from all methods that
|
||||
* are documented to indicate that they should not be invoked unless the renderer is prepared.
|
||||
* This renderer returns {@link TrackRenderer#STATE_IGNORE} from {@link #doPrepare(long)} in order
|
||||
* to request that it should be ignored. {@link IllegalStateException} is thrown from all methods
|
||||
* that are documented to indicate that they should not be invoked unless the renderer is prepared.
|
||||
*/
|
||||
public class DummyTrackRenderer extends TrackRenderer {
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
return STATE_IGNORE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ import java.util.List;
|
|||
boolean prepared = true;
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
if (renderers[i].getState() == TrackRenderer.STATE_UNPREPARED) {
|
||||
int state = renderers[i].prepare();
|
||||
int state = renderers[i].prepare(positionUs);
|
||||
if (state == TrackRenderer.STATE_UNPREPARED) {
|
||||
prepared = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() throws IOException {
|
||||
public boolean prepare(long positionUs) throws IOException {
|
||||
if (!prepared) {
|
||||
extractor = new MediaExtractor();
|
||||
if (context != null) {
|
||||
|
|
|
|||
|
|
@ -243,9 +243,9 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
boolean sourcePrepared = source.prepare();
|
||||
boolean sourcePrepared = source.prepare(positionUs);
|
||||
if (!sourcePrepared) {
|
||||
return TrackRenderer.STATE_UNPREPARED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,10 +57,11 @@ public interface SampleSource {
|
|||
* and formats). If insufficient data is available then the call will return {@code false} rather
|
||||
* than block. The method can be called repeatedly until the return value indicates success.
|
||||
*
|
||||
* @param positionUs The player's current playback position.
|
||||
* @return True if the source was prepared successfully, false otherwise.
|
||||
* @throws IOException If an error occurred preparing the source.
|
||||
*/
|
||||
public boolean prepare() throws IOException;
|
||||
public boolean prepare(long positionUs) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the number of tracks exposed by the source.
|
||||
|
|
|
|||
|
|
@ -108,11 +108,12 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||
* Prepares the renderer. This method is non-blocking, and hence it may be necessary to call it
|
||||
* more than once in order to transition the renderer into the prepared state.
|
||||
*
|
||||
* @param positionUs The player's current playback position.
|
||||
* @return The current state (one of the STATE_* constants), for convenience.
|
||||
*/
|
||||
/* package */ final int prepare() throws ExoPlaybackException {
|
||||
/* package */ final int prepare(long positionUs) throws ExoPlaybackException {
|
||||
Assertions.checkState(state == TrackRenderer.STATE_UNPREPARED);
|
||||
state = doPrepare();
|
||||
state = doPrepare(positionUs);
|
||||
Assertions.checkState(state == TrackRenderer.STATE_UNPREPARED ||
|
||||
state == TrackRenderer.STATE_PREPARED ||
|
||||
state == TrackRenderer.STATE_IGNORE);
|
||||
|
|
@ -127,11 +128,12 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||
* This method should return quickly, and should not block if the renderer is currently unable to
|
||||
* make any useful progress.
|
||||
*
|
||||
* @param positionUs The player's current playback position.
|
||||
* @return The new state of the renderer. One of {@link #STATE_UNPREPARED},
|
||||
* {@link #STATE_PREPARED} and {@link #STATE_IGNORE}.
|
||||
* @throws ExoPlaybackException If an error occurs.
|
||||
*/
|
||||
protected abstract int doPrepare() throws ExoPlaybackException;
|
||||
protected abstract int doPrepare(long positionUs) throws ExoPlaybackException;
|
||||
|
||||
/**
|
||||
* Enable the renderer.
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() {
|
||||
public boolean prepare(long positionUs) {
|
||||
Assertions.checkState(state == STATE_UNPREPARED);
|
||||
loader = new Loader("Loader:" + chunkSource.getTrackInfo().mimeType);
|
||||
state = STATE_PREPARED;
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() throws IOException {
|
||||
public boolean prepare(long positionUs) throws IOException {
|
||||
if (prepared) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,15 +125,12 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() throws IOException {
|
||||
public boolean prepare(long positionUs) throws IOException {
|
||||
if (prepared) {
|
||||
return true;
|
||||
}
|
||||
if (loader == null) {
|
||||
loader = new Loader("Loader:HLS");
|
||||
}
|
||||
continueBufferingInternal();
|
||||
if (!extractors.isEmpty()) {
|
||||
// We're not prepared, but we might have loaded what we need.
|
||||
HlsExtractorWrapper extractor = extractors.getFirst();
|
||||
if (extractor.isPrepared()) {
|
||||
trackCount = extractor.getTrackCount();
|
||||
|
|
@ -146,12 +143,23 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
|||
trackInfos[i] = new TrackInfo(format.mimeType, chunkSource.getDurationUs());
|
||||
}
|
||||
prepared = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!prepared) {
|
||||
maybeThrowLoadableException();
|
||||
// We're not prepared and we haven't loaded what we need.
|
||||
if (loader == null) {
|
||||
loader = new Loader("Loader:HLS");
|
||||
}
|
||||
return prepared;
|
||||
if (!loader.isLoading()) {
|
||||
// We're going to have to start loading a chunk to get what we need for preparation. We should
|
||||
// attempt to load the chunk at positionUs, so that we'll already be loading the correct chunk
|
||||
// in the common case where the renderer is subsequently enabled at this position.
|
||||
pendingResetPositionUs = positionUs;
|
||||
downstreamPositionUs = positionUs;
|
||||
}
|
||||
maybeStartLoading();
|
||||
maybeThrowLoadableException();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ public class MetadataTrackRenderer<T> extends TrackRenderer implements Callback
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
boolean sourcePrepared = source.prepare();
|
||||
boolean sourcePrepared = source.prepare(positionUs);
|
||||
if (!sourcePrepared) {
|
||||
return TrackRenderer.STATE_UNPREPARED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,9 +80,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
boolean sourcePrepared = source.prepare();
|
||||
boolean sourcePrepared = source.prepare(positionUs);
|
||||
if (!sourcePrepared) {
|
||||
return TrackRenderer.STATE_UNPREPARED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ public class Eia608TrackRenderer extends TrackRenderer implements Callback {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int doPrepare() throws ExoPlaybackException {
|
||||
protected int doPrepare(long positionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
boolean sourcePrepared = source.prepare();
|
||||
boolean sourcePrepared = source.prepare(positionUs);
|
||||
if (!sourcePrepared) {
|
||||
return TrackRenderer.STATE_UNPREPARED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ public class Mp4ExtractorTest extends TestCase {
|
|||
try {
|
||||
switch (message.what) {
|
||||
case MSG_PREPARE:
|
||||
if (!source.prepare()) {
|
||||
if (!source.prepare(0)) {
|
||||
sendEmptyMessage(MSG_PREPARE);
|
||||
} else {
|
||||
// Select the video track and get its metadata.
|
||||
|
|
|
|||
Loading…
Reference in a new issue