1 /*
2 * Copyright 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 "NuPlayerDecoder"
19 #include <utils/Log.h>
20 #include <inttypes.h>
21
22 #include "NuPlayerCCDecoder.h"
23 #include "NuPlayerDecoder.h"
24 #include "NuPlayerRenderer.h"
25 #include "NuPlayerSource.h"
26
27 #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/MediaBuffer.h>
32 #include <media/stagefright/MediaCodec.h>
33 #include <media/stagefright/MediaDefs.h>
34 #include <media/stagefright/MediaErrors.h>
35
36 #include "avc_utils.h"
37 #include "ATSParser.h"
38
39 namespace android {
40
Decoder(const sp<AMessage> & notify,const sp<Source> & source,const sp<Renderer> & renderer,const sp<NativeWindowWrapper> & nativeWindow,const sp<CCDecoder> & ccDecoder)41 NuPlayer::Decoder::Decoder(
42 const sp<AMessage> ¬ify,
43 const sp<Source> &source,
44 const sp<Renderer> &renderer,
45 const sp<NativeWindowWrapper> &nativeWindow,
46 const sp<CCDecoder> &ccDecoder)
47 : DecoderBase(notify),
48 mNativeWindow(nativeWindow),
49 mSource(source),
50 mRenderer(renderer),
51 mCCDecoder(ccDecoder),
52 mSkipRenderingUntilMediaTimeUs(-1ll),
53 mNumFramesTotal(0ll),
54 mNumFramesDropped(0ll),
55 mIsAudio(true),
56 mIsVideoAVC(false),
57 mIsSecure(false),
58 mFormatChangePending(false),
59 mPaused(true),
60 mResumePending(false),
61 mComponentName("decoder") {
62 mCodecLooper = new ALooper;
63 mCodecLooper->setName("NPDecoder-CL");
64 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
65 }
66
~Decoder()67 NuPlayer::Decoder::~Decoder() {
68 releaseAndResetMediaBuffers();
69 }
70
getStats(int64_t * numFramesTotal,int64_t * numFramesDropped) const71 void NuPlayer::Decoder::getStats(
72 int64_t *numFramesTotal,
73 int64_t *numFramesDropped) const {
74 *numFramesTotal = mNumFramesTotal;
75 *numFramesDropped = mNumFramesDropped;
76 }
77
onMessageReceived(const sp<AMessage> & msg)78 void 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();
103 break;
104 }
105
106 case kWhatRenderBuffer:
107 {
108 if (!isStaleReply(msg)) {
109 onRenderBuffer(msg);
110 }
111 break;
112 }
113
114 default:
115 DecoderBase::onMessageReceived(msg);
116 break;
117 }
118 }
119
onConfigure(const sp<AMessage> & format)120 void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
121 CHECK(mCodec == NULL);
122
123 mFormatChangePending = false;
124
125 ++mBufferGeneration;
126
127 AString mime;
128 CHECK(format->findString("mime", &mime));
129
130 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
131 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
132
133 sp<Surface> surface = NULL;
134 if (mNativeWindow != NULL) {
135 surface = mNativeWindow->getSurfaceTextureClient();
136 }
137
138 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 */);
143 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 }
154 if (mCodec == NULL) {
155 ALOGE("Failed to create %s%s decoder",
156 (secure ? "secure " : ""), mime.c_str());
157 handleError(UNKNOWN_ERROR);
158 return;
159 }
160 mIsSecure = secure;
161
162 mCodec->getName(&mComponentName);
163
164 status_t err;
165 if (mNativeWindow != NULL) {
166 // disconnect from surface as MediaCodec will reconnect
167 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);
173 }
174 err = mCodec->configure(
175 format, surface, NULL /* crypto */, 0 /* flags */);
176 if (err != OK) {
177 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
178 mCodec->release();
179 mCodec.clear();
180 handleError(err);
181 return;
182 }
183 rememberCodecSpecificData(format);
184
185 // 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);
192 mCodec->release();
193 mCodec.clear();
194 handleError(err);
195 return;
196 }
197
198 // the following should work after start
199 CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
200 releaseAndResetMediaBuffers();
201 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());
206
207 if (mRenderer != NULL) {
208 requestCodecNotification();
209 }
210 mPaused = false;
211 mResumePending = false;
212 }
213
onSetRenderer(const sp<Renderer> & renderer)214 void 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
onGetInputBuffers(Vector<sp<ABuffer>> * dstBuffers)222 void 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
onResume(bool notifyComplete)230 void NuPlayer::Decoder::onResume(bool notifyComplete) {
231 mPaused = false;
232
233 if (notifyComplete) {
234 mResumePending = true;
235 }
236 }
237
onFlush(bool notifyComplete)238 void 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
onShutdown(bool notifyComplete)271 void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
272 status_t err = OK;
273
274 // if there is a pending resume request, notify complete now
275 notifyResumeCompleteIfNecessary();
276
277 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
doRequestBuffers()311 void 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);
329 }
330 }
331
332 if (err == -EWOULDBLOCK
333 && mSource->feedMoreTSData() == OK) {
334 scheduleRequestBuffers();
335 }
336 }
337
handleAnInputBuffer()338 bool NuPlayer::Decoder::handleAnInputBuffer() {
339 if (mFormatChangePending) {
340 return false;
341 }
342 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) {
348 ALOGE("Failed to dequeue input buffer for %s (err=%d)",
349 mComponentName.c_str(), res);
350 handleError(res);
351 }
352 return false;
353 }
354
355 CHECK_LT(bufferIx, mInputBuffers.size());
356
357 if (mMediaBuffers[bufferIx] != NULL) {
358 mMediaBuffers[bufferIx]->release();
359 mMediaBuffers.editItemAt(bufferIx) = NULL;
360 }
361 mInputBufferIsDequeued.editItemAt(bufferIx) = true;
362
363 if (!mCSDsToSubmit.isEmpty()) {
364 sp<AMessage> msg = new AMessage();
365 msg->setSize("buffer-ix", bufferIx);
366
367 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
368 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
369 msg->setBuffer("buffer", buffer);
370 mCSDsToSubmit.removeAt(0);
371 CHECK(onInputBufferFetched(msg));
372 return true;
373 }
374
375 while (!mPendingInputMessages.empty()) {
376 sp<AMessage> msg = *mPendingInputMessages.begin();
377 if (!onInputBufferFetched(msg)) {
378 break;
379 }
380 mPendingInputMessages.erase(mPendingInputMessages.begin());
381 }
382
383 if (!mInputBufferIsDequeued.editItemAt(bufferIx)) {
384 return true;
385 }
386
387 mDequeuedInputBuffers.push_back(bufferIx);
388
389 onRequestInputBuffers();
390 return true;
391 }
392
handleAnOutputBuffer()393 bool NuPlayer::Decoder::handleAnOutputBuffer() {
394 if (mFormatChangePending) {
395 return false;
396 }
397 size_t bufferIx = -1;
398 size_t offset;
399 size_t size;
400 int64_t timeUs;
401 uint32_t flags;
402 status_t res = mCodec->dequeueOutputBuffer(
403 &bufferIx, &offset, &size, &timeUs, &flags);
404
405 if (res != OK) {
406 ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
407 } else {
408 ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
409 mComponentName.c_str(), (int)bufferIx, timeUs, flags);
410 }
411
412 if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
413 res = mCodec->getOutputBuffers(&mOutputBuffers);
414 if (res != OK) {
415 ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
416 mComponentName.c_str(), res);
417 handleError(res);
418 return false;
419 }
420 // NuPlayer ignores this
421 return true;
422 } else if (res == INFO_FORMAT_CHANGED) {
423 sp<AMessage> format = new AMessage();
424 res = mCodec->getOutputFormat(&format);
425 if (res != OK) {
426 ALOGE("Failed to get output format for %s after INFO event (err=%d)",
427 mComponentName.c_str(), res);
428 handleError(res);
429 return false;
430 }
431
432 if (!mIsAudio) {
433 sp<AMessage> notify = mNotify->dup();
434 notify->setInt32("what", kWhatVideoSizeChanged);
435 notify->setMessage("format", format);
436 notify->post();
437 } else if (mRenderer != NULL) {
438 uint32_t flags;
439 int64_t durationUs;
440 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
441 if (!hasVideo &&
442 mSource->getDuration(&durationUs) == OK &&
443 durationUs
444 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
445 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
446 } else {
447 flags = AUDIO_OUTPUT_FLAG_NONE;
448 }
449
450 res = mRenderer->openAudioSink(
451 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaded */);
452 if (res != OK) {
453 ALOGE("Failed to open AudioSink on format change for %s (err=%d)",
454 mComponentName.c_str(), res);
455 handleError(res);
456 return false;
457 }
458 }
459 return true;
460 } else if (res == INFO_DISCONTINUITY) {
461 // nothing to do
462 return true;
463 } else if (res != OK) {
464 if (res != -EAGAIN) {
465 ALOGE("Failed to dequeue output buffer for %s (err=%d)",
466 mComponentName.c_str(), res);
467 handleError(res);
468 }
469 return false;
470 }
471
472 CHECK_LT(bufferIx, mOutputBuffers.size());
473 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
474 buffer->setRange(offset, size);
475 buffer->meta()->clear();
476 buffer->meta()->setInt64("timeUs", timeUs);
477 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
478 buffer->meta()->setInt32("eos", true);
479 notifyResumeCompleteIfNecessary();
480 }
481 // we do not expect CODECCONFIG or SYNCFRAME for decoder
482
483 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
484 reply->setSize("buffer-ix", bufferIx);
485 reply->setInt32("generation", mBufferGeneration);
486
487 if (mSkipRenderingUntilMediaTimeUs >= 0) {
488 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
489 ALOGV("[%s] dropping buffer at time %lld as requested.",
490 mComponentName.c_str(), (long long)timeUs);
491
492 reply->post();
493 return true;
494 }
495
496 mSkipRenderingUntilMediaTimeUs = -1;
497 }
498
499 // wait until 1st frame comes out to signal resume complete
500 notifyResumeCompleteIfNecessary();
501
502 if (mRenderer != NULL) {
503 // send the buffer to renderer.
504 mRenderer->queueBuffer(mIsAudio, buffer, reply);
505 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
506 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
507 }
508 }
509
510 return true;
511 }
512
releaseAndResetMediaBuffers()513 void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
514 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
515 if (mMediaBuffers[i] != NULL) {
516 mMediaBuffers[i]->release();
517 mMediaBuffers.editItemAt(i) = NULL;
518 }
519 }
520 mMediaBuffers.resize(mInputBuffers.size());
521 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
522 mMediaBuffers.editItemAt(i) = NULL;
523 }
524 mInputBufferIsDequeued.clear();
525 mInputBufferIsDequeued.resize(mInputBuffers.size());
526 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
527 mInputBufferIsDequeued.editItemAt(i) = false;
528 }
529
530 mPendingInputMessages.clear();
531 mDequeuedInputBuffers.clear();
532 mSkipRenderingUntilMediaTimeUs = -1;
533 }
534
requestCodecNotification()535 void NuPlayer::Decoder::requestCodecNotification() {
536 if (mFormatChangePending) {
537 return;
538 }
539 if (mCodec != NULL) {
540 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
541 reply->setInt32("generation", mBufferGeneration);
542 mCodec->requestActivityNotification(reply);
543 }
544 }
545
isStaleReply(const sp<AMessage> & msg)546 bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
547 int32_t generation;
548 CHECK(msg->findInt32("generation", &generation));
549 return generation != mBufferGeneration;
550 }
551
fetchInputData(sp<AMessage> & reply)552 status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
553 sp<ABuffer> accessUnit;
554 bool dropAccessUnit;
555 do {
556 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
557
558 if (err == -EWOULDBLOCK) {
559 return err;
560 } else if (err != OK) {
561 if (err == INFO_DISCONTINUITY) {
562 int32_t type;
563 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
564
565 bool formatChange =
566 (mIsAudio &&
567 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
568 || (!mIsAudio &&
569 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
570
571 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
572
573 ALOGI("%s discontinuity (format=%d, time=%d)",
574 mIsAudio ? "audio" : "video", formatChange, timeChange);
575
576 bool seamlessFormatChange = false;
577 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
578 if (formatChange) {
579 seamlessFormatChange =
580 supportsSeamlessFormatChange(newFormat);
581 // treat seamless format change separately
582 formatChange = !seamlessFormatChange;
583 }
584
585 if (formatChange || timeChange) {
586 sp<AMessage> msg = mNotify->dup();
587 msg->setInt32("what", kWhatInputDiscontinuity);
588 msg->setInt32("formatChange", formatChange);
589 msg->post();
590 }
591
592 if (formatChange /* not seamless */) {
593 // must change decoder
594 // return EOS and wait to be killed
595 mFormatChangePending = true;
596 return ERROR_END_OF_STREAM;
597 } else if (timeChange) {
598 // need to flush
599 // TODO: Ideally we shouldn't need a flush upon time
600 // discontinuity, flushing will cause loss of frames.
601 // We probably should queue a time change marker to the
602 // output queue, and handles it in renderer instead.
603 rememberCodecSpecificData(newFormat);
604 onFlush(false /* notifyComplete */);
605 err = OK;
606 } else if (seamlessFormatChange) {
607 // reuse existing decoder and don't flush
608 rememberCodecSpecificData(newFormat);
609 err = OK;
610 } else {
611 // This stream is unaffected by the discontinuity
612 return -EWOULDBLOCK;
613 }
614 }
615
616 reply->setInt32("err", err);
617 return OK;
618 }
619
620 if (!mIsAudio) {
621 ++mNumFramesTotal;
622 }
623
624 dropAccessUnit = false;
625 if (!mIsAudio
626 && !mIsSecure
627 && mRenderer->getVideoLateByUs() > 100000ll
628 && mIsVideoAVC
629 && !IsAVCReferenceFrame(accessUnit)) {
630 dropAccessUnit = true;
631 ++mNumFramesDropped;
632 }
633 } while (dropAccessUnit);
634
635 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
636 #if 0
637 int64_t mediaTimeUs;
638 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
639 ALOGV("feeding %s input buffer at media time %.2f secs",
640 mIsAudio ? "audio" : "video",
641 mediaTimeUs / 1E6);
642 #endif
643
644 if (mCCDecoder != NULL) {
645 mCCDecoder->decode(accessUnit);
646 }
647
648 reply->setBuffer("buffer", accessUnit);
649
650 return OK;
651 }
652
onInputBufferFetched(const sp<AMessage> & msg)653 bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
654 size_t bufferIx;
655 CHECK(msg->findSize("buffer-ix", &bufferIx));
656 CHECK_LT(bufferIx, mInputBuffers.size());
657 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
658
659 sp<ABuffer> buffer;
660 bool hasBuffer = msg->findBuffer("buffer", &buffer);
661
662 // handle widevine classic source - that fills an arbitrary input buffer
663 MediaBuffer *mediaBuffer = NULL;
664 if (hasBuffer) {
665 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
666 if (mediaBuffer != NULL) {
667 // likely filled another buffer than we requested: adjust buffer index
668 size_t ix;
669 for (ix = 0; ix < mInputBuffers.size(); ix++) {
670 const sp<ABuffer> &buf = mInputBuffers[ix];
671 if (buf->data() == mediaBuffer->data()) {
672 // all input buffers are dequeued on start, hence the check
673 if (!mInputBufferIsDequeued[ix]) {
674 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
675 mComponentName.c_str(), ix, bufferIx);
676 mediaBuffer->release();
677 return false;
678 }
679
680 // TRICKY: need buffer for the metadata, so instead, set
681 // codecBuffer to the same (though incorrect) buffer to
682 // avoid a memcpy into the codecBuffer
683 codecBuffer = buffer;
684 codecBuffer->setRange(
685 mediaBuffer->range_offset(),
686 mediaBuffer->range_length());
687 bufferIx = ix;
688 break;
689 }
690 }
691 CHECK(ix < mInputBuffers.size());
692 }
693 }
694
695 if (buffer == NULL /* includes !hasBuffer */) {
696 int32_t streamErr = ERROR_END_OF_STREAM;
697 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
698
699 if (streamErr == OK) {
700 /* buffers are returned to hold on to */
701 return true;
702 }
703
704 // attempt to queue EOS
705 status_t err = mCodec->queueInputBuffer(
706 bufferIx,
707 0,
708 0,
709 0,
710 MediaCodec::BUFFER_FLAG_EOS);
711 if (err == OK) {
712 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
713 } else if (streamErr == ERROR_END_OF_STREAM) {
714 streamErr = err;
715 // err will not be ERROR_END_OF_STREAM
716 }
717
718 if (streamErr != ERROR_END_OF_STREAM) {
719 ALOGE("Stream error for %s (err=%d), EOS %s queued",
720 mComponentName.c_str(),
721 streamErr,
722 err == OK ? "successfully" : "unsuccessfully");
723 handleError(streamErr);
724 }
725 } else {
726 sp<AMessage> extra;
727 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
728 int64_t resumeAtMediaTimeUs;
729 if (extra->findInt64(
730 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
731 ALOGI("[%s] suppressing rendering until %lld us",
732 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
733 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
734 }
735 }
736
737 int64_t timeUs = 0;
738 uint32_t flags = 0;
739 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
740
741 int32_t eos, csd;
742 // we do not expect SYNCFRAME for decoder
743 if (buffer->meta()->findInt32("eos", &eos) && eos) {
744 flags |= MediaCodec::BUFFER_FLAG_EOS;
745 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
746 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
747 }
748
749 // copy into codec buffer
750 if (buffer != codecBuffer) {
751 CHECK_LE(buffer->size(), codecBuffer->capacity());
752 codecBuffer->setRange(0, buffer->size());
753 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
754 }
755
756 status_t err = mCodec->queueInputBuffer(
757 bufferIx,
758 codecBuffer->offset(),
759 codecBuffer->size(),
760 timeUs,
761 flags);
762 if (err != OK) {
763 if (mediaBuffer != NULL) {
764 mediaBuffer->release();
765 }
766 ALOGE("Failed to queue input buffer for %s (err=%d)",
767 mComponentName.c_str(), err);
768 handleError(err);
769 } else {
770 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
771 if (mediaBuffer != NULL) {
772 CHECK(mMediaBuffers[bufferIx] == NULL);
773 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
774 }
775 }
776 }
777 return true;
778 }
779
onRenderBuffer(const sp<AMessage> & msg)780 void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
781 status_t err;
782 int32_t render;
783 size_t bufferIx;
784 CHECK(msg->findSize("buffer-ix", &bufferIx));
785
786 if (!mIsAudio) {
787 int64_t timeUs;
788 sp<ABuffer> buffer = mOutputBuffers[bufferIx];
789 buffer->meta()->findInt64("timeUs", &timeUs);
790
791 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
792 mCCDecoder->display(timeUs);
793 }
794 }
795
796 if (msg->findInt32("render", &render) && render) {
797 int64_t timestampNs;
798 CHECK(msg->findInt64("timestampNs", ×tampNs));
799 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
800 } else {
801 err = mCodec->releaseOutputBuffer(bufferIx);
802 }
803 if (err != OK) {
804 ALOGE("failed to release output buffer for %s (err=%d)",
805 mComponentName.c_str(), err);
806 handleError(err);
807 }
808 }
809
supportsSeamlessAudioFormatChange(const sp<AMessage> & targetFormat) const810 bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
811 const sp<AMessage> &targetFormat) const {
812 if (targetFormat == NULL) {
813 return true;
814 }
815
816 AString mime;
817 if (!targetFormat->findString("mime", &mime)) {
818 return false;
819 }
820
821 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
822 // field-by-field comparison
823 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
824 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
825 int32_t oldVal, newVal;
826 if (!mInputFormat->findInt32(keys[i], &oldVal) ||
827 !targetFormat->findInt32(keys[i], &newVal) ||
828 oldVal != newVal) {
829 return false;
830 }
831 }
832
833 sp<ABuffer> oldBuf, newBuf;
834 if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
835 targetFormat->findBuffer("csd-0", &newBuf)) {
836 if (oldBuf->size() != newBuf->size()) {
837 return false;
838 }
839 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
840 }
841 }
842 return false;
843 }
844
supportsSeamlessFormatChange(const sp<AMessage> & targetFormat) const845 bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
846 if (mInputFormat == NULL) {
847 return false;
848 }
849
850 if (targetFormat == NULL) {
851 return true;
852 }
853
854 AString oldMime, newMime;
855 if (!mInputFormat->findString("mime", &oldMime)
856 || !targetFormat->findString("mime", &newMime)
857 || !(oldMime == newMime)) {
858 return false;
859 }
860
861 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
862 bool seamless;
863 if (audio) {
864 seamless = supportsSeamlessAudioFormatChange(targetFormat);
865 } else {
866 int32_t isAdaptive;
867 seamless = (mCodec != NULL &&
868 mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
869 isAdaptive);
870 }
871
872 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
873 return seamless;
874 }
875
rememberCodecSpecificData(const sp<AMessage> & format)876 void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
877 if (format == NULL) {
878 return;
879 }
880 mCSDsForCurrentFormat.clear();
881 for (int32_t i = 0; ; ++i) {
882 AString tag = "csd-";
883 tag.append(i);
884 sp<ABuffer> buffer;
885 if (!format->findBuffer(tag.c_str(), &buffer)) {
886 break;
887 }
888 mCSDsForCurrentFormat.push(buffer);
889 }
890 }
891
notifyResumeCompleteIfNecessary()892 void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
893 if (mResumePending) {
894 mResumePending = false;
895
896 sp<AMessage> notify = mNotify->dup();
897 notify->setInt32("what", kWhatResumeCompleted);
898 notify->post();
899 }
900 }
901
902 } // namespace android
903
904