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