Commit e486dc60 by aquilescanta Committed by Oliver Woodman

Release Extractor resources in DASH

PiperOrigin-RevId: 321181453
parent 8cd4afcd
...@@ -105,6 +105,11 @@ public final class BundledChunkExtractor implements ExtractorOutput, ChunkExtrac ...@@ -105,6 +105,11 @@ public final class BundledChunkExtractor implements ExtractorOutput, ChunkExtrac
} }
@Override @Override
public void release() {
extractor.release();
}
@Override
public boolean read(ExtractorInput input) throws IOException { public boolean read(ExtractorInput input) throws IOException {
int result = extractor.read(input, POSITION_HOLDER); int result = extractor.read(input, POSITION_HOLDER);
Assertions.checkState(result != Extractor.RESULT_SEEK); Assertions.checkState(result != Extractor.RESULT_SEEK);
......
...@@ -74,6 +74,9 @@ public interface ChunkExtractor { ...@@ -74,6 +74,9 @@ public interface ChunkExtractor {
*/ */
void init(@Nullable TrackOutputProvider trackOutputProvider, long startTimeUs, long endTimeUs); void init(@Nullable TrackOutputProvider trackOutputProvider, long startTimeUs, long endTimeUs);
/** Releases any held resources. */
void release();
/** /**
* Reads from the given {@link ExtractorInput}. * Reads from the given {@link ExtractorInput}.
* *
......
...@@ -355,6 +355,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -355,6 +355,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) { for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.release(); embeddedSampleQueue.release();
} }
chunkSource.release();
if (releaseCallback != null) { if (releaseCallback != null) {
releaseCallback.onSampleStreamReleased(this); releaseCallback.onSampleStreamReleased(this);
} }
......
...@@ -104,4 +104,7 @@ public interface ChunkSource { ...@@ -104,4 +104,7 @@ public interface ChunkSource {
* chunk. * chunk.
*/ */
boolean onChunkLoadError(Chunk chunk, boolean cancelable, Exception e, long exclusionDurationMs); boolean onChunkLoadError(Chunk chunk, boolean cancelable, Exception e, long exclusionDurationMs);
/** Releases any held resources. */
void release();
} }
...@@ -114,11 +114,16 @@ public final class DashUtil { ...@@ -114,11 +114,16 @@ public final class DashUtil {
@Nullable @Nullable
public static Format loadSampleFormat( public static Format loadSampleFormat(
DataSource dataSource, int trackType, Representation representation) throws IOException { DataSource dataSource, int trackType, Representation representation) throws IOException {
ChunkExtractor chunkExtractor = if (representation.getInitializationUri() == null) {
loadInitializationData(dataSource, trackType, representation, false); return null;
return chunkExtractor == null }
? null ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
: Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0]; try {
loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ false);
} finally {
chunkExtractor.release();
}
return Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0];
} }
/** /**
...@@ -136,39 +141,40 @@ public final class DashUtil { ...@@ -136,39 +141,40 @@ public final class DashUtil {
@Nullable @Nullable
public static ChunkIndex loadChunkIndex( public static ChunkIndex loadChunkIndex(
DataSource dataSource, int trackType, Representation representation) throws IOException { DataSource dataSource, int trackType, Representation representation) throws IOException {
@Nullable if (representation.getInitializationUri() == null) {
ChunkExtractor chunkExtractor = return null;
loadInitializationData(dataSource, trackType, representation, true); }
return chunkExtractor == null ? null : chunkExtractor.getChunkIndex(); ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
try {
loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ true);
} finally {
chunkExtractor.release();
}
return chunkExtractor.getChunkIndex();
} }
/** /**
* Loads initialization data for the {@code representation} and optionally index data then returns * Loads initialization data for the {@code representation} and optionally index data then returns
* a {@link BundledChunkExtractor} which contains the output. * a {@link BundledChunkExtractor} which contains the output.
* *
* @param chunkExtractor The {@link ChunkExtractor} to use.
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the {@link
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to. * @param representation The representation which initialization chunk belongs to.
* @param loadIndex Whether to load index data too. * @param loadIndex Whether to load index data too.
* @return A {@link BundledChunkExtractor} for the {@code representation}, or null if no
* initialization or (if requested) index data exists.
* @throws IOException Thrown when there is an error while loading. * @throws IOException Thrown when there is an error while loading.
*/ */
@Nullable private static void loadInitializationData(
private static ChunkExtractor loadInitializationData( ChunkExtractor chunkExtractor,
DataSource dataSource, int trackType, Representation representation, boolean loadIndex) DataSource dataSource,
Representation representation,
boolean loadIndex)
throws IOException { throws IOException {
RangedUri initializationUri = representation.getInitializationUri(); RangedUri initializationUri = Assertions.checkNotNull(representation.getInitializationUri());
if (initializationUri == null) {
return null;
}
ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
RangedUri requestUri; RangedUri requestUri;
if (loadIndex) { if (loadIndex) {
RangedUri indexUri = representation.getIndexUri(); RangedUri indexUri = representation.getIndexUri();
if (indexUri == null) { if (indexUri == null) {
return null; return;
} }
// It's common for initialization and index data to be stored adjacently. Attempt to merge // It's common for initialization and index data to be stored adjacently. Attempt to merge
// the two requests together to request both at once. // the two requests together to request both at once.
...@@ -181,7 +187,6 @@ public final class DashUtil { ...@@ -181,7 +187,6 @@ public final class DashUtil {
requestUri = initializationUri; requestUri = initializationUri;
} }
loadInitializationData(dataSource, representation, chunkExtractor, requestUri); loadInitializationData(dataSource, representation, chunkExtractor, requestUri);
return chunkExtractor;
} }
private static void loadInitializationData( private static void loadInitializationData(
......
...@@ -442,6 +442,16 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -442,6 +442,16 @@ public class DefaultDashChunkSource implements DashChunkSource {
&& trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs); && trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs);
} }
@Override
public void release() {
for (RepresentationHolder representationHolder : representationHolders) {
@Nullable ChunkExtractor chunkExtractor = representationHolder.chunkExtractor;
if (chunkExtractor != null) {
chunkExtractor.release();
}
}
}
// Internal methods. // Internal methods.
private long getSegmentNum( private long getSegmentNum(
......
...@@ -271,6 +271,13 @@ public class DefaultSsChunkSource implements SsChunkSource { ...@@ -271,6 +271,13 @@ public class DefaultSsChunkSource implements SsChunkSource {
&& trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs); && trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), exclusionDurationMs);
} }
@Override
public void release() {
for (ChunkExtractor chunkExtractor : chunkExtractors) {
chunkExtractor.release();
}
}
// Private methods. // Private methods.
private static MediaChunk newMediaChunk( private static MediaChunk newMediaChunk(
......
...@@ -150,4 +150,8 @@ public final class FakeChunkSource implements ChunkSource { ...@@ -150,4 +150,8 @@ public final class FakeChunkSource implements ChunkSource {
return false; return false;
} }
@Override
public void release() {
// Do nothing.
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment