Home | History | Annotate | Download | only in buffer
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tv.tuner.exoplayer.buffer;
     18 
     19 import android.os.ConditionVariable;
     20 
     21 import android.support.annotation.NonNull;
     22 
     23 import com.google.android.exoplayer.C;
     24 import com.google.android.exoplayer.MediaFormat;
     25 import com.google.android.exoplayer.SampleHolder;
     26 import com.google.android.exoplayer.SampleSource;
     27 import com.android.tv.common.SoftPreconditions;
     28 import com.android.tv.tuner.tvinput.PlaybackBufferListener;
     29 import com.android.tv.tuner.exoplayer.SampleExtractor;
     30 
     31 import java.io.IOException;
     32 import java.util.List;
     33 
     34 /**
     35  * Handles I/O for {@link SampleExtractor} when
     36  * physical storage based buffer is not used. Trickplay is disabled.
     37  */
     38 public class SimpleSampleBuffer implements BufferManager.SampleBuffer {
     39     private final SamplePool mSamplePool = new SamplePool();
     40     private SampleQueue[] mPlayingSampleQueues;
     41     private long mLastBufferedPositionUs = C.UNKNOWN_TIME_US;
     42 
     43     private volatile boolean mEos;
     44 
     45     public SimpleSampleBuffer(PlaybackBufferListener bufferListener) {
     46         if (bufferListener != null) {
     47             // Disables trickplay.
     48             bufferListener.onBufferStateChanged(false);
     49         }
     50     }
     51 
     52     @Override
     53     public synchronized void init(@NonNull List<String> ids,
     54             @NonNull List<MediaFormat> mediaFormats) {
     55         int trackCount = ids.size();
     56         mPlayingSampleQueues = new SampleQueue[trackCount];
     57         for (int i = 0; i < trackCount; i++) {
     58             mPlayingSampleQueues[i] = null;
     59         }
     60     }
     61 
     62     @Override
     63     public void setEos() {
     64         mEos = true;
     65     }
     66 
     67     private boolean reachedEos() {
     68         return mEos;
     69     }
     70 
     71     @Override
     72     public void selectTrack(int index) {
     73         synchronized (this) {
     74             if (mPlayingSampleQueues[index] == null) {
     75                 mPlayingSampleQueues[index] = new SampleQueue(mSamplePool);
     76             } else {
     77                 mPlayingSampleQueues[index].clear();
     78             }
     79         }
     80     }
     81 
     82     @Override
     83     public void deselectTrack(int index) {
     84         synchronized (this) {
     85             if (mPlayingSampleQueues[index] != null) {
     86                 mPlayingSampleQueues[index].clear();
     87                 mPlayingSampleQueues[index] = null;
     88             }
     89         }
     90     }
     91 
     92     @Override
     93     public synchronized long getBufferedPositionUs() {
     94         Long result = null;
     95         for (SampleQueue queue : mPlayingSampleQueues) {
     96             if (queue == null) {
     97                 continue;
     98             }
     99             Long lastQueuedSamplePositionUs = queue.getLastQueuedPositionUs();
    100             if (lastQueuedSamplePositionUs == null) {
    101                 // No sample has been queued.
    102                 result = mLastBufferedPositionUs;
    103                 continue;
    104             }
    105             if (result == null || result > lastQueuedSamplePositionUs) {
    106                 result = lastQueuedSamplePositionUs;
    107             }
    108         }
    109         if (result == null) {
    110             return mLastBufferedPositionUs;
    111         }
    112         return (mLastBufferedPositionUs = result);
    113     }
    114 
    115     @Override
    116     public synchronized int readSample(int track, SampleHolder sampleHolder) {
    117         SampleQueue queue = mPlayingSampleQueues[track];
    118         SoftPreconditions.checkNotNull(queue);
    119         int result = queue == null ? SampleSource.NOTHING_READ : queue.dequeueSample(sampleHolder);
    120         if (result != SampleSource.SAMPLE_READ && reachedEos()) {
    121             return SampleSource.END_OF_STREAM;
    122         }
    123         return result;
    124     }
    125 
    126     @Override
    127     public void writeSample(int index, SampleHolder sample,
    128             ConditionVariable conditionVariable) throws IOException {
    129         sample.data.position(0).limit(sample.size);
    130         SampleHolder sampleToQueue = mSamplePool.acquireSample(sample.size);
    131         sampleToQueue.size = sample.size;
    132         sampleToQueue.clearData();
    133         sampleToQueue.data.put(sample.data);
    134         sampleToQueue.timeUs = sample.timeUs;
    135         sampleToQueue.flags = sample.flags;
    136 
    137         synchronized (this) {
    138             if (mPlayingSampleQueues[index] != null) {
    139                 mPlayingSampleQueues[index].queueSample(sampleToQueue);
    140             }
    141         }
    142     }
    143 
    144     @Override
    145     public boolean isWriteSpeedSlow(int sampleSize, long durationNs) {
    146         // Since SimpleSampleBuffer write samples only to memory (not to physical storage),
    147         // write speed is always fine.
    148         return false;
    149     }
    150 
    151     @Override
    152     public void handleWriteSpeedSlow() {
    153         // no-op
    154     }
    155 
    156     @Override
    157     public synchronized boolean continueBuffering(long positionUs) {
    158         for (SampleQueue queue : mPlayingSampleQueues) {
    159             if (queue == null) {
    160                 continue;
    161             }
    162             if (queue.getLastQueuedPositionUs() == null
    163                     || positionUs > queue.getLastQueuedPositionUs()) {
    164                 // No more buffered data.
    165                 return false;
    166             }
    167         }
    168         return true;
    169     }
    170 
    171     @Override
    172     public void seekTo(long positionUs) {
    173         // Not used.
    174     }
    175 
    176     @Override
    177     public void release() {
    178         // Not used.
    179     }
    180 }
    181