11abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/*
21abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Copyright (C) 2015 The Android Open Source Project
31abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
41abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
51abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * you may not use this file except in compliance with the License.
61abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * You may obtain a copy of the License at
71abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
81abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
91abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Unless required by applicable law or agreed to in writing, software
111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * See the License for the specific language governing permissions and
141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * limitations under the License.
151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1748dadb49248271b01997862e1335912a4f2e189fYoungsang Chopackage com.android.usbtuner.exoplayer.cache;
181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1948dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.media.MediaFormat;
201abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.os.ConditionVariable;
211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
221abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.C;
231abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.SampleHolder;
241abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.SampleSource;
251abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.usbtuner.tvinput.PlaybackCacheListener;
261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2748dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport java.io.IOException;
2848dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport java.util.List;
2948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
301abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport junit.framework.Assert;
311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/**
3348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Handles I/O for {@link com.android.usbtuner.exoplayer.SampleExtractor} when
3448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * physical storage based cache is not used. Trickplay is disabled.
351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
3648dadb49248271b01997862e1335912a4f2e189fYoungsang Chopublic class SimpleSampleBuffer implements CacheManager.SampleBuffer {
371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final SamplePool mSamplePool = new SamplePool();
381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private SampleQueue[] mPlayingSampleQueues;
391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private long mLastBufferedPositionUs = C.UNKNOWN_TIME_US;
401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    private volatile boolean mEos;
421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public SimpleSampleBuffer(PlaybackCacheListener cacheListener) {
4448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        if (cacheListener != null) {
4548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            // Disables trickplay.
4648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            cacheListener.onCacheStateChanged(false);
471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
5148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public synchronized void init(List<String> ids, List<MediaFormat> mediaFormats) {
5248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        int trackCount = ids.size();
531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayingSampleQueues = new SampleQueue[trackCount];
541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        for (int i = 0; i < trackCount; i++) {
551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mPlayingSampleQueues[i] = null;
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
6048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public void setEos() {
6148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mEos = true;
6248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
6348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
6448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    private boolean reachedEos() {
6548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        return mEos;
6648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
6748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
6848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    @Override
691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void selectTrack(int index) {
701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        synchronized (this) {
711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (mPlayingSampleQueues[index] == null) {
721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mPlayingSampleQueues[index] = new SampleQueue(mSamplePool);
731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            } else {
741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mPlayingSampleQueues[index].clear();
751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void deselectTrack(int index) {
811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        synchronized (this) {
821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (mPlayingSampleQueues[index] != null) {
831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mPlayingSampleQueues[index].clear();
841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mPlayingSampleQueues[index] = null;
851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
9048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public synchronized long getBufferedPositionUs() {
9148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        Long result = null;
9248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        for (SampleQueue queue : mPlayingSampleQueues) {
9348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (queue == null) {
9448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                continue;
95369b6a409204a9b2a95f7ba575d7c3b7bdc94ab7Youngsang Cho            }
9648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            Long bufferedPositionUs = queue.getEndPositionUs();
9748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (bufferedPositionUs == null) {
9848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                continue;
9948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            }
10048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (result == null || result > bufferedPositionUs) {
10148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                result = bufferedPositionUs;
1021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
1031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
10448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        if (result == null) {
10548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            return mLastBufferedPositionUs;
10648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        } else {
10748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            return (mLastBufferedPositionUs = result);
10848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        }
1091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
11248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public synchronized int readSample(int track, SampleHolder sampleHolder) {
11348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        SampleQueue queue = mPlayingSampleQueues[track];
11448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        Assert.assertNotNull(queue);
11548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        int result = queue.dequeueSample(sampleHolder);
11648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        if (result != SampleSource.SAMPLE_READ && reachedEos()) {
11748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            return SampleSource.END_OF_STREAM;
11848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        }
11948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        return result;
12048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
12148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
12248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    @Override
12348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public void writeSample(int index, SampleHolder sample,
12448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            ConditionVariable conditionVariable) throws IOException {
12548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sample.data.position(0).limit(sample.size);
12648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        SampleHolder sampleToQueue = mSamplePool.acquireSample(sample.size);
12748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sampleToQueue.size = sample.size;
12848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sampleToQueue.clearData();
12948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sampleToQueue.data.put(sample.data);
13048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sampleToQueue.timeUs = sample.timeUs;
13148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        sampleToQueue.flags = sample.flags;
13248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
1331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        synchronized (this) {
13448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (mPlayingSampleQueues[index] != null) {
13548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                mPlayingSampleQueues[index].queueSample(sampleToQueue);
1361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
1371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
14148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public boolean isWriteSpeedSlow(int sampleSize, long durationNs) {
14248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // Since SimpleSampleBuffer write samples only to memory (not to physical storage),
14348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // write speed is always fine.
14448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        return false;
14548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
14648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
14748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    @Override
14848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public void handleWriteSpeedSlow() {
14948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // no-op
15048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
15148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
15248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    @Override
15348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public synchronized boolean continueBuffering(long positionUs) {
15448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        for (SampleQueue queue : mPlayingSampleQueues) {
15548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (queue == null) {
15648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                continue;
15748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            }
15848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (queue.isEmpty()) {
15948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                return false;
1601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
16248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        return true;
1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
1661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void seekTo(long positionUs) {
1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Not used.
1681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
16948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
17048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    @Override
17148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public void release() {
17248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // Not used.
17348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    }
1741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
175