• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SimpleSampleBuffer(PlaybackBufferListener bufferListener)45     public SimpleSampleBuffer(PlaybackBufferListener bufferListener) {
46         if (bufferListener != null) {
47             // Disables trickplay.
48             bufferListener.onBufferStateChanged(false);
49         }
50     }
51 
52     @Override
init(@onNull List<String> ids, @NonNull List<MediaFormat> mediaFormats)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
setEos()63     public void setEos() {
64         mEos = true;
65     }
66 
reachedEos()67     private boolean reachedEos() {
68         return mEos;
69     }
70 
71     @Override
selectTrack(int index)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
deselectTrack(int index)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
getBufferedPositionUs()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
readSample(int track, SampleHolder sampleHolder)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
writeSample(int index, SampleHolder sample, ConditionVariable conditionVariable)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
isWriteSpeedSlow(int sampleSize, long durationNs)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
handleWriteSpeedSlow()152     public void handleWriteSpeedSlow() {
153         // no-op
154     }
155 
156     @Override
continueBuffering(long positionUs)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
seekTo(long positionUs)172     public void seekTo(long positionUs) {
173         // Not used.
174     }
175 
176     @Override
release()177     public void release() {
178         // Not used.
179     }
180 }
181