blob: 6cc43fd2ec5af8ccfda4523e61918b36dc52f7c5 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
Chong Zhang7137ec72014-11-12 16:41:05 -08002 * Copyright 2014 The Android Open Source Project
Andreas Huberf9334412010-12-15 15:17:42 -08003 *
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 "NuPlayerDecoder"
19#include <utils/Log.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080020#include <inttypes.h>
Andreas Huberf9334412010-12-15 15:17:42 -080021
Chong Zhang7137ec72014-11-12 16:41:05 -080022#include "NuPlayerCCDecoder.h"
Andreas Huberf9334412010-12-15 15:17:42 -080023#include "NuPlayerDecoder.h"
Wei Jiac6cfd702014-11-11 16:33:20 -080024#include "NuPlayerRenderer.h"
25#include "NuPlayerSource.h"
26
Lajos Molnar1cd13982014-01-17 15:12:51 -080027#include <media/ICrypto.h>
Andreas Huberf9334412010-12-15 15:17:42 -080028#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080030#include <media/stagefright/foundation/AMessage.h>
Lajos Molnar09524832014-07-17 14:29:51 -070031#include <media/stagefright/MediaBuffer.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080032#include <media/stagefright/MediaCodec.h>
Andreas Huberf9334412010-12-15 15:17:42 -080033#include <media/stagefright/MediaDefs.h>
Lajos Molnar1cd13982014-01-17 15:12:51 -080034#include <media/stagefright/MediaErrors.h>
Andreas Huberf9334412010-12-15 15:17:42 -080035
Chong Zhang7137ec72014-11-12 16:41:05 -080036#include "avc_utils.h"
37#include "ATSParser.h"
38
Andreas Huberf9334412010-12-15 15:17:42 -080039namespace android {
40
41NuPlayer::Decoder::Decoder(
Glenn Kasten11731182011-02-08 17:26:17 -080042 const sp<AMessage> &notify,
Wei Jiac6cfd702014-11-11 16:33:20 -080043 const sp<Source> &source,
44 const sp<Renderer> &renderer,
Chong Zhang7137ec72014-11-12 16:41:05 -080045 const sp<NativeWindowWrapper> &nativeWindow,
46 const sp<CCDecoder> &ccDecoder)
Andy Hung202bce12014-12-03 11:47:36 -080047 : DecoderBase(notify),
Lajos Molnar1cd13982014-01-17 15:12:51 -080048 mNativeWindow(nativeWindow),
Wei Jiac6cfd702014-11-11 16:33:20 -080049 mSource(source),
50 mRenderer(renderer),
Chong Zhang7137ec72014-11-12 16:41:05 -080051 mCCDecoder(ccDecoder),
Wei Jiac6cfd702014-11-11 16:33:20 -080052 mSkipRenderingUntilMediaTimeUs(-1ll),
Chong Zhang7137ec72014-11-12 16:41:05 -080053 mNumFramesTotal(0ll),
54 mNumFramesDropped(0ll),
55 mIsAudio(true),
56 mIsVideoAVC(false),
57 mIsSecure(false),
58 mFormatChangePending(false),
Wei Jia704e7262014-06-04 16:21:56 -070059 mPaused(true),
Chong Zhangf8d71772014-11-26 15:08:34 -080060 mResumePending(false),
Lajos Molnar1cd13982014-01-17 15:12:51 -080061 mComponentName("decoder") {
Lajos Molnar1cd13982014-01-17 15:12:51 -080062 mCodecLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070063 mCodecLooper->setName("NPDecoder-CL");
Lajos Molnar1cd13982014-01-17 15:12:51 -080064 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
Andreas Huberf9334412010-12-15 15:17:42 -080065}
66
67NuPlayer::Decoder::~Decoder() {
Wei Jia4923cee2014-09-24 14:25:19 -070068 releaseAndResetMediaBuffers();
Andreas Huberf9334412010-12-15 15:17:42 -080069}
70
Chong Zhang7137ec72014-11-12 16:41:05 -080071void NuPlayer::Decoder::getStats(
72 int64_t *numFramesTotal,
73 int64_t *numFramesDropped) const {
74 *numFramesTotal = mNumFramesTotal;
75 *numFramesDropped = mNumFramesDropped;
Lajos Molnar09524832014-07-17 14:29:51 -070076}
77
Chong Zhang7137ec72014-11-12 16:41:05 -080078void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
79 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
80
81 switch (msg->what()) {
82 case kWhatCodecNotify:
83 {
84 if (!isStaleReply(msg)) {
85 int32_t numInput, numOutput;
86
87 if (!msg->findInt32("input-buffers", &numInput)) {
88 numInput = INT32_MAX;
89 }
90
91 if (!msg->findInt32("output-buffers", &numOutput)) {
92 numOutput = INT32_MAX;
93 }
94
95 if (!mPaused) {
96 while (numInput-- > 0 && handleAnInputBuffer()) {}
97 }
98
99 while (numOutput-- > 0 && handleAnOutputBuffer()) {}
100 }
101
102 requestCodecNotification();
Lajos Molnar87603c02014-08-20 19:25:30 -0700103 break;
104 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800105
106 case kWhatRenderBuffer:
107 {
108 if (!isStaleReply(msg)) {
109 onRenderBuffer(msg);
110 }
111 break;
112 }
113
114 default:
115 DecoderBase::onMessageReceived(msg);
116 break;
Lajos Molnar87603c02014-08-20 19:25:30 -0700117 }
118}
119
Lajos Molnar1cd13982014-01-17 15:12:51 -0800120void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
Andreas Huberf9334412010-12-15 15:17:42 -0800121 CHECK(mCodec == NULL);
Andreas Huberf9334412010-12-15 15:17:42 -0800122
Chong Zhang7137ec72014-11-12 16:41:05 -0800123 mFormatChangePending = false;
124
Lajos Molnar1cd13982014-01-17 15:12:51 -0800125 ++mBufferGeneration;
126
Andreas Huber84066782011-08-16 09:34:26 -0700127 AString mime;
128 CHECK(format->findString("mime", &mime));
Andreas Huberf9334412010-12-15 15:17:42 -0800129
Chong Zhang7137ec72014-11-12 16:41:05 -0800130 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
131 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
132
Lajos Molnar1cd13982014-01-17 15:12:51 -0800133 sp<Surface> surface = NULL;
134 if (mNativeWindow != NULL) {
135 surface = mNativeWindow->getSurfaceTextureClient();
Andreas Huber84066782011-08-16 09:34:26 -0700136 }
Andreas Huberf9334412010-12-15 15:17:42 -0800137
Lajos Molnar1cd13982014-01-17 15:12:51 -0800138 mComponentName = mime;
139 mComponentName.append(" decoder");
140 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get());
141
142 mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
Lajos Molnar09524832014-07-17 14:29:51 -0700143 int32_t secure = 0;
144 if (format->findInt32("secure", &secure) && secure != 0) {
145 if (mCodec != NULL) {
146 mCodec->getName(&mComponentName);
147 mComponentName.append(".secure");
148 mCodec->release();
149 ALOGI("[%s] creating", mComponentName.c_str());
150 mCodec = MediaCodec::CreateByComponentName(
151 mCodecLooper, mComponentName.c_str());
152 }
153 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800154 if (mCodec == NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700155 ALOGE("Failed to create %s%s decoder",
156 (secure ? "secure " : ""), mime.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800157 handleError(UNKNOWN_ERROR);
158 return;
159 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800160 mIsSecure = secure;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800161
162 mCodec->getName(&mComponentName);
163
Lajos Molnar14986f62014-09-15 11:04:44 -0700164 status_t err;
Glenn Kasten11731182011-02-08 17:26:17 -0800165 if (mNativeWindow != NULL) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800166 // disconnect from surface as MediaCodec will reconnect
Lajos Molnar14986f62014-09-15 11:04:44 -0700167 err = native_window_api_disconnect(
168 surface.get(), NATIVE_WINDOW_API_MEDIA);
169 // We treat this as a warning, as this is a preparatory step.
170 // Codec will try to connect to the surface, which is where
171 // any error signaling will occur.
172 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800173 }
Lajos Molnar14986f62014-09-15 11:04:44 -0700174 err = mCodec->configure(
Lajos Molnar1cd13982014-01-17 15:12:51 -0800175 format, surface, NULL /* crypto */, 0 /* flags */);
176 if (err != OK) {
177 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700178 mCodec->release();
179 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800180 handleError(err);
181 return;
182 }
Lajos Molnar87603c02014-08-20 19:25:30 -0700183 rememberCodecSpecificData(format);
184
Lajos Molnar1cd13982014-01-17 15:12:51 -0800185 // the following should work in configured state
186 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
187 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
188
189 err = mCodec->start();
190 if (err != OK) {
191 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700192 mCodec->release();
193 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800194 handleError(err);
195 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800196 }
197
Lajos Molnar1cd13982014-01-17 15:12:51 -0800198 // the following should work after start
199 CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
Lajos Molnar09524832014-07-17 14:29:51 -0700200 releaseAndResetMediaBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800201 CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers));
202 ALOGV("[%s] got %zu input and %zu output buffers",
203 mComponentName.c_str(),
204 mInputBuffers.size(),
205 mOutputBuffers.size());
Andreas Huber078cfcf2011-09-15 12:25:04 -0700206
Wei Jiac6cfd702014-11-11 16:33:20 -0800207 if (mRenderer != NULL) {
208 requestCodecNotification();
209 }
Wei Jia704e7262014-06-04 16:21:56 -0700210 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800211 mResumePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800212}
Andreas Huber078cfcf2011-09-15 12:25:04 -0700213
Chong Zhang7137ec72014-11-12 16:41:05 -0800214void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
215 bool hadNoRenderer = (mRenderer == NULL);
216 mRenderer = renderer;
217 if (hadNoRenderer && mRenderer != NULL) {
218 requestCodecNotification();
219 }
220}
221
222void NuPlayer::Decoder::onGetInputBuffers(
223 Vector<sp<ABuffer> > *dstBuffers) {
224 dstBuffers->clear();
225 for (size_t i = 0; i < mInputBuffers.size(); i++) {
226 dstBuffers->push(mInputBuffers[i]);
227 }
228}
229
Chong Zhangf8d71772014-11-26 15:08:34 -0800230void NuPlayer::Decoder::onResume(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800231 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800232
233 if (notifyComplete) {
234 mResumePending = true;
235 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800236}
237
238void NuPlayer::Decoder::onFlush(bool notifyComplete) {
239 if (mCCDecoder != NULL) {
240 mCCDecoder->flush();
241 }
242
243 if (mRenderer != NULL) {
244 mRenderer->flush(mIsAudio, notifyComplete);
245 mRenderer->signalTimeDiscontinuity();
246 }
247
248 status_t err = OK;
249 if (mCodec != NULL) {
250 err = mCodec->flush();
251 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
252 ++mBufferGeneration;
253 }
254
255 if (err != OK) {
256 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
257 handleError(err);
258 // finish with posting kWhatFlushCompleted.
259 // we attempt to release the buffers even if flush fails.
260 }
261 releaseAndResetMediaBuffers();
262
263 if (notifyComplete) {
264 sp<AMessage> notify = mNotify->dup();
265 notify->setInt32("what", kWhatFlushCompleted);
266 notify->post();
267 mPaused = true;
268 }
269}
270
271void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
272 status_t err = OK;
Chong Zhangf8d71772014-11-26 15:08:34 -0800273
274 // if there is a pending resume request, notify complete now
275 notifyResumeCompleteIfNecessary();
276
Chong Zhang7137ec72014-11-12 16:41:05 -0800277 if (mCodec != NULL) {
278 err = mCodec->release();
279 mCodec = NULL;
280 ++mBufferGeneration;
281
282 if (mNativeWindow != NULL) {
283 // reconnect to surface as MediaCodec disconnected from it
284 status_t error =
285 native_window_api_connect(
286 mNativeWindow->getNativeWindow().get(),
287 NATIVE_WINDOW_API_MEDIA);
288 ALOGW_IF(error != NO_ERROR,
289 "[%s] failed to connect to native window, error=%d",
290 mComponentName.c_str(), error);
291 }
292 mComponentName = "decoder";
293 }
294
295 releaseAndResetMediaBuffers();
296
297 if (err != OK) {
298 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
299 handleError(err);
300 // finish with posting kWhatShutdownCompleted.
301 }
302
303 if (notifyComplete) {
304 sp<AMessage> notify = mNotify->dup();
305 notify->setInt32("what", kWhatShutdownCompleted);
306 notify->post();
307 mPaused = true;
308 }
309}
310
311void NuPlayer::Decoder::doRequestBuffers() {
312 if (mFormatChangePending) {
313 return;
314 }
315 status_t err = OK;
316 while (!mDequeuedInputBuffers.empty()) {
317 size_t bufferIx = *mDequeuedInputBuffers.begin();
318 sp<AMessage> msg = new AMessage();
319 msg->setSize("buffer-ix", bufferIx);
320 err = fetchInputData(msg);
321 if (err != OK) {
322 break;
323 }
324 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
325
326 if (!mPendingInputMessages.empty()
327 || !onInputBufferFetched(msg)) {
328 mPendingInputMessages.push_back(msg);
Lajos Molnar09524832014-07-17 14:29:51 -0700329 }
330 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800331
332 if (err == -EWOULDBLOCK
333 && mSource->feedMoreTSData() == OK) {
334 scheduleRequestBuffers();
Wei Jia81e50d02014-07-24 10:28:47 -0700335 }
Lajos Molnar09524832014-07-17 14:29:51 -0700336}
337
Lajos Molnar1cd13982014-01-17 15:12:51 -0800338bool NuPlayer::Decoder::handleAnInputBuffer() {
Chong Zhang7137ec72014-11-12 16:41:05 -0800339 if (mFormatChangePending) {
340 return false;
341 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800342 size_t bufferIx = -1;
343 status_t res = mCodec->dequeueInputBuffer(&bufferIx);
344 ALOGV("[%s] dequeued input: %d",
345 mComponentName.c_str(), res == OK ? (int)bufferIx : res);
346 if (res != OK) {
347 if (res != -EAGAIN) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700348 ALOGE("Failed to dequeue input buffer for %s (err=%d)",
349 mComponentName.c_str(), res);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800350 handleError(res);
351 }
352 return false;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700353 }
354
Lajos Molnar1cd13982014-01-17 15:12:51 -0800355 CHECK_LT(bufferIx, mInputBuffers.size());
Andreas Huberf9334412010-12-15 15:17:42 -0800356
Lajos Molnar09524832014-07-17 14:29:51 -0700357 if (mMediaBuffers[bufferIx] != NULL) {
358 mMediaBuffers[bufferIx]->release();
359 mMediaBuffers.editItemAt(bufferIx) = NULL;
360 }
361 mInputBufferIsDequeued.editItemAt(bufferIx) = true;
362
Lajos Molnar87603c02014-08-20 19:25:30 -0700363 if (!mCSDsToSubmit.isEmpty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800364 sp<AMessage> msg = new AMessage();
365 msg->setSize("buffer-ix", bufferIx);
366
Lajos Molnar87603c02014-08-20 19:25:30 -0700367 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
368 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
Chong Zhang7137ec72014-11-12 16:41:05 -0800369 msg->setBuffer("buffer", buffer);
Lajos Molnar87603c02014-08-20 19:25:30 -0700370 mCSDsToSubmit.removeAt(0);
Wei Jia15c37402016-01-07 16:03:03 -0800371 if (!onInputBufferFetched(msg)) {
372 handleError(UNKNOWN_ERROR);
373 return false;
374 }
Wei Jia2245fc62014-10-02 15:12:25 -0700375 return true;
376 }
377
378 while (!mPendingInputMessages.empty()) {
379 sp<AMessage> msg = *mPendingInputMessages.begin();
Chong Zhang7137ec72014-11-12 16:41:05 -0800380 if (!onInputBufferFetched(msg)) {
Wei Jia2245fc62014-10-02 15:12:25 -0700381 break;
382 }
383 mPendingInputMessages.erase(mPendingInputMessages.begin());
384 }
385
386 if (!mInputBufferIsDequeued.editItemAt(bufferIx)) {
Lajos Molnar87603c02014-08-20 19:25:30 -0700387 return true;
388 }
389
Chong Zhang7137ec72014-11-12 16:41:05 -0800390 mDequeuedInputBuffers.push_back(bufferIx);
391
392 onRequestInputBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800393 return true;
394}
395
Chong Zhang7137ec72014-11-12 16:41:05 -0800396bool NuPlayer::Decoder::handleAnOutputBuffer() {
397 if (mFormatChangePending) {
398 return false;
399 }
400 size_t bufferIx = -1;
401 size_t offset;
402 size_t size;
403 int64_t timeUs;
404 uint32_t flags;
405 status_t res = mCodec->dequeueOutputBuffer(
406 &bufferIx, &offset, &size, &timeUs, &flags);
407
408 if (res != OK) {
409 ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
410 } else {
411 ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
412 mComponentName.c_str(), (int)bufferIx, timeUs, flags);
413 }
414
415 if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
416 res = mCodec->getOutputBuffers(&mOutputBuffers);
417 if (res != OK) {
418 ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
419 mComponentName.c_str(), res);
420 handleError(res);
421 return false;
422 }
423 // NuPlayer ignores this
424 return true;
425 } else if (res == INFO_FORMAT_CHANGED) {
426 sp<AMessage> format = new AMessage();
427 res = mCodec->getOutputFormat(&format);
428 if (res != OK) {
429 ALOGE("Failed to get output format for %s after INFO event (err=%d)",
430 mComponentName.c_str(), res);
431 handleError(res);
432 return false;
433 }
434
435 if (!mIsAudio) {
436 sp<AMessage> notify = mNotify->dup();
437 notify->setInt32("what", kWhatVideoSizeChanged);
438 notify->setMessage("format", format);
439 notify->post();
440 } else if (mRenderer != NULL) {
441 uint32_t flags;
442 int64_t durationUs;
443 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
444 if (!hasVideo &&
445 mSource->getDuration(&durationUs) == OK &&
446 durationUs
447 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
448 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
449 } else {
450 flags = AUDIO_OUTPUT_FLAG_NONE;
451 }
452
Andy Hung202bce12014-12-03 11:47:36 -0800453 res = mRenderer->openAudioSink(
454 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaded */);
455 if (res != OK) {
456 ALOGE("Failed to open AudioSink on format change for %s (err=%d)",
457 mComponentName.c_str(), res);
458 handleError(res);
459 return false;
460 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800461 }
462 return true;
463 } else if (res == INFO_DISCONTINUITY) {
464 // nothing to do
465 return true;
466 } else if (res != OK) {
467 if (res != -EAGAIN) {
468 ALOGE("Failed to dequeue output buffer for %s (err=%d)",
469 mComponentName.c_str(), res);
470 handleError(res);
471 }
472 return false;
473 }
474
475 CHECK_LT(bufferIx, mOutputBuffers.size());
476 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
477 buffer->setRange(offset, size);
478 buffer->meta()->clear();
479 buffer->meta()->setInt64("timeUs", timeUs);
480 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
481 buffer->meta()->setInt32("eos", true);
Wei Jia474d7c72014-12-04 15:12:13 -0800482 notifyResumeCompleteIfNecessary();
Chong Zhang7137ec72014-11-12 16:41:05 -0800483 }
484 // we do not expect CODECCONFIG or SYNCFRAME for decoder
485
486 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
487 reply->setSize("buffer-ix", bufferIx);
488 reply->setInt32("generation", mBufferGeneration);
489
490 if (mSkipRenderingUntilMediaTimeUs >= 0) {
491 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
492 ALOGV("[%s] dropping buffer at time %lld as requested.",
493 mComponentName.c_str(), (long long)timeUs);
494
495 reply->post();
496 return true;
497 }
498
499 mSkipRenderingUntilMediaTimeUs = -1;
500 }
501
Chong Zhangf8d71772014-11-26 15:08:34 -0800502 // wait until 1st frame comes out to signal resume complete
503 notifyResumeCompleteIfNecessary();
504
Chong Zhang7137ec72014-11-12 16:41:05 -0800505 if (mRenderer != NULL) {
506 // send the buffer to renderer.
507 mRenderer->queueBuffer(mIsAudio, buffer, reply);
508 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
509 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
510 }
511 }
512
513 return true;
514}
515
516void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
517 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
518 if (mMediaBuffers[i] != NULL) {
519 mMediaBuffers[i]->release();
520 mMediaBuffers.editItemAt(i) = NULL;
521 }
522 }
523 mMediaBuffers.resize(mInputBuffers.size());
524 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
525 mMediaBuffers.editItemAt(i) = NULL;
526 }
527 mInputBufferIsDequeued.clear();
528 mInputBufferIsDequeued.resize(mInputBuffers.size());
529 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
530 mInputBufferIsDequeued.editItemAt(i) = false;
531 }
532
533 mPendingInputMessages.clear();
534 mDequeuedInputBuffers.clear();
535 mSkipRenderingUntilMediaTimeUs = -1;
536}
537
538void NuPlayer::Decoder::requestCodecNotification() {
539 if (mFormatChangePending) {
540 return;
541 }
542 if (mCodec != NULL) {
543 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
544 reply->setInt32("generation", mBufferGeneration);
545 mCodec->requestActivityNotification(reply);
546 }
547}
548
549bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
550 int32_t generation;
551 CHECK(msg->findInt32("generation", &generation));
552 return generation != mBufferGeneration;
553}
554
555status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
556 sp<ABuffer> accessUnit;
557 bool dropAccessUnit;
558 do {
559 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
560
561 if (err == -EWOULDBLOCK) {
562 return err;
563 } else if (err != OK) {
564 if (err == INFO_DISCONTINUITY) {
565 int32_t type;
566 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
567
568 bool formatChange =
569 (mIsAudio &&
570 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
571 || (!mIsAudio &&
572 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
573
574 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
575
576 ALOGI("%s discontinuity (format=%d, time=%d)",
577 mIsAudio ? "audio" : "video", formatChange, timeChange);
578
579 bool seamlessFormatChange = false;
580 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
581 if (formatChange) {
582 seamlessFormatChange =
583 supportsSeamlessFormatChange(newFormat);
584 // treat seamless format change separately
585 formatChange = !seamlessFormatChange;
586 }
587
588 if (formatChange || timeChange) {
589 sp<AMessage> msg = mNotify->dup();
590 msg->setInt32("what", kWhatInputDiscontinuity);
591 msg->setInt32("formatChange", formatChange);
592 msg->post();
593 }
594
595 if (formatChange /* not seamless */) {
596 // must change decoder
597 // return EOS and wait to be killed
598 mFormatChangePending = true;
599 return ERROR_END_OF_STREAM;
600 } else if (timeChange) {
601 // need to flush
602 // TODO: Ideally we shouldn't need a flush upon time
603 // discontinuity, flushing will cause loss of frames.
604 // We probably should queue a time change marker to the
605 // output queue, and handles it in renderer instead.
606 rememberCodecSpecificData(newFormat);
607 onFlush(false /* notifyComplete */);
608 err = OK;
609 } else if (seamlessFormatChange) {
610 // reuse existing decoder and don't flush
611 rememberCodecSpecificData(newFormat);
612 err = OK;
613 } else {
614 // This stream is unaffected by the discontinuity
615 return -EWOULDBLOCK;
616 }
617 }
618
619 reply->setInt32("err", err);
620 return OK;
621 }
622
623 if (!mIsAudio) {
624 ++mNumFramesTotal;
625 }
626
627 dropAccessUnit = false;
628 if (!mIsAudio
629 && !mIsSecure
630 && mRenderer->getVideoLateByUs() > 100000ll
631 && mIsVideoAVC
632 && !IsAVCReferenceFrame(accessUnit)) {
633 dropAccessUnit = true;
634 ++mNumFramesDropped;
635 }
636 } while (dropAccessUnit);
637
638 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
639#if 0
640 int64_t mediaTimeUs;
641 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
642 ALOGV("feeding %s input buffer at media time %.2f secs",
643 mIsAudio ? "audio" : "video",
644 mediaTimeUs / 1E6);
645#endif
646
647 if (mCCDecoder != NULL) {
648 mCCDecoder->decode(accessUnit);
649 }
650
651 reply->setBuffer("buffer", accessUnit);
652
653 return OK;
654}
655
656bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800657 size_t bufferIx;
658 CHECK(msg->findSize("buffer-ix", &bufferIx));
659 CHECK_LT(bufferIx, mInputBuffers.size());
660 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
661
662 sp<ABuffer> buffer;
663 bool hasBuffer = msg->findBuffer("buffer", &buffer);
Lajos Molnar09524832014-07-17 14:29:51 -0700664
665 // handle widevine classic source - that fills an arbitrary input buffer
666 MediaBuffer *mediaBuffer = NULL;
Wei Jia96e92b52014-09-18 17:36:20 -0700667 if (hasBuffer) {
668 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
669 if (mediaBuffer != NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700670 // likely filled another buffer than we requested: adjust buffer index
671 size_t ix;
672 for (ix = 0; ix < mInputBuffers.size(); ix++) {
673 const sp<ABuffer> &buf = mInputBuffers[ix];
674 if (buf->data() == mediaBuffer->data()) {
675 // all input buffers are dequeued on start, hence the check
Wei Jia2245fc62014-10-02 15:12:25 -0700676 if (!mInputBufferIsDequeued[ix]) {
677 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
678 mComponentName.c_str(), ix, bufferIx);
679 mediaBuffer->release();
680 return false;
681 }
Lajos Molnar09524832014-07-17 14:29:51 -0700682
683 // TRICKY: need buffer for the metadata, so instead, set
684 // codecBuffer to the same (though incorrect) buffer to
685 // avoid a memcpy into the codecBuffer
686 codecBuffer = buffer;
687 codecBuffer->setRange(
688 mediaBuffer->range_offset(),
689 mediaBuffer->range_length());
690 bufferIx = ix;
691 break;
692 }
693 }
694 CHECK(ix < mInputBuffers.size());
695 }
696 }
697
Lajos Molnar1cd13982014-01-17 15:12:51 -0800698 if (buffer == NULL /* includes !hasBuffer */) {
699 int32_t streamErr = ERROR_END_OF_STREAM;
700 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
701
702 if (streamErr == OK) {
703 /* buffers are returned to hold on to */
Wei Jia2245fc62014-10-02 15:12:25 -0700704 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800705 }
706
707 // attempt to queue EOS
708 status_t err = mCodec->queueInputBuffer(
709 bufferIx,
710 0,
711 0,
712 0,
713 MediaCodec::BUFFER_FLAG_EOS);
Andy Hungcf31f1e2014-09-23 14:59:01 -0700714 if (err == OK) {
715 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
716 } else if (streamErr == ERROR_END_OF_STREAM) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800717 streamErr = err;
718 // err will not be ERROR_END_OF_STREAM
719 }
720
721 if (streamErr != ERROR_END_OF_STREAM) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700722 ALOGE("Stream error for %s (err=%d), EOS %s queued",
723 mComponentName.c_str(),
724 streamErr,
725 err == OK ? "successfully" : "unsuccessfully");
Lajos Molnar1cd13982014-01-17 15:12:51 -0800726 handleError(streamErr);
727 }
728 } else {
Wei Jiac6cfd702014-11-11 16:33:20 -0800729 sp<AMessage> extra;
730 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
731 int64_t resumeAtMediaTimeUs;
732 if (extra->findInt64(
733 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
734 ALOGI("[%s] suppressing rendering until %lld us",
735 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
736 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
737 }
738 }
739
Lajos Molnar1cd13982014-01-17 15:12:51 -0800740 int64_t timeUs = 0;
741 uint32_t flags = 0;
742 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
743
Lajos Molnar87603c02014-08-20 19:25:30 -0700744 int32_t eos, csd;
745 // we do not expect SYNCFRAME for decoder
Lajos Molnar1cd13982014-01-17 15:12:51 -0800746 if (buffer->meta()->findInt32("eos", &eos) && eos) {
747 flags |= MediaCodec::BUFFER_FLAG_EOS;
Lajos Molnar87603c02014-08-20 19:25:30 -0700748 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
749 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800750 }
751
752 // copy into codec buffer
753 if (buffer != codecBuffer) {
Wei Jia15c37402016-01-07 16:03:03 -0800754 if (buffer->size() > codecBuffer->capacity()) {
755 handleError(ERROR_BUFFER_TOO_SMALL);
756 mDequeuedInputBuffers.push_back(bufferIx);
757 return false;
758 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800759 codecBuffer->setRange(0, buffer->size());
760 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
761 }
762
763 status_t err = mCodec->queueInputBuffer(
764 bufferIx,
765 codecBuffer->offset(),
766 codecBuffer->size(),
767 timeUs,
768 flags);
769 if (err != OK) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700770 if (mediaBuffer != NULL) {
771 mediaBuffer->release();
772 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800773 ALOGE("Failed to queue input buffer for %s (err=%d)",
774 mComponentName.c_str(), err);
775 handleError(err);
Andy Hungcf31f1e2014-09-23 14:59:01 -0700776 } else {
777 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
778 if (mediaBuffer != NULL) {
779 CHECK(mMediaBuffers[bufferIx] == NULL);
780 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
781 }
Lajos Molnar09524832014-07-17 14:29:51 -0700782 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800783 }
Wei Jia2245fc62014-10-02 15:12:25 -0700784 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800785}
786
Lajos Molnar1cd13982014-01-17 15:12:51 -0800787void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
788 status_t err;
789 int32_t render;
790 size_t bufferIx;
791 CHECK(msg->findSize("buffer-ix", &bufferIx));
Wei Jiac6cfd702014-11-11 16:33:20 -0800792
Chong Zhang7137ec72014-11-12 16:41:05 -0800793 if (!mIsAudio) {
Wei Jiac6cfd702014-11-11 16:33:20 -0800794 int64_t timeUs;
795 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
796 buffer->meta()->findInt64("timeUs", &timeUs);
Chong Zhang7137ec72014-11-12 16:41:05 -0800797
798 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
799 mCCDecoder->display(timeUs);
800 }
Wei Jiac6cfd702014-11-11 16:33:20 -0800801 }
802
Lajos Molnar1cd13982014-01-17 15:12:51 -0800803 if (msg->findInt32("render", &render) && render) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -0700804 int64_t timestampNs;
805 CHECK(msg->findInt64("timestampNs", &timestampNs));
806 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800807 } else {
808 err = mCodec->releaseOutputBuffer(bufferIx);
809 }
810 if (err != OK) {
811 ALOGE("failed to release output buffer for %s (err=%d)",
812 mComponentName.c_str(), err);
813 handleError(err);
814 }
815}
816
Chong Zhang7137ec72014-11-12 16:41:05 -0800817bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
818 const sp<AMessage> &targetFormat) const {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800819 if (targetFormat == NULL) {
820 return true;
821 }
822
823 AString mime;
824 if (!targetFormat->findString("mime", &mime)) {
825 return false;
826 }
827
828 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
829 // field-by-field comparison
830 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
831 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
832 int32_t oldVal, newVal;
joakim johansson7abbd4c2015-01-30 14:16:03 +0100833 if (!mInputFormat->findInt32(keys[i], &oldVal) ||
Lajos Molnar1cd13982014-01-17 15:12:51 -0800834 !targetFormat->findInt32(keys[i], &newVal) ||
835 oldVal != newVal) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800836 return false;
837 }
838 }
839
840 sp<ABuffer> oldBuf, newBuf;
joakim johansson7abbd4c2015-01-30 14:16:03 +0100841 if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
Lajos Molnar1cd13982014-01-17 15:12:51 -0800842 targetFormat->findBuffer("csd-0", &newBuf)) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800843 if (oldBuf->size() != newBuf->size()) {
844 return false;
845 }
846 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
847 }
848 }
849 return false;
850}
851
852bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
joakim johansson7abbd4c2015-01-30 14:16:03 +0100853 if (mInputFormat == NULL) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800854 return false;
855 }
856
857 if (targetFormat == NULL) {
858 return true;
859 }
860
861 AString oldMime, newMime;
joakim johansson7abbd4c2015-01-30 14:16:03 +0100862 if (!mInputFormat->findString("mime", &oldMime)
Robert Shih6d0a94e2014-01-23 16:18:22 -0800863 || !targetFormat->findString("mime", &newMime)
864 || !(oldMime == newMime)) {
865 return false;
866 }
867
868 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
869 bool seamless;
870 if (audio) {
871 seamless = supportsSeamlessAudioFormatChange(targetFormat);
872 } else {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800873 int32_t isAdaptive;
874 seamless = (mCodec != NULL &&
875 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
876 isAdaptive);
Robert Shih6d0a94e2014-01-23 16:18:22 -0800877 }
878
879 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
880 return seamless;
881}
882
Chong Zhang7137ec72014-11-12 16:41:05 -0800883void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
884 if (format == NULL) {
Chong Zhangb86e68f2014-08-01 13:46:53 -0700885 return;
886 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800887 mCSDsForCurrentFormat.clear();
888 for (int32_t i = 0; ; ++i) {
889 AString tag = "csd-";
890 tag.append(i);
891 sp<ABuffer> buffer;
892 if (!format->findBuffer(tag.c_str(), &buffer)) {
893 break;
894 }
895 mCSDsForCurrentFormat.push(buffer);
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700896 }
Chong Zhangb86e68f2014-08-01 13:46:53 -0700897}
898
Chong Zhangf8d71772014-11-26 15:08:34 -0800899void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
900 if (mResumePending) {
901 mResumePending = false;
902
903 sp<AMessage> notify = mNotify->dup();
904 notify->setInt32("what", kWhatResumeCompleted);
905 notify->post();
906 }
907}
908
Andreas Huberf9334412010-12-15 15:17:42 -0800909} // namespace android
910