blob: 012d33e0abf138b98f4e3476939626c79a7e6b5e [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)
Andreas Huberf9334412010-12-15 15:17:42 -080047 : mNotify(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),
Lajos Molnar1cd13982014-01-17 15:12:51 -080059 mBufferGeneration(0),
Wei Jia704e7262014-06-04 16:21:56 -070060 mPaused(true),
Chong Zhangf8d71772014-11-26 15:08:34 -080061 mResumePending(false),
Lajos Molnar1cd13982014-01-17 15:12:51 -080062 mComponentName("decoder") {
Lajos Molnar1cd13982014-01-17 15:12:51 -080063 mCodecLooper = new ALooper;
Marco Nelissen9e2b7912014-08-18 16:13:03 -070064 mCodecLooper->setName("NPDecoder-CL");
Lajos Molnar1cd13982014-01-17 15:12:51 -080065 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
Andreas Huberf9334412010-12-15 15:17:42 -080066}
67
68NuPlayer::Decoder::~Decoder() {
Wei Jia4923cee2014-09-24 14:25:19 -070069 releaseAndResetMediaBuffers();
Andreas Huberf9334412010-12-15 15:17:42 -080070}
71
Chong Zhang7137ec72014-11-12 16:41:05 -080072void NuPlayer::Decoder::getStats(
73 int64_t *numFramesTotal,
74 int64_t *numFramesDropped) const {
75 *numFramesTotal = mNumFramesTotal;
76 *numFramesDropped = mNumFramesDropped;
Lajos Molnar09524832014-07-17 14:29:51 -070077}
78
Chong Zhang7137ec72014-11-12 16:41:05 -080079void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
80 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
81
82 switch (msg->what()) {
83 case kWhatCodecNotify:
84 {
85 if (!isStaleReply(msg)) {
86 int32_t numInput, numOutput;
87
88 if (!msg->findInt32("input-buffers", &numInput)) {
89 numInput = INT32_MAX;
90 }
91
92 if (!msg->findInt32("output-buffers", &numOutput)) {
93 numOutput = INT32_MAX;
94 }
95
96 if (!mPaused) {
97 while (numInput-- > 0 && handleAnInputBuffer()) {}
98 }
99
100 while (numOutput-- > 0 && handleAnOutputBuffer()) {}
101 }
102
103 requestCodecNotification();
Lajos Molnar87603c02014-08-20 19:25:30 -0700104 break;
105 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800106
107 case kWhatRenderBuffer:
108 {
109 if (!isStaleReply(msg)) {
110 onRenderBuffer(msg);
111 }
112 break;
113 }
114
115 default:
116 DecoderBase::onMessageReceived(msg);
117 break;
Lajos Molnar87603c02014-08-20 19:25:30 -0700118 }
119}
120
Lajos Molnar1cd13982014-01-17 15:12:51 -0800121void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
Andreas Huberf9334412010-12-15 15:17:42 -0800122 CHECK(mCodec == NULL);
Andreas Huberf9334412010-12-15 15:17:42 -0800123
Chong Zhang7137ec72014-11-12 16:41:05 -0800124 mFormatChangePending = false;
125
Lajos Molnar1cd13982014-01-17 15:12:51 -0800126 ++mBufferGeneration;
127
Andreas Huber84066782011-08-16 09:34:26 -0700128 AString mime;
129 CHECK(format->findString("mime", &mime));
Andreas Huberf9334412010-12-15 15:17:42 -0800130
Chong Zhang7137ec72014-11-12 16:41:05 -0800131 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
132 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
133
Lajos Molnar1cd13982014-01-17 15:12:51 -0800134 sp<Surface> surface = NULL;
135 if (mNativeWindow != NULL) {
136 surface = mNativeWindow->getSurfaceTextureClient();
Andreas Huber84066782011-08-16 09:34:26 -0700137 }
Andreas Huberf9334412010-12-15 15:17:42 -0800138
Lajos Molnar1cd13982014-01-17 15:12:51 -0800139 mComponentName = mime;
140 mComponentName.append(" decoder");
141 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get());
142
143 mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
Lajos Molnar09524832014-07-17 14:29:51 -0700144 int32_t secure = 0;
145 if (format->findInt32("secure", &secure) && secure != 0) {
146 if (mCodec != NULL) {
147 mCodec->getName(&mComponentName);
148 mComponentName.append(".secure");
149 mCodec->release();
150 ALOGI("[%s] creating", mComponentName.c_str());
151 mCodec = MediaCodec::CreateByComponentName(
152 mCodecLooper, mComponentName.c_str());
153 }
154 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800155 if (mCodec == NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700156 ALOGE("Failed to create %s%s decoder",
157 (secure ? "secure " : ""), mime.c_str());
Lajos Molnar1cd13982014-01-17 15:12:51 -0800158 handleError(UNKNOWN_ERROR);
159 return;
160 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800161 mIsSecure = secure;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800162
163 mCodec->getName(&mComponentName);
164
Lajos Molnar14986f62014-09-15 11:04:44 -0700165 status_t err;
Glenn Kasten11731182011-02-08 17:26:17 -0800166 if (mNativeWindow != NULL) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800167 // disconnect from surface as MediaCodec will reconnect
Lajos Molnar14986f62014-09-15 11:04:44 -0700168 err = native_window_api_disconnect(
169 surface.get(), NATIVE_WINDOW_API_MEDIA);
170 // We treat this as a warning, as this is a preparatory step.
171 // Codec will try to connect to the surface, which is where
172 // any error signaling will occur.
173 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800174 }
Lajos Molnar14986f62014-09-15 11:04:44 -0700175 err = mCodec->configure(
Lajos Molnar1cd13982014-01-17 15:12:51 -0800176 format, surface, NULL /* crypto */, 0 /* flags */);
177 if (err != OK) {
178 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700179 mCodec->release();
180 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800181 handleError(err);
182 return;
183 }
Lajos Molnar87603c02014-08-20 19:25:30 -0700184 rememberCodecSpecificData(format);
185
Lajos Molnar1cd13982014-01-17 15:12:51 -0800186 // the following should work in configured state
187 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
188 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
189
190 err = mCodec->start();
191 if (err != OK) {
192 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
Andy Hung2abde2c2014-09-30 14:40:32 -0700193 mCodec->release();
194 mCodec.clear();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800195 handleError(err);
196 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800197 }
198
Lajos Molnar1cd13982014-01-17 15:12:51 -0800199 // the following should work after start
200 CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
Lajos Molnar09524832014-07-17 14:29:51 -0700201 releaseAndResetMediaBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800202 CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers));
203 ALOGV("[%s] got %zu input and %zu output buffers",
204 mComponentName.c_str(),
205 mInputBuffers.size(),
206 mOutputBuffers.size());
Andreas Huber078cfcf2011-09-15 12:25:04 -0700207
Wei Jiac6cfd702014-11-11 16:33:20 -0800208 if (mRenderer != NULL) {
209 requestCodecNotification();
210 }
Wei Jia704e7262014-06-04 16:21:56 -0700211 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800212 mResumePending = false;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800213}
Andreas Huber078cfcf2011-09-15 12:25:04 -0700214
Chong Zhang7137ec72014-11-12 16:41:05 -0800215void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
216 bool hadNoRenderer = (mRenderer == NULL);
217 mRenderer = renderer;
218 if (hadNoRenderer && mRenderer != NULL) {
219 requestCodecNotification();
220 }
221}
222
223void NuPlayer::Decoder::onGetInputBuffers(
224 Vector<sp<ABuffer> > *dstBuffers) {
225 dstBuffers->clear();
226 for (size_t i = 0; i < mInputBuffers.size(); i++) {
227 dstBuffers->push(mInputBuffers[i]);
228 }
229}
230
Chong Zhangf8d71772014-11-26 15:08:34 -0800231void NuPlayer::Decoder::onResume(bool notifyComplete) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800232 mPaused = false;
Chong Zhangf8d71772014-11-26 15:08:34 -0800233
234 if (notifyComplete) {
235 mResumePending = true;
236 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800237}
238
239void NuPlayer::Decoder::onFlush(bool notifyComplete) {
240 if (mCCDecoder != NULL) {
241 mCCDecoder->flush();
242 }
243
244 if (mRenderer != NULL) {
245 mRenderer->flush(mIsAudio, notifyComplete);
246 mRenderer->signalTimeDiscontinuity();
247 }
248
249 status_t err = OK;
250 if (mCodec != NULL) {
251 err = mCodec->flush();
252 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
253 ++mBufferGeneration;
254 }
255
256 if (err != OK) {
257 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
258 handleError(err);
259 // finish with posting kWhatFlushCompleted.
260 // we attempt to release the buffers even if flush fails.
261 }
262 releaseAndResetMediaBuffers();
263
264 if (notifyComplete) {
265 sp<AMessage> notify = mNotify->dup();
266 notify->setInt32("what", kWhatFlushCompleted);
267 notify->post();
268 mPaused = true;
269 }
270}
271
272void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
273 status_t err = OK;
Chong Zhangf8d71772014-11-26 15:08:34 -0800274
275 // if there is a pending resume request, notify complete now
276 notifyResumeCompleteIfNecessary();
277
Chong Zhang7137ec72014-11-12 16:41:05 -0800278 if (mCodec != NULL) {
279 err = mCodec->release();
280 mCodec = NULL;
281 ++mBufferGeneration;
282
283 if (mNativeWindow != NULL) {
284 // reconnect to surface as MediaCodec disconnected from it
285 status_t error =
286 native_window_api_connect(
287 mNativeWindow->getNativeWindow().get(),
288 NATIVE_WINDOW_API_MEDIA);
289 ALOGW_IF(error != NO_ERROR,
290 "[%s] failed to connect to native window, error=%d",
291 mComponentName.c_str(), error);
292 }
293 mComponentName = "decoder";
294 }
295
296 releaseAndResetMediaBuffers();
297
298 if (err != OK) {
299 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
300 handleError(err);
301 // finish with posting kWhatShutdownCompleted.
302 }
303
304 if (notifyComplete) {
305 sp<AMessage> notify = mNotify->dup();
306 notify->setInt32("what", kWhatShutdownCompleted);
307 notify->post();
308 mPaused = true;
309 }
310}
311
312void NuPlayer::Decoder::doRequestBuffers() {
313 if (mFormatChangePending) {
314 return;
315 }
316 status_t err = OK;
317 while (!mDequeuedInputBuffers.empty()) {
318 size_t bufferIx = *mDequeuedInputBuffers.begin();
319 sp<AMessage> msg = new AMessage();
320 msg->setSize("buffer-ix", bufferIx);
321 err = fetchInputData(msg);
322 if (err != OK) {
323 break;
324 }
325 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
326
327 if (!mPendingInputMessages.empty()
328 || !onInputBufferFetched(msg)) {
329 mPendingInputMessages.push_back(msg);
Lajos Molnar09524832014-07-17 14:29:51 -0700330 }
331 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800332
333 if (err == -EWOULDBLOCK
334 && mSource->feedMoreTSData() == OK) {
335 scheduleRequestBuffers();
Wei Jia81e50d02014-07-24 10:28:47 -0700336 }
Lajos Molnar09524832014-07-17 14:29:51 -0700337}
338
Lajos Molnar1cd13982014-01-17 15:12:51 -0800339void NuPlayer::Decoder::handleError(int32_t err)
340{
Andy Hungcf31f1e2014-09-23 14:59:01 -0700341 // We cannot immediately release the codec due to buffers still outstanding
342 // in the renderer. We signal to the player the error so it can shutdown/release the
343 // decoder after flushing and increment the generation to discard unnecessary messages.
344
345 ++mBufferGeneration;
Wei Jiac22c6952014-08-29 14:47:50 -0700346
Lajos Molnar1cd13982014-01-17 15:12:51 -0800347 sp<AMessage> notify = mNotify->dup();
348 notify->setInt32("what", kWhatError);
349 notify->setInt32("err", err);
350 notify->post();
351}
352
353bool NuPlayer::Decoder::handleAnInputBuffer() {
Chong Zhang7137ec72014-11-12 16:41:05 -0800354 if (mFormatChangePending) {
355 return false;
356 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800357 size_t bufferIx = -1;
358 status_t res = mCodec->dequeueInputBuffer(&bufferIx);
359 ALOGV("[%s] dequeued input: %d",
360 mComponentName.c_str(), res == OK ? (int)bufferIx : res);
361 if (res != OK) {
362 if (res != -EAGAIN) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700363 ALOGE("Failed to dequeue input buffer for %s (err=%d)",
364 mComponentName.c_str(), res);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800365 handleError(res);
366 }
367 return false;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700368 }
369
Lajos Molnar1cd13982014-01-17 15:12:51 -0800370 CHECK_LT(bufferIx, mInputBuffers.size());
Andreas Huberf9334412010-12-15 15:17:42 -0800371
Lajos Molnar09524832014-07-17 14:29:51 -0700372 if (mMediaBuffers[bufferIx] != NULL) {
373 mMediaBuffers[bufferIx]->release();
374 mMediaBuffers.editItemAt(bufferIx) = NULL;
375 }
376 mInputBufferIsDequeued.editItemAt(bufferIx) = true;
377
Lajos Molnar87603c02014-08-20 19:25:30 -0700378 if (!mCSDsToSubmit.isEmpty()) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800379 sp<AMessage> msg = new AMessage();
380 msg->setSize("buffer-ix", bufferIx);
381
Lajos Molnar87603c02014-08-20 19:25:30 -0700382 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
383 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
Chong Zhang7137ec72014-11-12 16:41:05 -0800384 msg->setBuffer("buffer", buffer);
Lajos Molnar87603c02014-08-20 19:25:30 -0700385 mCSDsToSubmit.removeAt(0);
Chong Zhang7137ec72014-11-12 16:41:05 -0800386 CHECK(onInputBufferFetched(msg));
Wei Jia2245fc62014-10-02 15:12:25 -0700387 return true;
388 }
389
390 while (!mPendingInputMessages.empty()) {
391 sp<AMessage> msg = *mPendingInputMessages.begin();
Chong Zhang7137ec72014-11-12 16:41:05 -0800392 if (!onInputBufferFetched(msg)) {
Wei Jia2245fc62014-10-02 15:12:25 -0700393 break;
394 }
395 mPendingInputMessages.erase(mPendingInputMessages.begin());
396 }
397
398 if (!mInputBufferIsDequeued.editItemAt(bufferIx)) {
Lajos Molnar87603c02014-08-20 19:25:30 -0700399 return true;
400 }
401
Chong Zhang7137ec72014-11-12 16:41:05 -0800402 mDequeuedInputBuffers.push_back(bufferIx);
403
404 onRequestInputBuffers();
Lajos Molnar1cd13982014-01-17 15:12:51 -0800405 return true;
406}
407
Chong Zhang7137ec72014-11-12 16:41:05 -0800408bool NuPlayer::Decoder::handleAnOutputBuffer() {
409 if (mFormatChangePending) {
410 return false;
411 }
412 size_t bufferIx = -1;
413 size_t offset;
414 size_t size;
415 int64_t timeUs;
416 uint32_t flags;
417 status_t res = mCodec->dequeueOutputBuffer(
418 &bufferIx, &offset, &size, &timeUs, &flags);
419
420 if (res != OK) {
421 ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
422 } else {
423 ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
424 mComponentName.c_str(), (int)bufferIx, timeUs, flags);
425 }
426
427 if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
428 res = mCodec->getOutputBuffers(&mOutputBuffers);
429 if (res != OK) {
430 ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
431 mComponentName.c_str(), res);
432 handleError(res);
433 return false;
434 }
435 // NuPlayer ignores this
436 return true;
437 } else if (res == INFO_FORMAT_CHANGED) {
438 sp<AMessage> format = new AMessage();
439 res = mCodec->getOutputFormat(&format);
440 if (res != OK) {
441 ALOGE("Failed to get output format for %s after INFO event (err=%d)",
442 mComponentName.c_str(), res);
443 handleError(res);
444 return false;
445 }
446
447 if (!mIsAudio) {
448 sp<AMessage> notify = mNotify->dup();
449 notify->setInt32("what", kWhatVideoSizeChanged);
450 notify->setMessage("format", format);
451 notify->post();
452 } else if (mRenderer != NULL) {
453 uint32_t flags;
454 int64_t durationUs;
455 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
456 if (!hasVideo &&
457 mSource->getDuration(&durationUs) == OK &&
458 durationUs
459 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
460 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
461 } else {
462 flags = AUDIO_OUTPUT_FLAG_NONE;
463 }
464
465 mRenderer->openAudioSink(
466 format, false /* offloadOnly */, hasVideo, flags);
467 }
468 return true;
469 } else if (res == INFO_DISCONTINUITY) {
470 // nothing to do
471 return true;
472 } else if (res != OK) {
473 if (res != -EAGAIN) {
474 ALOGE("Failed to dequeue output buffer for %s (err=%d)",
475 mComponentName.c_str(), res);
476 handleError(res);
477 }
478 return false;
479 }
480
481 CHECK_LT(bufferIx, mOutputBuffers.size());
482 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
483 buffer->setRange(offset, size);
484 buffer->meta()->clear();
485 buffer->meta()->setInt64("timeUs", timeUs);
486 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
487 buffer->meta()->setInt32("eos", true);
488 }
489 // we do not expect CODECCONFIG or SYNCFRAME for decoder
490
491 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
492 reply->setSize("buffer-ix", bufferIx);
493 reply->setInt32("generation", mBufferGeneration);
494
495 if (mSkipRenderingUntilMediaTimeUs >= 0) {
496 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
497 ALOGV("[%s] dropping buffer at time %lld as requested.",
498 mComponentName.c_str(), (long long)timeUs);
499
500 reply->post();
501 return true;
502 }
503
504 mSkipRenderingUntilMediaTimeUs = -1;
505 }
506
Chong Zhangf8d71772014-11-26 15:08:34 -0800507 // wait until 1st frame comes out to signal resume complete
508 notifyResumeCompleteIfNecessary();
509
Chong Zhang7137ec72014-11-12 16:41:05 -0800510 if (mRenderer != NULL) {
511 // send the buffer to renderer.
512 mRenderer->queueBuffer(mIsAudio, buffer, reply);
513 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
514 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
515 }
516 }
517
518 return true;
519}
520
521void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
522 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
523 if (mMediaBuffers[i] != NULL) {
524 mMediaBuffers[i]->release();
525 mMediaBuffers.editItemAt(i) = NULL;
526 }
527 }
528 mMediaBuffers.resize(mInputBuffers.size());
529 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
530 mMediaBuffers.editItemAt(i) = NULL;
531 }
532 mInputBufferIsDequeued.clear();
533 mInputBufferIsDequeued.resize(mInputBuffers.size());
534 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
535 mInputBufferIsDequeued.editItemAt(i) = false;
536 }
537
538 mPendingInputMessages.clear();
539 mDequeuedInputBuffers.clear();
540 mSkipRenderingUntilMediaTimeUs = -1;
541}
542
543void NuPlayer::Decoder::requestCodecNotification() {
544 if (mFormatChangePending) {
545 return;
546 }
547 if (mCodec != NULL) {
548 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
549 reply->setInt32("generation", mBufferGeneration);
550 mCodec->requestActivityNotification(reply);
551 }
552}
553
554bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
555 int32_t generation;
556 CHECK(msg->findInt32("generation", &generation));
557 return generation != mBufferGeneration;
558}
559
560status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
561 sp<ABuffer> accessUnit;
562 bool dropAccessUnit;
563 do {
564 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
565
566 if (err == -EWOULDBLOCK) {
567 return err;
568 } else if (err != OK) {
569 if (err == INFO_DISCONTINUITY) {
570 int32_t type;
571 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
572
573 bool formatChange =
574 (mIsAudio &&
575 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
576 || (!mIsAudio &&
577 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
578
579 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
580
581 ALOGI("%s discontinuity (format=%d, time=%d)",
582 mIsAudio ? "audio" : "video", formatChange, timeChange);
583
584 bool seamlessFormatChange = false;
585 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
586 if (formatChange) {
587 seamlessFormatChange =
588 supportsSeamlessFormatChange(newFormat);
589 // treat seamless format change separately
590 formatChange = !seamlessFormatChange;
591 }
592
593 if (formatChange || timeChange) {
594 sp<AMessage> msg = mNotify->dup();
595 msg->setInt32("what", kWhatInputDiscontinuity);
596 msg->setInt32("formatChange", formatChange);
597 msg->post();
598 }
599
600 if (formatChange /* not seamless */) {
601 // must change decoder
602 // return EOS and wait to be killed
603 mFormatChangePending = true;
604 return ERROR_END_OF_STREAM;
605 } else if (timeChange) {
606 // need to flush
607 // TODO: Ideally we shouldn't need a flush upon time
608 // discontinuity, flushing will cause loss of frames.
609 // We probably should queue a time change marker to the
610 // output queue, and handles it in renderer instead.
611 rememberCodecSpecificData(newFormat);
612 onFlush(false /* notifyComplete */);
613 err = OK;
614 } else if (seamlessFormatChange) {
615 // reuse existing decoder and don't flush
616 rememberCodecSpecificData(newFormat);
617 err = OK;
618 } else {
619 // This stream is unaffected by the discontinuity
620 return -EWOULDBLOCK;
621 }
622 }
623
624 reply->setInt32("err", err);
625 return OK;
626 }
627
628 if (!mIsAudio) {
629 ++mNumFramesTotal;
630 }
631
632 dropAccessUnit = false;
633 if (!mIsAudio
634 && !mIsSecure
635 && mRenderer->getVideoLateByUs() > 100000ll
636 && mIsVideoAVC
637 && !IsAVCReferenceFrame(accessUnit)) {
638 dropAccessUnit = true;
639 ++mNumFramesDropped;
640 }
641 } while (dropAccessUnit);
642
643 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
644#if 0
645 int64_t mediaTimeUs;
646 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
647 ALOGV("feeding %s input buffer at media time %.2f secs",
648 mIsAudio ? "audio" : "video",
649 mediaTimeUs / 1E6);
650#endif
651
652 if (mCCDecoder != NULL) {
653 mCCDecoder->decode(accessUnit);
654 }
655
656 reply->setBuffer("buffer", accessUnit);
657
658 return OK;
659}
660
661bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800662 size_t bufferIx;
663 CHECK(msg->findSize("buffer-ix", &bufferIx));
664 CHECK_LT(bufferIx, mInputBuffers.size());
665 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
666
667 sp<ABuffer> buffer;
668 bool hasBuffer = msg->findBuffer("buffer", &buffer);
Lajos Molnar09524832014-07-17 14:29:51 -0700669
670 // handle widevine classic source - that fills an arbitrary input buffer
671 MediaBuffer *mediaBuffer = NULL;
Wei Jia96e92b52014-09-18 17:36:20 -0700672 if (hasBuffer) {
673 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
674 if (mediaBuffer != NULL) {
Lajos Molnar09524832014-07-17 14:29:51 -0700675 // likely filled another buffer than we requested: adjust buffer index
676 size_t ix;
677 for (ix = 0; ix < mInputBuffers.size(); ix++) {
678 const sp<ABuffer> &buf = mInputBuffers[ix];
679 if (buf->data() == mediaBuffer->data()) {
680 // all input buffers are dequeued on start, hence the check
Wei Jia2245fc62014-10-02 15:12:25 -0700681 if (!mInputBufferIsDequeued[ix]) {
682 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
683 mComponentName.c_str(), ix, bufferIx);
684 mediaBuffer->release();
685 return false;
686 }
Lajos Molnar09524832014-07-17 14:29:51 -0700687
688 // TRICKY: need buffer for the metadata, so instead, set
689 // codecBuffer to the same (though incorrect) buffer to
690 // avoid a memcpy into the codecBuffer
691 codecBuffer = buffer;
692 codecBuffer->setRange(
693 mediaBuffer->range_offset(),
694 mediaBuffer->range_length());
695 bufferIx = ix;
696 break;
697 }
698 }
699 CHECK(ix < mInputBuffers.size());
700 }
701 }
702
Lajos Molnar1cd13982014-01-17 15:12:51 -0800703 if (buffer == NULL /* includes !hasBuffer */) {
704 int32_t streamErr = ERROR_END_OF_STREAM;
705 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
706
707 if (streamErr == OK) {
708 /* buffers are returned to hold on to */
Wei Jia2245fc62014-10-02 15:12:25 -0700709 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800710 }
711
712 // attempt to queue EOS
713 status_t err = mCodec->queueInputBuffer(
714 bufferIx,
715 0,
716 0,
717 0,
718 MediaCodec::BUFFER_FLAG_EOS);
Andy Hungcf31f1e2014-09-23 14:59:01 -0700719 if (err == OK) {
720 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
721 } else if (streamErr == ERROR_END_OF_STREAM) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800722 streamErr = err;
723 // err will not be ERROR_END_OF_STREAM
724 }
725
726 if (streamErr != ERROR_END_OF_STREAM) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700727 ALOGE("Stream error for %s (err=%d), EOS %s queued",
728 mComponentName.c_str(),
729 streamErr,
730 err == OK ? "successfully" : "unsuccessfully");
Lajos Molnar1cd13982014-01-17 15:12:51 -0800731 handleError(streamErr);
732 }
733 } else {
Wei Jiac6cfd702014-11-11 16:33:20 -0800734 sp<AMessage> extra;
735 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
736 int64_t resumeAtMediaTimeUs;
737 if (extra->findInt64(
738 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
739 ALOGI("[%s] suppressing rendering until %lld us",
740 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
741 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
742 }
743 }
744
Lajos Molnar1cd13982014-01-17 15:12:51 -0800745 int64_t timeUs = 0;
746 uint32_t flags = 0;
747 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
748
Lajos Molnar87603c02014-08-20 19:25:30 -0700749 int32_t eos, csd;
750 // we do not expect SYNCFRAME for decoder
Lajos Molnar1cd13982014-01-17 15:12:51 -0800751 if (buffer->meta()->findInt32("eos", &eos) && eos) {
752 flags |= MediaCodec::BUFFER_FLAG_EOS;
Lajos Molnar87603c02014-08-20 19:25:30 -0700753 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
754 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800755 }
756
757 // copy into codec buffer
758 if (buffer != codecBuffer) {
759 CHECK_LE(buffer->size(), codecBuffer->capacity());
760 codecBuffer->setRange(0, buffer->size());
761 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
762 }
763
764 status_t err = mCodec->queueInputBuffer(
765 bufferIx,
766 codecBuffer->offset(),
767 codecBuffer->size(),
768 timeUs,
769 flags);
770 if (err != OK) {
Andy Hungcf31f1e2014-09-23 14:59:01 -0700771 if (mediaBuffer != NULL) {
772 mediaBuffer->release();
773 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800774 ALOGE("Failed to queue input buffer for %s (err=%d)",
775 mComponentName.c_str(), err);
776 handleError(err);
Andy Hungcf31f1e2014-09-23 14:59:01 -0700777 } else {
778 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
779 if (mediaBuffer != NULL) {
780 CHECK(mMediaBuffers[bufferIx] == NULL);
781 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
782 }
Lajos Molnar09524832014-07-17 14:29:51 -0700783 }
Lajos Molnar1cd13982014-01-17 15:12:51 -0800784 }
Wei Jia2245fc62014-10-02 15:12:25 -0700785 return true;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800786}
787
Lajos Molnar1cd13982014-01-17 15:12:51 -0800788void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
789 status_t err;
790 int32_t render;
791 size_t bufferIx;
792 CHECK(msg->findSize("buffer-ix", &bufferIx));
Wei Jiac6cfd702014-11-11 16:33:20 -0800793
Chong Zhang7137ec72014-11-12 16:41:05 -0800794 if (!mIsAudio) {
Wei Jiac6cfd702014-11-11 16:33:20 -0800795 int64_t timeUs;
796 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
797 buffer->meta()->findInt64("timeUs", &timeUs);
Chong Zhang7137ec72014-11-12 16:41:05 -0800798
799 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
800 mCCDecoder->display(timeUs);
801 }
Wei Jiac6cfd702014-11-11 16:33:20 -0800802 }
803
Lajos Molnar1cd13982014-01-17 15:12:51 -0800804 if (msg->findInt32("render", &render) && render) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -0700805 int64_t timestampNs;
806 CHECK(msg->findInt64("timestampNs", &timestampNs));
807 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800808 } else {
809 err = mCodec->releaseOutputBuffer(bufferIx);
810 }
811 if (err != OK) {
812 ALOGE("failed to release output buffer for %s (err=%d)",
813 mComponentName.c_str(), err);
814 handleError(err);
815 }
816}
817
Chong Zhang7137ec72014-11-12 16:41:05 -0800818bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
819 const sp<AMessage> &targetFormat) const {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800820 if (targetFormat == NULL) {
821 return true;
822 }
823
824 AString mime;
825 if (!targetFormat->findString("mime", &mime)) {
826 return false;
827 }
828
829 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
830 // field-by-field comparison
831 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
832 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
833 int32_t oldVal, newVal;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800834 if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
835 !targetFormat->findInt32(keys[i], &newVal) ||
836 oldVal != newVal) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800837 return false;
838 }
839 }
840
841 sp<ABuffer> oldBuf, newBuf;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800842 if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
843 targetFormat->findBuffer("csd-0", &newBuf)) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800844 if (oldBuf->size() != newBuf->size()) {
845 return false;
846 }
847 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
848 }
849 }
850 return false;
851}
852
853bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800854 if (mOutputFormat == NULL) {
Robert Shih6d0a94e2014-01-23 16:18:22 -0800855 return false;
856 }
857
858 if (targetFormat == NULL) {
859 return true;
860 }
861
862 AString oldMime, newMime;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800863 if (!mOutputFormat->findString("mime", &oldMime)
Robert Shih6d0a94e2014-01-23 16:18:22 -0800864 || !targetFormat->findString("mime", &newMime)
865 || !(oldMime == newMime)) {
866 return false;
867 }
868
869 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
870 bool seamless;
871 if (audio) {
872 seamless = supportsSeamlessAudioFormatChange(targetFormat);
873 } else {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800874 int32_t isAdaptive;
875 seamless = (mCodec != NULL &&
876 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
877 isAdaptive);
Robert Shih6d0a94e2014-01-23 16:18:22 -0800878 }
879
880 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
881 return seamless;
882}
883
Chong Zhang7137ec72014-11-12 16:41:05 -0800884void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
885 if (format == NULL) {
Chong Zhangb86e68f2014-08-01 13:46:53 -0700886 return;
887 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800888 mCSDsForCurrentFormat.clear();
889 for (int32_t i = 0; ; ++i) {
890 AString tag = "csd-";
891 tag.append(i);
892 sp<ABuffer> buffer;
893 if (!format->findBuffer(tag.c_str(), &buffer)) {
894 break;
895 }
896 mCSDsForCurrentFormat.push(buffer);
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700897 }
Chong Zhangb86e68f2014-08-01 13:46:53 -0700898}
899
Chong Zhangf8d71772014-11-26 15:08:34 -0800900void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
901 if (mResumePending) {
902 mResumePending = false;
903
904 sp<AMessage> notify = mNotify->dup();
905 notify->setInt32("what", kWhatResumeCompleted);
906 notify->post();
907 }
908}
909
Andreas Huberf9334412010-12-15 15:17:42 -0800910} // namespace android
911