aboutsummaryrefslogtreecommitdiff
path: root/usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java
diff options
context:
space:
mode:
Diffstat (limited to 'usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java')
-rw-r--r--usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java163
1 files changed, 163 insertions, 0 deletions
diff --git a/usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java b/usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java
new file mode 100644
index 00000000..6800d644
--- /dev/null
+++ b/usbtuner/src/com/android/usbtuner/exoplayer/DefaultSampleSource.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.usbtuner.exoplayer;
+
+import com.google.android.exoplayer.C;
+import com.google.android.exoplayer.MediaFormatHolder;
+import com.google.android.exoplayer.SampleHolder;
+import com.google.android.exoplayer.SampleSource;
+import com.google.android.exoplayer.TrackInfo;
+import com.google.android.exoplayer.util.Assertions;
+
+import java.io.IOException;
+
+/** {@link SampleSource} that extracts sample data using a {@link SampleExtractor}. */
+public final class DefaultSampleSource implements SampleSource {
+
+ private static final int TRACK_STATE_DISABLED = 0;
+ private static final int TRACK_STATE_ENABLED = 1;
+ private static final int TRACK_STATE_FORMAT_SENT = 2;
+
+ private final SampleExtractor sampleExtractor;
+
+ private TrackInfo[] trackInfos;
+ private boolean prepared;
+ private int remainingReleaseCount;
+ private int[] trackStates;
+ private boolean[] pendingDiscontinuities;
+
+ private long seekPositionUs;
+
+ /**
+ * Creates a new sample source that extracts samples using {@code sampleExtractor}. Specifies the
+ * {@code downstreamRendererCount} to ensure that the sample source is released only when all
+ * downstream renderers have been released.
+ *
+ * @param sampleExtractor a sample extractor for accessing media samples
+ * @param downstreamRendererCount the number of track renderers dependent on this sample source
+ */
+ public DefaultSampleSource(SampleExtractor sampleExtractor, int downstreamRendererCount) {
+ this.sampleExtractor = Assertions.checkNotNull(sampleExtractor);
+ this.remainingReleaseCount = downstreamRendererCount;
+ }
+
+ @Override
+ public boolean prepare(long positionUs) throws IOException {
+ if (prepared) {
+ return true;
+ }
+
+ if (sampleExtractor.prepare()) {
+ prepared = true;
+ trackInfos = sampleExtractor.getTrackInfos();
+ trackStates = new int[trackInfos.length];
+ pendingDiscontinuities = new boolean[trackInfos.length];
+ }
+
+ return prepared;
+ }
+
+ @Override
+ public int getTrackCount() {
+ Assertions.checkState(prepared);
+ return trackInfos.length;
+ }
+
+ @Override
+ public TrackInfo getTrackInfo(int track) {
+ Assertions.checkState(prepared);
+ return trackInfos[track];
+ }
+
+ @Override
+ public void enable(int track, long positionUs) {
+ Assertions.checkState(prepared);
+ Assertions.checkState(trackStates[track] == TRACK_STATE_DISABLED);
+ trackStates[track] = TRACK_STATE_ENABLED;
+ sampleExtractor.selectTrack(track);
+ seekToUsInternal(positionUs, positionUs != 0);
+ }
+
+ @Override
+ public void disable(int track) {
+ Assertions.checkState(prepared);
+ Assertions.checkState(trackStates[track] != TRACK_STATE_DISABLED);
+ sampleExtractor.deselectTrack(track);
+ pendingDiscontinuities[track] = false;
+ trackStates[track] = TRACK_STATE_DISABLED;
+ }
+
+ @Override
+ public boolean continueBuffering(long positionUs) throws IOException {
+ return sampleExtractor.continueBuffering(positionUs);
+ }
+
+ @Override
+ public int readData(int track, long positionUs, MediaFormatHolder formatHolder,
+ SampleHolder sampleHolder, boolean onlyReadDiscontinuity) throws IOException {
+ Assertions.checkState(prepared);
+ Assertions.checkState(trackStates[track] != TRACK_STATE_DISABLED);
+ if (pendingDiscontinuities[track]) {
+ pendingDiscontinuities[track] = false;
+ return DISCONTINUITY_READ;
+ }
+ if (onlyReadDiscontinuity) {
+ return NOTHING_READ;
+ }
+ if (trackStates[track] != TRACK_STATE_FORMAT_SENT) {
+ sampleExtractor.getTrackMediaFormat(track, formatHolder);
+ trackStates[track] = TRACK_STATE_FORMAT_SENT;
+ return FORMAT_READ;
+ }
+
+ seekPositionUs = C.UNKNOWN_TIME_US;
+ return sampleExtractor.readSample(track, sampleHolder);
+ }
+
+ @Override
+ public void seekToUs(long positionUs) {
+ Assertions.checkState(prepared);
+ seekToUsInternal(positionUs, false);
+ }
+
+ @Override
+ public long getBufferedPositionUs() {
+ Assertions.checkState(prepared);
+ return sampleExtractor.getBufferedPositionUs();
+ }
+
+ @Override
+ public void release() {
+ Assertions.checkState(remainingReleaseCount > 0);
+ if (--remainingReleaseCount == 0) {
+ sampleExtractor.release();
+ }
+ }
+
+ private void seekToUsInternal(long positionUs, boolean force) {
+ // Unless forced, avoid duplicate calls to the underlying extractor's seek method in the case
+ // that there have been no interleaving calls to readSample.
+ if (force || seekPositionUs != positionUs) {
+ seekPositionUs = positionUs;
+ sampleExtractor.seekTo(positionUs);
+ for (int i = 0; i < trackStates.length; ++i) {
+ if (trackStates[i] != TRACK_STATE_DISABLED) {
+ pendingDiscontinuities[i] = true;
+ }
+ }
+ }
+ }
+}