diff options
Diffstat (limited to 'tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleSource.java')
-rw-r--r-- | tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleSource.java | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleSource.java b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleSource.java new file mode 100644 index 00000000..3b5d1011 --- /dev/null +++ b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleSource.java @@ -0,0 +1,195 @@ +/* + * 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.tv.tuner.exoplayer; + +import com.google.android.exoplayer.C; +import com.google.android.exoplayer.MediaFormat; +import com.google.android.exoplayer.MediaFormatHolder; +import com.google.android.exoplayer.SampleHolder; +import com.google.android.exoplayer.SampleSource; +import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.util.Assertions; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** {@link SampleSource} that extracts sample data using a {@link SampleExtractor}. */ +public final class MpegTsSampleSource implements SampleSource, SampleSourceReader { + + 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 mSampleExtractor; + private final List<Integer> mTrackStates = new ArrayList<>(); + private final List<Boolean> mPendingDiscontinuities = new ArrayList<>(); + + private boolean mPrepared; + private IOException mPreparationError; + private int mRemainingReleaseCount; + + private long mLastSeekPositionUs; + private long mPendingSeekPositionUs; + + /** + * Creates a new sample source that extracts samples using {@code mSampleExtractor}. + * + * @param sampleExtractor a sample extractor for accessing media samples + */ + public MpegTsSampleSource(SampleExtractor sampleExtractor) { + mSampleExtractor = Assertions.checkNotNull(sampleExtractor); + } + + @Override + public SampleSourceReader register() { + mRemainingReleaseCount++; + return this; + } + + @Override + public boolean prepare(long positionUs) { + if (!mPrepared) { + if (mPreparationError != null) { + return false; + } + try { + if (mSampleExtractor.prepare()) { + int trackCount = mSampleExtractor.getTrackFormats().size(); + mTrackStates.clear(); + mPendingDiscontinuities.clear(); + for (int i = 0; i < trackCount; ++i) { + mTrackStates.add(i, TRACK_STATE_DISABLED); + mPendingDiscontinuities.add(i, false); + } + mPrepared = true; + } else { + return false; + } + } catch (IOException e) { + mPreparationError = e; + return false; + } + } + return true; + } + + @Override + public int getTrackCount() { + Assertions.checkState(mPrepared); + return mSampleExtractor.getTrackFormats().size(); + } + + @Override + public MediaFormat getFormat(int track) { + Assertions.checkState(mPrepared); + return mSampleExtractor.getTrackFormats().get(track); + } + + @Override + public void enable(int track, long positionUs) { + Assertions.checkState(mPrepared); + Assertions.checkState(mTrackStates.get(track) == TRACK_STATE_DISABLED); + mTrackStates.set(track, TRACK_STATE_ENABLED); + mSampleExtractor.selectTrack(track); + seekToUsInternal(positionUs, positionUs != 0); + } + + @Override + public void disable(int track) { + Assertions.checkState(mPrepared); + Assertions.checkState(mTrackStates.get(track) != TRACK_STATE_DISABLED); + mSampleExtractor.deselectTrack(track); + mPendingDiscontinuities.set(track, false); + mTrackStates.set(track, TRACK_STATE_DISABLED); + } + + @Override + public boolean continueBuffering(int track, long positionUs) { + return mSampleExtractor.continueBuffering(positionUs); + } + + @Override + public long readDiscontinuity(int track) { + if (mPendingDiscontinuities.get(track)) { + mPendingDiscontinuities.set(track, false); + return mLastSeekPositionUs; + } + return NO_DISCONTINUITY; + } + + @Override + public int readData( + int track, long positionUs, MediaFormatHolder formatHolder, SampleHolder sampleHolder) { + Assertions.checkState(mPrepared); + Assertions.checkState(mTrackStates.get(track) != TRACK_STATE_DISABLED); + if (mPendingDiscontinuities.get(track)) { + return NOTHING_READ; + } + if (mTrackStates.get(track) != TRACK_STATE_FORMAT_SENT) { + mSampleExtractor.getTrackMediaFormat(track, formatHolder); + mTrackStates.set(track, TRACK_STATE_FORMAT_SENT); + return FORMAT_READ; + } + + mPendingSeekPositionUs = C.UNKNOWN_TIME_US; + return mSampleExtractor.readSample(track, sampleHolder); + } + + @Override + public void maybeThrowError() throws IOException { + if (mPreparationError != null) { + throw mPreparationError; + } + if (mSampleExtractor != null) { + mSampleExtractor.maybeThrowError(); + } + } + + @Override + public void seekToUs(long positionUs) { + Assertions.checkState(mPrepared); + seekToUsInternal(positionUs, false); + } + + @Override + public long getBufferedPositionUs() { + Assertions.checkState(mPrepared); + return mSampleExtractor.getBufferedPositionUs(); + } + + @Override + public void release() { + Assertions.checkState(mRemainingReleaseCount > 0); + if (--mRemainingReleaseCount == 0) { + mSampleExtractor.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 || mPendingSeekPositionUs != positionUs) { + mLastSeekPositionUs = positionUs; + mPendingSeekPositionUs = positionUs; + mSampleExtractor.seekTo(positionUs); + for (int i = 0; i < mTrackStates.size(); ++i) { + if (mTrackStates.get(i) != TRACK_STATE_DISABLED) { + mPendingDiscontinuities.set(i, true); + } + } + } + } +} |