blob: d2721edcfaecb390cfa4f37a74419bfe613c3894 [file] [log] [blame]
Wei Jiabc2fb722014-07-08 16:37:57 -07001/*
2 * Copyright (C) 2014 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//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayerDecoderPassThrough"
19#include <utils/Log.h>
20#include <inttypes.h>
21
22#include "NuPlayerDecoderPassThrough.h"
23
Wei Jiac6cfd702014-11-11 16:33:20 -080024#include "NuPlayerRenderer.h"
25#include "NuPlayerSource.h"
26
Wei Jiabc2fb722014-07-08 16:37:57 -070027#include <media/ICrypto.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/MediaDefs.h>
32#include <media/stagefright/MediaErrors.h>
33
34namespace android {
35
Phil Burkc5cc2e22014-09-09 20:08:39 -070036static const size_t kMaxCachedBytes = 200000;
37// The buffers will contain a bit less than kAggregateBufferSizeBytes.
38// So we can start off with just enough buffers to keep the cache full.
39static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
Wei Jiabc2fb722014-07-08 16:37:57 -070040
41NuPlayer::DecoderPassThrough::DecoderPassThrough(
Wei Jiac6cfd702014-11-11 16:33:20 -080042 const sp<AMessage> &notify,
43 const sp<Source> &source,
44 const sp<Renderer> &renderer)
45 : Decoder(notify, source),
Wei Jiabc2fb722014-07-08 16:37:57 -070046 mNotify(notify),
Wei Jiac6cfd702014-11-11 16:33:20 -080047 mSource(source),
48 mRenderer(renderer),
49 mSkipRenderingUntilMediaTimeUs(-1ll),
Wei Jiabc2fb722014-07-08 16:37:57 -070050 mBufferGeneration(0),
51 mReachedEOS(true),
Phil Burkc5cc2e22014-09-09 20:08:39 -070052 mPendingBuffersToFill(0),
53 mPendingBuffersToDrain(0),
Chong Zhangde01afb2014-08-13 13:48:10 -070054 mCachedBytes(0),
Wei Jiabc2fb722014-07-08 16:37:57 -070055 mComponentName("pass through decoder") {
Wei Jiac6cfd702014-11-11 16:33:20 -080056 ALOGW_IF(renderer == NULL, "expect a non-NULL renderer");
Wei Jiabc2fb722014-07-08 16:37:57 -070057 mDecoderLooper = new ALooper;
58 mDecoderLooper->setName("NuPlayerDecoderPassThrough");
59 mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
60}
61
62NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
63}
64
65void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
66 sp<AMessage> msg = new AMessage(kWhatConfigure, id());
67 msg->setMessage("format", format);
68 msg->post();
69}
70
71void NuPlayer::DecoderPassThrough::init() {
72 mDecoderLooper->registerHandler(this);
73}
74
75void NuPlayer::DecoderPassThrough::signalFlush() {
76 (new AMessage(kWhatFlush, id()))->post();
77}
78
79void NuPlayer::DecoderPassThrough::signalResume() {
80 (new AMessage(kWhatResume, id()))->post();
81}
82
83void NuPlayer::DecoderPassThrough::initiateShutdown() {
84 (new AMessage(kWhatShutdown, id()))->post();
85}
86
87bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
88 const sp<AMessage> & /* targetFormat */) const {
89 return true;
90}
91
92void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
93 ALOGV("[%s] onConfigure", mComponentName.c_str());
Chong Zhangde01afb2014-08-13 13:48:10 -070094 mCachedBytes = 0;
Phil Burkc5cc2e22014-09-09 20:08:39 -070095 mPendingBuffersToFill = 0;
96 mPendingBuffersToDrain = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -070097 mReachedEOS = false;
98 ++mBufferGeneration;
99
Phil Burkc5cc2e22014-09-09 20:08:39 -0700100 requestMaxBuffers();
Wei Jiabc2fb722014-07-08 16:37:57 -0700101
Wei Jiac6cfd702014-11-11 16:33:20 -0800102 uint32_t flags;
103 int64_t durationUs;
104 if (mSource->getDuration(&durationUs) == OK &&
105 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
106 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
107 } else {
108 flags = AUDIO_OUTPUT_FLAG_NONE;
109 }
110
111 mRenderer->openAudioSink(
112 format, true /* offloadOnly */, false /* hasVideo */, flags);
Wei Jiabc2fb722014-07-08 16:37:57 -0700113}
114
115bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
116 int32_t generation;
117 CHECK(msg->findInt32("generation", &generation));
118 return generation != mBufferGeneration;
119}
120
Phil Burkc5cc2e22014-09-09 20:08:39 -0700121bool NuPlayer::DecoderPassThrough::requestABuffer() {
122 if (mCachedBytes >= kMaxCachedBytes) {
123 ALOGV("[%s] mCachedBytes = %zu",
124 mComponentName.c_str(), mCachedBytes);
125 return false;
126 }
127 if (mReachedEOS) {
128 ALOGV("[%s] reached EOS", mComponentName.c_str());
129 return false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700130 }
131
132 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
133 reply->setInt32("generation", mBufferGeneration);
134
135 sp<AMessage> notify = mNotify->dup();
136 notify->setInt32("what", kWhatFillThisBuffer);
137 notify->setMessage("reply", reply);
138 notify->post();
Phil Burkc5cc2e22014-09-09 20:08:39 -0700139 mPendingBuffersToFill++;
140 ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill,
141 mPendingBuffersToDrain);
Wei Jiabc2fb722014-07-08 16:37:57 -0700142
Phil Burkc5cc2e22014-09-09 20:08:39 -0700143 return true;
Wei Jiabc2fb722014-07-08 16:37:57 -0700144}
145
146void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
147 const sp<AMessage> &msg) {
Phil Burkc5cc2e22014-09-09 20:08:39 -0700148 --mPendingBuffersToFill;
Wei Jiabc2fb722014-07-08 16:37:57 -0700149 if (mReachedEOS) {
150 return;
151 }
152
153 sp<ABuffer> buffer;
154 msg->findBuffer("buffer", &buffer);
155 if (buffer == NULL) {
156 mReachedEOS = true;
Wei Jiac6cfd702014-11-11 16:33:20 -0800157 if (mRenderer != NULL) {
158 mRenderer->queueEOS(true /* audio */, ERROR_END_OF_STREAM);
159 }
Wei Jiabc2fb722014-07-08 16:37:57 -0700160 return;
161 }
162
Wei Jiac6cfd702014-11-11 16:33:20 -0800163 sp<AMessage> extra;
164 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
165 int64_t resumeAtMediaTimeUs;
166 if (extra->findInt64(
167 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
168 ALOGI("[%s] suppressing rendering until %lld us",
169 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
170 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
171 }
172 }
173
174 int32_t bufferSize = buffer->size();
175 mCachedBytes += bufferSize;
176
177 if (mSkipRenderingUntilMediaTimeUs >= 0) {
178 int64_t timeUs = 0;
179 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
180
181 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
182 ALOGV("[%s] dropping buffer at time %lld as requested.",
183 mComponentName.c_str(), (long long)timeUs);
184
185 onBufferConsumed(bufferSize);
186 return;
187 }
188
189 mSkipRenderingUntilMediaTimeUs = -1;
190 }
191
192 if (mRenderer == NULL) {
193 onBufferConsumed(bufferSize);
194 return;
195 }
Chong Zhangde01afb2014-08-13 13:48:10 -0700196
Wei Jiabc2fb722014-07-08 16:37:57 -0700197 sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
198 reply->setInt32("generation", mBufferGeneration);
Wei Jiac6cfd702014-11-11 16:33:20 -0800199 reply->setInt32("size", bufferSize);
Wei Jiabc2fb722014-07-08 16:37:57 -0700200
Wei Jiac6cfd702014-11-11 16:33:20 -0800201 mRenderer->queueBuffer(true /* audio */, buffer, reply);
202
Phil Burkc5cc2e22014-09-09 20:08:39 -0700203 ++mPendingBuffersToDrain;
204 ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
205 mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
Wei Jiabc2fb722014-07-08 16:37:57 -0700206}
207
Chong Zhangde01afb2014-08-13 13:48:10 -0700208void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
Phil Burkc5cc2e22014-09-09 20:08:39 -0700209 --mPendingBuffersToDrain;
Chong Zhangde01afb2014-08-13 13:48:10 -0700210 mCachedBytes -= size;
Phil Burkc5cc2e22014-09-09 20:08:39 -0700211 ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
212 mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
Lajos Molnar178e5062014-09-09 20:08:39 -0700213 requestABuffer();
Wei Jiabc2fb722014-07-08 16:37:57 -0700214}
215
216void NuPlayer::DecoderPassThrough::onFlush() {
217 ++mBufferGeneration;
Wei Jiac6cfd702014-11-11 16:33:20 -0800218 mSkipRenderingUntilMediaTimeUs = -1;
219
220 if (mRenderer != NULL) {
221 mRenderer->flush(true /* audio */);
222 }
Wei Jiabc2fb722014-07-08 16:37:57 -0700223
224 sp<AMessage> notify = mNotify->dup();
225 notify->setInt32("what", kWhatFlushCompleted);
226 notify->post();
Phil Burkc5cc2e22014-09-09 20:08:39 -0700227 mPendingBuffersToFill = 0;
228 mPendingBuffersToDrain = 0;
Chong Zhangde01afb2014-08-13 13:48:10 -0700229 mCachedBytes = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -0700230 mReachedEOS = false;
231}
232
Phil Burkc5cc2e22014-09-09 20:08:39 -0700233void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
234 for (size_t i = 0; i < kMaxPendingBuffers; i++) {
235 if (!requestABuffer()) {
236 break;
237 }
238 }
239}
240
Wei Jiabc2fb722014-07-08 16:37:57 -0700241void NuPlayer::DecoderPassThrough::onShutdown() {
242 ++mBufferGeneration;
Wei Jiac6cfd702014-11-11 16:33:20 -0800243 mSkipRenderingUntilMediaTimeUs = -1;
Wei Jiabc2fb722014-07-08 16:37:57 -0700244
245 sp<AMessage> notify = mNotify->dup();
246 notify->setInt32("what", kWhatShutdownCompleted);
247 notify->post();
248 mReachedEOS = true;
249}
250
251void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
252 ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
253 msg->debugString().c_str());
254
255 switch (msg->what()) {
256 case kWhatConfigure:
257 {
258 sp<AMessage> format;
259 CHECK(msg->findMessage("format", &format));
260 onConfigure(format);
261 break;
262 }
263
264 case kWhatRequestABuffer:
265 {
266 if (!isStaleReply(msg)) {
267 requestABuffer();
268 }
269
270 break;
271 }
272
273 case kWhatInputBufferFilled:
274 {
275 if (!isStaleReply(msg)) {
276 onInputBufferFilled(msg);
277 }
278 break;
279 }
280
281 case kWhatBufferConsumed:
282 {
283 if (!isStaleReply(msg)) {
Chong Zhangde01afb2014-08-13 13:48:10 -0700284 int32_t size;
285 CHECK(msg->findInt32("size", &size));
286 onBufferConsumed(size);
Wei Jiabc2fb722014-07-08 16:37:57 -0700287 }
288 break;
289 }
290
291 case kWhatFlush:
292 {
293 onFlush();
294 break;
295 }
296
297 case kWhatResume:
298 {
Phil Burkc5cc2e22014-09-09 20:08:39 -0700299 requestMaxBuffers();
Wei Jiabc2fb722014-07-08 16:37:57 -0700300 break;
301 }
302
303 case kWhatShutdown:
304 {
305 onShutdown();
306 break;
307 }
308
309 default:
310 TRESPASS();
311 break;
312 }
313}
314
315} // namespace android