1 /*
2 * Copyright 2017 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 "NuPlayer2Decoder"
19 #include <utils/Log.h>
20 #include <inttypes.h>
21
22 #include <algorithm>
23
24 #include "NuPlayer2CCDecoder.h"
25 #include "NuPlayer2Decoder.h"
26 #include "NuPlayer2Drm.h"
27 #include "NuPlayer2Renderer.h"
28 #include "NuPlayer2Source.h"
29
30 #include <cutils/properties.h>
31 #include <media/MediaBufferHolder.h>
32 #include <media/MediaCodecBuffer.h>
33 #include <media/NdkMediaCodec.h>
34 #include <media/NdkWrapper.h>
35 #include <media/stagefright/foundation/ABuffer.h>
36 #include <media/stagefright/foundation/ADebug.h>
37 #include <media/stagefright/foundation/AMessage.h>
38 #include <media/stagefright/foundation/avc_utils.h>
39 #include <media/stagefright/MediaBuffer.h>
40 #include <media/stagefright/MediaDefs.h>
41 #include <media/stagefright/MediaErrors.h>
42 #include <media/stagefright/SurfaceUtils.h>
43
44 #include <system/window.h>
45 #include "ATSParser.h"
46
47 namespace android {
48
49 static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
50
51 // The default total video frame rate of a stream when that info is not available from
52 // the source.
53 static float kDefaultVideoFrameRateTotal = 30.f;
54
getAudioDeepBufferSetting()55 static inline bool getAudioDeepBufferSetting() {
56 return property_get_bool("media.stagefright.audio.deep", false /* default_value */);
57 }
58
Decoder(const sp<AMessage> & notify,const sp<Source> & source,pid_t pid,uid_t uid,const sp<Renderer> & renderer,const sp<ANativeWindowWrapper> & nww,const sp<CCDecoder> & ccDecoder)59 NuPlayer2::Decoder::Decoder(
60 const sp<AMessage> ¬ify,
61 const sp<Source> &source,
62 pid_t pid,
63 uid_t uid,
64 const sp<Renderer> &renderer,
65 const sp<ANativeWindowWrapper> &nww,
66 const sp<CCDecoder> &ccDecoder)
67 : DecoderBase(notify),
68 mNativeWindow(nww),
69 mSource(source),
70 mRenderer(renderer),
71 mCCDecoder(ccDecoder),
72 mPid(pid),
73 mUid(uid),
74 mSkipRenderingUntilMediaTimeUs(-1LL),
75 mNumFramesTotal(0LL),
76 mNumInputFramesDropped(0LL),
77 mNumOutputFramesDropped(0LL),
78 mVideoWidth(0),
79 mVideoHeight(0),
80 mIsAudio(true),
81 mIsVideoAVC(false),
82 mIsSecure(false),
83 mIsEncrypted(false),
84 mIsEncryptedObservedEarlier(false),
85 mFormatChangePending(false),
86 mTimeChangePending(false),
87 mFrameRateTotal(kDefaultVideoFrameRateTotal),
88 mPlaybackSpeed(1.0f),
89 mNumVideoTemporalLayerTotal(1), // decode all layers
90 mNumVideoTemporalLayerAllowed(1),
91 mCurrentMaxVideoTemporalLayerId(0),
92 mResumePending(false),
93 mComponentName("decoder") {
94 mVideoTemporalLayerAggregateFps[0] = mFrameRateTotal;
95 }
96
~Decoder()97 NuPlayer2::Decoder::~Decoder() {
98 // Need to stop looper first since mCodec could be accessed on the mDecoderLooper.
99 stopLooper();
100 if (mCodec != NULL) {
101 mCodec->release();
102 }
103 releaseAndResetMediaBuffers();
104 }
105
getStats() const106 sp<AMessage> NuPlayer2::Decoder::getStats() const {
107 mStats->setInt64("frames-total", mNumFramesTotal);
108 mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
109 mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
110 mStats->setFloat("frame-rate-total", mFrameRateTotal);
111
112 // i'm mutexed right now.
113 // make our own copy, so we aren't victim to any later changes.
114 sp<AMessage> copiedStats = mStats->dup();
115 return copiedStats;
116 }
117
setVideoSurface(const sp<ANativeWindowWrapper> & nww)118 status_t NuPlayer2::Decoder::setVideoSurface(const sp<ANativeWindowWrapper> &nww) {
119 if (nww == NULL || nww->getANativeWindow() == NULL
120 || ADebug::isExperimentEnabled("legacy-setsurface")) {
121 return BAD_VALUE;
122 }
123
124 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
125
126 msg->setObject("surface", nww);
127 sp<AMessage> response;
128 status_t err = msg->postAndAwaitResponse(&response);
129 if (err == OK && response != NULL) {
130 CHECK(response->findInt32("err", &err));
131 }
132 return err;
133 }
134
onMessageReceived(const sp<AMessage> & msg)135 void NuPlayer2::Decoder::onMessageReceived(const sp<AMessage> &msg) {
136 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
137
138 switch (msg->what()) {
139 case kWhatCodecNotify:
140 {
141 int32_t cbID;
142 CHECK(msg->findInt32("callbackID", &cbID));
143
144 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",
145 mIsAudio ? "audio" : "video", cbID, mPaused);
146
147 if (mPaused) {
148 break;
149 }
150
151 switch (cbID) {
152 case AMediaCodecWrapper::CB_INPUT_AVAILABLE:
153 {
154 int32_t index;
155 CHECK(msg->findInt32("index", &index));
156
157 handleAnInputBuffer(index);
158 break;
159 }
160
161 case AMediaCodecWrapper::CB_OUTPUT_AVAILABLE:
162 {
163 int32_t index;
164 size_t offset;
165 size_t size;
166 int64_t timeUs;
167 int32_t flags;
168
169 CHECK(msg->findInt32("index", &index));
170 CHECK(msg->findSize("offset", &offset));
171 CHECK(msg->findSize("size", &size));
172 CHECK(msg->findInt64("timeUs", &timeUs));
173 CHECK(msg->findInt32("flags", &flags));
174
175 handleAnOutputBuffer(index, offset, size, timeUs, flags);
176 break;
177 }
178
179 case AMediaCodecWrapper::CB_OUTPUT_FORMAT_CHANGED:
180 {
181 sp<AMessage> format;
182 CHECK(msg->findMessage("format", &format));
183
184 handleOutputFormatChange(format);
185 break;
186 }
187
188 case AMediaCodecWrapper::CB_ERROR:
189 {
190 status_t err;
191 CHECK(msg->findInt32("err", &err));
192 ALOGE("Decoder (%s) reported error : 0x%x",
193 mIsAudio ? "audio" : "video", err);
194
195 handleError(err);
196 break;
197 }
198
199 default:
200 {
201 TRESPASS();
202 break;
203 }
204 }
205
206 break;
207 }
208
209 case kWhatRenderBuffer:
210 {
211 if (!isStaleReply(msg)) {
212 onRenderBuffer(msg);
213 }
214 break;
215 }
216
217 case kWhatAudioOutputFormatChanged:
218 {
219 if (!isStaleReply(msg)) {
220 status_t err;
221 if (msg->findInt32("err", &err) && err != OK) {
222 ALOGE("Renderer reported 0x%x when changing audio output format", err);
223 handleError(err);
224 }
225 }
226 break;
227 }
228
229 case kWhatSetVideoSurface:
230 {
231 sp<AReplyToken> replyID;
232 CHECK(msg->senderAwaitsResponse(&replyID));
233
234 sp<RefBase> obj;
235 CHECK(msg->findObject("surface", &obj));
236 sp<ANativeWindowWrapper> nww =
237 static_cast<ANativeWindowWrapper *>(obj.get()); // non-null
238 if (nww == NULL || nww->getANativeWindow() == NULL) {
239 break;
240 }
241 int32_t err = INVALID_OPERATION;
242 // NOTE: in practice mNativeWindow is always non-null,
243 // but checking here for completeness
244 if (mCodec != NULL
245 && mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
246 // TODO: once AwesomePlayer is removed, remove this automatic connecting
247 // to the surface by MediaPlayerService.
248 //
249 // at this point MediaPlayer2Manager::client has already connected to the
250 // surface, which MediaCodec does not expect
251 err = native_window_api_disconnect(nww->getANativeWindow(),
252 NATIVE_WINDOW_API_MEDIA);
253 if (err == OK) {
254 err = mCodec->setOutputSurface(nww);
255 ALOGI_IF(err, "codec setOutputSurface returned: %d", err);
256 if (err == OK) {
257 // reconnect to the old surface as MPS::Client will expect to
258 // be able to disconnect from it.
259 (void)native_window_api_connect(mNativeWindow->getANativeWindow(),
260 NATIVE_WINDOW_API_MEDIA);
261
262 mNativeWindow = nww;
263 }
264 }
265 if (err != OK) {
266 // reconnect to the new surface on error as MPS::Client will expect to
267 // be able to disconnect from it.
268 (void)native_window_api_connect(nww->getANativeWindow(),
269 NATIVE_WINDOW_API_MEDIA);
270 }
271 }
272
273 sp<AMessage> response = new AMessage;
274 response->setInt32("err", err);
275 response->postReply(replyID);
276 break;
277 }
278
279 case kWhatDrmReleaseCrypto:
280 {
281 ALOGV("kWhatDrmReleaseCrypto");
282 onReleaseCrypto(msg);
283 break;
284 }
285
286 default:
287 DecoderBase::onMessageReceived(msg);
288 break;
289 }
290 }
291
onConfigure(const sp<AMessage> & format)292 void NuPlayer2::Decoder::onConfigure(const sp<AMessage> &format) {
293 ALOGV("[%s] onConfigure (format=%s)", mComponentName.c_str(), format->debugString().c_str());
294 CHECK(mCodec == NULL);
295
296 mFormatChangePending = false;
297 mTimeChangePending = false;
298
299 ++mBufferGeneration;
300
301 AString mime;
302 CHECK(format->findString("mime", &mime));
303
304 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
305 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
306
307 mComponentName = mime;
308 mComponentName.append(" decoder");
309 ALOGV("[%s] onConfigure (nww=%p)", mComponentName.c_str(),
310 (mNativeWindow == NULL ? NULL : mNativeWindow->getANativeWindow()));
311
312 mCodec = AMediaCodecWrapper::CreateDecoderByType(mime);
313 int32_t secure = 0;
314 if (format->findInt32("secure", &secure) && secure != 0) {
315 if (mCodec != NULL) {
316 if (mCodec->getName(&mComponentName) == OK) {
317 mComponentName.append(".secure");
318 mCodec->release();
319 ALOGI("[%s] creating", mComponentName.c_str());
320 mCodec = AMediaCodecWrapper::CreateCodecByName(mComponentName);
321 } else {
322 mCodec = NULL;
323 }
324 }
325 }
326 if (mCodec == NULL) {
327 ALOGE("Failed to create %s%s decoder",
328 (secure ? "secure " : ""), mime.c_str());
329 handleError(NO_INIT);
330 return;
331 }
332 mIsSecure = secure;
333
334 mCodec->getName(&mComponentName);
335
336 status_t err;
337 if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
338 // disconnect from surface as MediaCodec will reconnect
339 err = native_window_api_disconnect(mNativeWindow->getANativeWindow(),
340 NATIVE_WINDOW_API_MEDIA);
341 // We treat this as a warning, as this is a preparatory step.
342 // Codec will try to connect to the surface, which is where
343 // any error signaling will occur.
344 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
345 }
346
347 // Modular DRM
348 sp<RefBase> objCrypto;
349 format->findObject("crypto", &objCrypto);
350 sp<AMediaCryptoWrapper> crypto = static_cast<AMediaCryptoWrapper *>(objCrypto.get());
351 // non-encrypted source won't have a crypto
352 mIsEncrypted = (crypto != NULL);
353 // configure is called once; still using OR in case the behavior changes.
354 mIsEncryptedObservedEarlier = mIsEncryptedObservedEarlier || mIsEncrypted;
355 ALOGV("onConfigure mCrypto: %p, mIsSecure: %d", crypto.get(), mIsSecure);
356
357 err = mCodec->configure(
358 AMediaFormatWrapper::Create(format),
359 mNativeWindow,
360 crypto,
361 0 /* flags */);
362
363 if (err != OK) {
364 ALOGE("Failed to configure [%s] decoder (err=%d)", mComponentName.c_str(), err);
365 mCodec->release();
366 mCodec.clear();
367 handleError(err);
368 return;
369 }
370 rememberCodecSpecificData(format);
371
372 // the following should work in configured state
373 sp<AMediaFormatWrapper> outputFormat = mCodec->getOutputFormat();
374 if (outputFormat == NULL) {
375 handleError(INVALID_OPERATION);
376 return;
377 }
378 mInputFormat = mCodec->getInputFormat();
379 if (mInputFormat == NULL) {
380 handleError(INVALID_OPERATION);
381 return;
382 }
383
384 mStats->setString("mime", mime.c_str());
385 mStats->setString("component-name", mComponentName.c_str());
386
387 if (!mIsAudio) {
388 int32_t width, height;
389 if (outputFormat->getInt32("width", &width)
390 && outputFormat->getInt32("height", &height)) {
391 mStats->setInt32("width", width);
392 mStats->setInt32("height", height);
393 }
394 }
395
396 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
397 mCodec->setCallback(reply);
398
399 err = mCodec->start();
400 if (err != OK) {
401 ALOGE("Failed to start [%s] decoder (err=%d)", mComponentName.c_str(), err);
402 mCodec->release();
403 mCodec.clear();
404 handleError(err);
405 return;
406 }
407
408 releaseAndResetMediaBuffers();
409
410 mPaused = false;
411 mResumePending = false;
412 }
413
onSetParameters(const sp<AMessage> & params)414 void NuPlayer2::Decoder::onSetParameters(const sp<AMessage> ¶ms) {
415 bool needAdjustLayers = false;
416 float frameRateTotal;
417 if (params->findFloat("frame-rate-total", &frameRateTotal)
418 && mFrameRateTotal != frameRateTotal) {
419 needAdjustLayers = true;
420 mFrameRateTotal = frameRateTotal;
421 }
422
423 int32_t numVideoTemporalLayerTotal;
424 if (params->findInt32("temporal-layer-count", &numVideoTemporalLayerTotal)
425 && numVideoTemporalLayerTotal >= 0
426 && numVideoTemporalLayerTotal <= kMaxNumVideoTemporalLayers
427 && mNumVideoTemporalLayerTotal != numVideoTemporalLayerTotal) {
428 needAdjustLayers = true;
429 mNumVideoTemporalLayerTotal = std::max(numVideoTemporalLayerTotal, 1);
430 }
431
432 if (needAdjustLayers && mNumVideoTemporalLayerTotal > 1) {
433 // TODO: For now, layer fps is calculated for some specific architectures.
434 // But it really should be extracted from the stream.
435 mVideoTemporalLayerAggregateFps[0] =
436 mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - 1));
437 for (int32_t i = 1; i < mNumVideoTemporalLayerTotal; ++i) {
438 mVideoTemporalLayerAggregateFps[i] =
439 mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - i))
440 + mVideoTemporalLayerAggregateFps[i - 1];
441 }
442 }
443
444 float playbackSpeed;
445 if (params->findFloat("playback-speed", &playbackSpeed)
446 && mPlaybackSpeed != playbackSpeed) {
447 needAdjustLayers = true;
448 mPlaybackSpeed = playbackSpeed;
449 }
450
451 if (needAdjustLayers) {
452 float decodeFrameRate = mFrameRateTotal;
453 // enable temporal layering optimization only if we know the layering depth
454 if (mNumVideoTemporalLayerTotal > 1) {
455 int32_t layerId;
456 for (layerId = 0; layerId < mNumVideoTemporalLayerTotal - 1; ++layerId) {
457 if (mVideoTemporalLayerAggregateFps[layerId] * mPlaybackSpeed
458 >= kDisplayRefreshingRate * 0.9) {
459 break;
460 }
461 }
462 mNumVideoTemporalLayerAllowed = layerId + 1;
463 decodeFrameRate = mVideoTemporalLayerAggregateFps[layerId];
464 }
465 ALOGV("onSetParameters: allowed layers=%d, decodeFps=%g",
466 mNumVideoTemporalLayerAllowed, decodeFrameRate);
467
468 if (mCodec == NULL) {
469 ALOGW("onSetParameters called before codec is created.");
470 return;
471 }
472
473 sp<AMediaFormatWrapper> codecParams = new AMediaFormatWrapper();
474 codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
475 mCodec->setParameters(codecParams);
476 }
477 }
478
onSetRenderer(const sp<Renderer> & renderer)479 void NuPlayer2::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
480 mRenderer = renderer;
481 }
482
onResume(bool notifyComplete)483 void NuPlayer2::Decoder::onResume(bool notifyComplete) {
484 mPaused = false;
485
486 if (notifyComplete) {
487 mResumePending = true;
488 }
489
490 if (mCodec == NULL) {
491 ALOGE("[%s] onResume without a valid codec", mComponentName.c_str());
492 handleError(NO_INIT);
493 return;
494 }
495 mCodec->start();
496 }
497
doFlush(bool notifyComplete)498 void NuPlayer2::Decoder::doFlush(bool notifyComplete) {
499 if (mCCDecoder != NULL) {
500 mCCDecoder->flush();
501 }
502
503 if (mRenderer != NULL) {
504 mRenderer->flush(mIsAudio, notifyComplete);
505 mRenderer->signalTimeDiscontinuity();
506 }
507
508 status_t err = OK;
509 if (mCodec != NULL) {
510 err = mCodec->flush();
511 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
512 ++mBufferGeneration;
513 }
514
515 if (err != OK) {
516 ALOGE("failed to flush [%s] (err=%d)", mComponentName.c_str(), err);
517 handleError(err);
518 // finish with posting kWhatFlushCompleted.
519 // we attempt to release the buffers even if flush fails.
520 }
521 releaseAndResetMediaBuffers();
522 mPaused = true;
523 }
524
525
onFlush()526 void NuPlayer2::Decoder::onFlush() {
527 doFlush(true);
528
529 if (isDiscontinuityPending()) {
530 // This could happen if the client starts seeking/shutdown
531 // after we queued an EOS for discontinuities.
532 // We can consider discontinuity handled.
533 finishHandleDiscontinuity(false /* flushOnTimeChange */);
534 }
535
536 sp<AMessage> notify = mNotify->dup();
537 notify->setInt32("what", kWhatFlushCompleted);
538 notify->post();
539 }
540
onShutdown(bool notifyComplete)541 void NuPlayer2::Decoder::onShutdown(bool notifyComplete) {
542 status_t err = OK;
543
544 // if there is a pending resume request, notify complete now
545 notifyResumeCompleteIfNecessary();
546
547 if (mCodec != NULL) {
548 err = mCodec->release();
549 mCodec = NULL;
550 ++mBufferGeneration;
551
552 if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
553 // reconnect to surface as MediaCodec disconnected from it
554 status_t error = native_window_api_connect(mNativeWindow->getANativeWindow(),
555 NATIVE_WINDOW_API_MEDIA);
556 ALOGW_IF(error != NO_ERROR,
557 "[%s] failed to connect to native window, error=%d",
558 mComponentName.c_str(), error);
559 }
560 mComponentName = "decoder";
561 }
562
563 releaseAndResetMediaBuffers();
564
565 if (err != OK) {
566 ALOGE("failed to release [%s] (err=%d)", mComponentName.c_str(), err);
567 handleError(err);
568 // finish with posting kWhatShutdownCompleted.
569 }
570
571 if (notifyComplete) {
572 sp<AMessage> notify = mNotify->dup();
573 notify->setInt32("what", kWhatShutdownCompleted);
574 notify->post();
575 mPaused = true;
576 }
577 }
578
579 /*
580 * returns true if we should request more data
581 */
doRequestBuffers()582 bool NuPlayer2::Decoder::doRequestBuffers() {
583 if (isDiscontinuityPending()) {
584 return false;
585 }
586 status_t err = OK;
587 while (err == OK && !mDequeuedInputBuffers.empty()) {
588 size_t bufferIx = *mDequeuedInputBuffers.begin();
589 sp<AMessage> msg = new AMessage();
590 msg->setSize("buffer-ix", bufferIx);
591 err = fetchInputData(msg);
592 if (err != OK && err != ERROR_END_OF_STREAM) {
593 // if EOS, need to queue EOS buffer
594 break;
595 }
596 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
597
598 if (!mPendingInputMessages.empty()
599 || !onInputBufferFetched(msg)) {
600 mPendingInputMessages.push_back(msg);
601 }
602 }
603
604 return err == -EWOULDBLOCK
605 && mSource->feedMoreTSData() == OK;
606 }
607
handleError(int32_t err)608 void NuPlayer2::Decoder::handleError(int32_t err)
609 {
610 // We cannot immediately release the codec due to buffers still outstanding
611 // in the renderer. We signal to the player the error so it can shutdown/release the
612 // decoder after flushing and increment the generation to discard unnecessary messages.
613
614 ++mBufferGeneration;
615
616 sp<AMessage> notify = mNotify->dup();
617 notify->setInt32("what", kWhatError);
618 notify->setInt32("err", err);
619 notify->post();
620 }
621
releaseCrypto()622 status_t NuPlayer2::Decoder::releaseCrypto()
623 {
624 ALOGV("releaseCrypto");
625
626 sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
627
628 sp<AMessage> response;
629 status_t status = msg->postAndAwaitResponse(&response);
630 if (status == OK && response != NULL) {
631 CHECK(response->findInt32("status", &status));
632 ALOGV("releaseCrypto ret: %d ", status);
633 } else {
634 ALOGE("releaseCrypto err: %d", status);
635 }
636
637 return status;
638 }
639
onReleaseCrypto(const sp<AMessage> & msg)640 void NuPlayer2::Decoder::onReleaseCrypto(const sp<AMessage>& msg)
641 {
642 status_t status = INVALID_OPERATION;
643 if (mCodec != NULL) {
644 status = mCodec->releaseCrypto();
645 } else {
646 // returning OK if the codec has been already released
647 status = OK;
648 ALOGE("onReleaseCrypto No mCodec. err: %d", status);
649 }
650
651 sp<AMessage> response = new AMessage;
652 response->setInt32("status", status);
653 // Clearing the state as it's tied to crypto. mIsEncryptedObservedEarlier is sticky though
654 // and lasts for the lifetime of this codec. See its use in fetchInputData.
655 mIsEncrypted = false;
656
657 sp<AReplyToken> replyID;
658 CHECK(msg->senderAwaitsResponse(&replyID));
659 response->postReply(replyID);
660 }
661
handleAnInputBuffer(size_t index)662 bool NuPlayer2::Decoder::handleAnInputBuffer(size_t index) {
663 if (isDiscontinuityPending()) {
664 return false;
665 }
666
667 if (mCodec == NULL) {
668 ALOGE("[%s] handleAnInputBuffer without a valid codec", mComponentName.c_str());
669 handleError(NO_INIT);
670 return false;
671 }
672
673 size_t bufferSize = 0;
674 uint8_t *bufferBase = mCodec->getInputBuffer(index, &bufferSize);
675
676 if (bufferBase == NULL) {
677 ALOGE("[%s] handleAnInputBuffer, failed to get input buffer", mComponentName.c_str());
678 handleError(UNKNOWN_ERROR);
679 return false;
680 }
681
682 sp<MediaCodecBuffer> buffer =
683 new MediaCodecBuffer(NULL /* format */, new ABuffer(bufferBase, bufferSize));
684
685 if (index >= mInputBuffers.size()) {
686 for (size_t i = mInputBuffers.size(); i <= index; ++i) {
687 mInputBuffers.add();
688 mMediaBuffers.add();
689 mInputBufferIsDequeued.add();
690 mMediaBuffers.editItemAt(i) = NULL;
691 mInputBufferIsDequeued.editItemAt(i) = false;
692 }
693 }
694 mInputBuffers.editItemAt(index) = buffer;
695
696 //CHECK_LT(bufferIx, mInputBuffers.size());
697
698 if (mMediaBuffers[index] != NULL) {
699 mMediaBuffers[index]->release();
700 mMediaBuffers.editItemAt(index) = NULL;
701 }
702 mInputBufferIsDequeued.editItemAt(index) = true;
703
704 if (!mCSDsToSubmit.isEmpty()) {
705 sp<AMessage> msg = new AMessage();
706 msg->setSize("buffer-ix", index);
707
708 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
709 ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
710 msg->setBuffer("buffer", buffer);
711 mCSDsToSubmit.removeAt(0);
712 if (!onInputBufferFetched(msg)) {
713 handleError(UNKNOWN_ERROR);
714 return false;
715 }
716 return true;
717 }
718
719 while (!mPendingInputMessages.empty()) {
720 sp<AMessage> msg = *mPendingInputMessages.begin();
721 if (!onInputBufferFetched(msg)) {
722 break;
723 }
724 mPendingInputMessages.erase(mPendingInputMessages.begin());
725 }
726
727 if (!mInputBufferIsDequeued.editItemAt(index)) {
728 return true;
729 }
730
731 mDequeuedInputBuffers.push_back(index);
732
733 onRequestInputBuffers();
734 return true;
735 }
736
handleAnOutputBuffer(size_t index,size_t offset,size_t size,int64_t timeUs,int32_t flags)737 bool NuPlayer2::Decoder::handleAnOutputBuffer(
738 size_t index,
739 size_t offset,
740 size_t size,
741 int64_t timeUs,
742 int32_t flags) {
743 if (mCodec == NULL) {
744 ALOGE("[%s] handleAnOutputBuffer without a valid codec", mComponentName.c_str());
745 handleError(NO_INIT);
746 return false;
747 }
748
749 // CHECK_LT(bufferIx, mOutputBuffers.size());
750
751 size_t bufferSize = 0;
752 uint8_t *bufferBase = mCodec->getOutputBuffer(index, &bufferSize);
753
754 if (bufferBase == NULL) {
755 ALOGE("[%s] handleAnOutputBuffer, failed to get output buffer", mComponentName.c_str());
756 handleError(UNKNOWN_ERROR);
757 return false;
758 }
759
760 sp<MediaCodecBuffer> buffer =
761 new MediaCodecBuffer(NULL /* format */, new ABuffer(bufferBase, bufferSize));
762
763 if (index >= mOutputBuffers.size()) {
764 for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
765 mOutputBuffers.add();
766 }
767 }
768
769 mOutputBuffers.editItemAt(index) = buffer;
770
771 buffer->setRange(offset, size);
772 buffer->meta()->clear();
773 buffer->meta()->setInt64("timeUs", timeUs);
774
775 bool eos = flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
776 // we do not expect CODECCONFIG or SYNCFRAME for decoder
777
778 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
779 reply->setSize("buffer-ix", index);
780 reply->setInt32("generation", mBufferGeneration);
781
782 if (eos) {
783 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
784
785 buffer->meta()->setInt32("eos", true);
786 reply->setInt32("eos", true);
787 }
788
789 mNumFramesTotal += !mIsAudio;
790
791 if (mSkipRenderingUntilMediaTimeUs >= 0) {
792 if (timeUs < mSkipRenderingUntilMediaTimeUs) {
793 ALOGV("[%s] dropping buffer at time %lld as requested.",
794 mComponentName.c_str(), (long long)timeUs);
795
796 reply->post();
797 if (eos) {
798 notifyResumeCompleteIfNecessary();
799 if (mRenderer != NULL && !isDiscontinuityPending()) {
800 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
801 }
802 }
803 return true;
804 }
805
806 mSkipRenderingUntilMediaTimeUs = -1;
807 }
808
809 // wait until 1st frame comes out to signal resume complete
810 notifyResumeCompleteIfNecessary();
811
812 if (mRenderer != NULL) {
813 // send the buffer to renderer.
814 mRenderer->queueBuffer(mIsAudio, buffer, reply);
815 if (eos && !isDiscontinuityPending()) {
816 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
817 }
818 }
819
820 return true;
821 }
822
handleOutputFormatChange(const sp<AMessage> & format)823 void NuPlayer2::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
824 if (!mIsAudio) {
825 int32_t width, height;
826 if (format->findInt32("width", &width)
827 && format->findInt32("height", &height)) {
828 mStats->setInt32("width", width);
829 mStats->setInt32("height", height);
830 }
831 sp<AMessage> notify = mNotify->dup();
832 notify->setInt32("what", kWhatVideoSizeChanged);
833 notify->setMessage("format", format);
834 notify->post();
835 } else if (mRenderer != NULL) {
836 uint32_t flags;
837 int64_t durationUs;
838 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
839 if (getAudioDeepBufferSetting() // override regardless of source duration
840 || (mSource->getDuration(&durationUs) == OK
841 && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
842 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
843 } else {
844 flags = AUDIO_OUTPUT_FLAG_NONE;
845 }
846
847 sp<AMessage> reply = new AMessage(kWhatAudioOutputFormatChanged, this);
848 reply->setInt32("generation", mBufferGeneration);
849 mRenderer->changeAudioFormat(
850 format, false /* offloadOnly */, hasVideo,
851 flags, mSource->isStreaming(), reply);
852 }
853 }
854
releaseAndResetMediaBuffers()855 void NuPlayer2::Decoder::releaseAndResetMediaBuffers() {
856 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
857 if (mMediaBuffers[i] != NULL) {
858 mMediaBuffers[i]->release();
859 mMediaBuffers.editItemAt(i) = NULL;
860 }
861 }
862 mMediaBuffers.resize(mInputBuffers.size());
863 for (size_t i = 0; i < mMediaBuffers.size(); i++) {
864 mMediaBuffers.editItemAt(i) = NULL;
865 }
866 mInputBufferIsDequeued.clear();
867 mInputBufferIsDequeued.resize(mInputBuffers.size());
868 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
869 mInputBufferIsDequeued.editItemAt(i) = false;
870 }
871
872 mPendingInputMessages.clear();
873 mDequeuedInputBuffers.clear();
874 mSkipRenderingUntilMediaTimeUs = -1;
875 }
876
isStaleReply(const sp<AMessage> & msg)877 bool NuPlayer2::Decoder::isStaleReply(const sp<AMessage> &msg) {
878 int32_t generation;
879 CHECK(msg->findInt32("generation", &generation));
880 return generation != mBufferGeneration;
881 }
882
fetchInputData(sp<AMessage> & reply)883 status_t NuPlayer2::Decoder::fetchInputData(sp<AMessage> &reply) {
884 sp<ABuffer> accessUnit;
885 bool dropAccessUnit = true;
886 do {
887 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
888
889 if (err == -EWOULDBLOCK) {
890 return err;
891 } else if (err != OK) {
892 if (err == INFO_DISCONTINUITY) {
893 int32_t type;
894 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
895
896 bool formatChange =
897 (mIsAudio &&
898 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
899 || (!mIsAudio &&
900 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
901
902 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
903
904 ALOGI("%s discontinuity (format=%d, time=%d)",
905 mIsAudio ? "audio" : "video", formatChange, timeChange);
906
907 bool seamlessFormatChange = false;
908 sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
909 if (formatChange) {
910 seamlessFormatChange =
911 supportsSeamlessFormatChange(newFormat);
912 // treat seamless format change separately
913 formatChange = !seamlessFormatChange;
914 }
915
916 // For format or time change, return EOS to queue EOS input,
917 // then wait for EOS on output.
918 if (formatChange /* not seamless */) {
919 mFormatChangePending = true;
920 err = ERROR_END_OF_STREAM;
921 } else if (timeChange) {
922 rememberCodecSpecificData(newFormat);
923 mTimeChangePending = true;
924 err = ERROR_END_OF_STREAM;
925 } else if (seamlessFormatChange) {
926 // reuse existing decoder and don't flush
927 rememberCodecSpecificData(newFormat);
928 continue;
929 } else {
930 // This stream is unaffected by the discontinuity
931 return -EWOULDBLOCK;
932 }
933 }
934
935 // reply should only be returned without a buffer set
936 // when there is an error (including EOS)
937 CHECK(err != OK);
938
939 reply->setInt32("err", err);
940 return ERROR_END_OF_STREAM;
941 }
942
943 dropAccessUnit = false;
944 if (!mIsAudio && !mIsEncrypted) {
945 // Extra safeguard if higher-level behavior changes. Otherwise, not required now.
946 // Preventing the buffer from being processed (and sent to codec) if this is a later
947 // round of playback but this time without prepareDrm. Or if there is a race between
948 // stop (which is not blocking) and releaseDrm allowing buffers being processed after
949 // Crypto has been released (GenericSource currently prevents this race though).
950 // Particularly doing this check before IsAVCReferenceFrame call to prevent parsing
951 // of encrypted data.
952 if (mIsEncryptedObservedEarlier) {
953 ALOGE("fetchInputData: mismatched mIsEncrypted/mIsEncryptedObservedEarlier (0/1)");
954
955 return INVALID_OPERATION;
956 }
957
958 int32_t layerId = 0;
959 bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
960 if (mRenderer->getVideoLateByUs() > 100000LL
961 && mIsVideoAVC
962 && !IsAVCReferenceFrame(accessUnit)) {
963 dropAccessUnit = true;
964 } else if (haveLayerId && mNumVideoTemporalLayerTotal > 1) {
965 // Add only one layer each time.
966 if (layerId > mCurrentMaxVideoTemporalLayerId + 1
967 || layerId >= mNumVideoTemporalLayerAllowed) {
968 dropAccessUnit = true;
969 ALOGV("dropping layer(%d), speed=%g, allowed layer count=%d, max layerId=%d",
970 layerId, mPlaybackSpeed, mNumVideoTemporalLayerAllowed,
971 mCurrentMaxVideoTemporalLayerId);
972 } else if (layerId > mCurrentMaxVideoTemporalLayerId) {
973 mCurrentMaxVideoTemporalLayerId = layerId;
974 } else if (layerId == 0 && mNumVideoTemporalLayerTotal > 1
975 && IsIDR(accessUnit->data(), accessUnit->size())) {
976 mCurrentMaxVideoTemporalLayerId = mNumVideoTemporalLayerTotal - 1;
977 }
978 }
979 if (dropAccessUnit) {
980 if (layerId <= mCurrentMaxVideoTemporalLayerId && layerId > 0) {
981 mCurrentMaxVideoTemporalLayerId = layerId - 1;
982 }
983 ++mNumInputFramesDropped;
984 }
985 }
986 } while (dropAccessUnit);
987
988 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
989 #if 0
990 int64_t mediaTimeUs;
991 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
992 ALOGV("[%s] feeding input buffer at media time %.3f",
993 mIsAudio ? "audio" : "video",
994 mediaTimeUs / 1E6);
995 #endif
996
997 if (mCCDecoder != NULL) {
998 mCCDecoder->decode(accessUnit);
999 }
1000
1001 reply->setBuffer("buffer", accessUnit);
1002
1003 return OK;
1004 }
1005
onInputBufferFetched(const sp<AMessage> & msg)1006 bool NuPlayer2::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
1007 if (mCodec == NULL) {
1008 ALOGE("[%s] onInputBufferFetched without a valid codec", mComponentName.c_str());
1009 handleError(NO_INIT);
1010 return false;
1011 }
1012
1013 size_t bufferIx;
1014 CHECK(msg->findSize("buffer-ix", &bufferIx));
1015 CHECK_LT(bufferIx, mInputBuffers.size());
1016 sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
1017
1018 sp<ABuffer> buffer;
1019 bool hasBuffer = msg->findBuffer("buffer", &buffer);
1020 bool needsCopy = true;
1021
1022 if (buffer == NULL /* includes !hasBuffer */) {
1023 int32_t streamErr = ERROR_END_OF_STREAM;
1024 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
1025
1026 CHECK(streamErr != OK);
1027
1028 // attempt to queue EOS
1029 status_t err = mCodec->queueInputBuffer(
1030 bufferIx,
1031 0,
1032 0,
1033 0,
1034 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
1035 if (err == OK) {
1036 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
1037 } else if (streamErr == ERROR_END_OF_STREAM) {
1038 streamErr = err;
1039 // err will not be ERROR_END_OF_STREAM
1040 }
1041
1042 if (streamErr != ERROR_END_OF_STREAM) {
1043 ALOGE("Stream error for [%s] (err=%d), EOS %s queued",
1044 mComponentName.c_str(),
1045 streamErr,
1046 err == OK ? "successfully" : "unsuccessfully");
1047 handleError(streamErr);
1048 }
1049 } else {
1050 sp<AMessage> extra;
1051 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
1052 int64_t resumeAtMediaTimeUs;
1053 if (extra->findInt64(
1054 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
1055 ALOGI("[%s] suppressing rendering until %lld us",
1056 mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
1057 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
1058 }
1059 }
1060
1061 int64_t timeUs = 0;
1062 uint32_t flags = 0;
1063 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1064
1065 int32_t eos, csd;
1066 // we do not expect SYNCFRAME for decoder
1067 if (buffer->meta()->findInt32("eos", &eos) && eos) {
1068 flags |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
1069 } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
1070 flags |= AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
1071 }
1072
1073 // Modular DRM
1074 MediaBufferBase *mediaBuf = NULL;
1075 sp<AMediaCodecCryptoInfoWrapper> cryptInfo;
1076
1077 // copy into codec buffer
1078 if (needsCopy) {
1079 if (buffer->size() > codecBuffer->capacity()) {
1080 handleError(ERROR_BUFFER_TOO_SMALL);
1081 mDequeuedInputBuffers.push_back(bufferIx);
1082 return false;
1083 }
1084
1085 if (buffer->data() != NULL) {
1086 codecBuffer->setRange(0, buffer->size());
1087 memcpy(codecBuffer->data(), buffer->data(), buffer->size());
1088 } else { // No buffer->data()
1089 //Modular DRM
1090 sp<RefBase> holder;
1091 if (buffer->meta()->findObject("mediaBufferHolder", &holder)) {
1092 mediaBuf = (holder != nullptr) ?
1093 static_cast<MediaBufferHolder*>(holder.get())->mediaBuffer() : nullptr;
1094 }
1095 if (mediaBuf != NULL) {
1096 if (mediaBuf->size() > codecBuffer->capacity()) {
1097 handleError(ERROR_BUFFER_TOO_SMALL);
1098 mDequeuedInputBuffers.push_back(bufferIx);
1099 return false;
1100 }
1101
1102 codecBuffer->setRange(0, mediaBuf->size());
1103 memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
1104
1105 MetaDataBase &meta_data = mediaBuf->meta_data();
1106 cryptInfo = AMediaCodecCryptoInfoWrapper::Create(meta_data);
1107 } else { // No mediaBuf
1108 ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
1109 buffer.get());
1110 handleError(UNKNOWN_ERROR);
1111 return false;
1112 }
1113 } // buffer->data()
1114 } // needsCopy
1115
1116 sp<RefBase> cryptInfoObj;
1117 if (buffer->meta()->findObject("cryptInfo", &cryptInfoObj)) {
1118 cryptInfo = static_cast<AMediaCodecCryptoInfoWrapper *>(cryptInfoObj.get());
1119 }
1120
1121 status_t err;
1122 if (cryptInfo != NULL) {
1123 err = mCodec->queueSecureInputBuffer(
1124 bufferIx,
1125 codecBuffer->offset(),
1126 cryptInfo,
1127 timeUs,
1128 flags);
1129 // synchronous call so done with cryptInfo here
1130 } else {
1131 err = mCodec->queueInputBuffer(
1132 bufferIx,
1133 codecBuffer->offset(),
1134 codecBuffer->size(),
1135 timeUs,
1136 flags);
1137 } // no cryptInfo
1138
1139 if (err != OK) {
1140 ALOGE("onInputBufferFetched: queue%sInputBuffer failed for [%s] (err=%d)",
1141 (cryptInfo != NULL ? "Secure" : ""),
1142 mComponentName.c_str(), err);
1143 handleError(err);
1144 } else {
1145 mInputBufferIsDequeued.editItemAt(bufferIx) = false;
1146 }
1147
1148 } // buffer != NULL
1149 return true;
1150 }
1151
onRenderBuffer(const sp<AMessage> & msg)1152 void NuPlayer2::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
1153 status_t err;
1154 int32_t render;
1155 size_t bufferIx;
1156 int32_t eos;
1157 CHECK(msg->findSize("buffer-ix", &bufferIx));
1158
1159 if (!mIsAudio) {
1160 int64_t timeUs;
1161 sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
1162 buffer->meta()->findInt64("timeUs", &timeUs);
1163
1164 if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
1165 mCCDecoder->display(timeUs);
1166 }
1167 }
1168
1169 if (mCodec == NULL) {
1170 err = NO_INIT;
1171 } else if (msg->findInt32("render", &render) && render) {
1172 int64_t timestampNs;
1173 CHECK(msg->findInt64("timestampNs", ×tampNs));
1174 err = mCodec->releaseOutputBufferAtTime(bufferIx, timestampNs);
1175 } else {
1176 mNumOutputFramesDropped += !mIsAudio;
1177 err = mCodec->releaseOutputBuffer(bufferIx, false /* render */);
1178 }
1179 if (err != OK) {
1180 ALOGE("failed to release output buffer for [%s] (err=%d)",
1181 mComponentName.c_str(), err);
1182 handleError(err);
1183 }
1184 if (msg->findInt32("eos", &eos) && eos
1185 && isDiscontinuityPending()) {
1186 finishHandleDiscontinuity(true /* flushOnTimeChange */);
1187 }
1188 }
1189
isDiscontinuityPending() const1190 bool NuPlayer2::Decoder::isDiscontinuityPending() const {
1191 return mFormatChangePending || mTimeChangePending;
1192 }
1193
finishHandleDiscontinuity(bool flushOnTimeChange)1194 void NuPlayer2::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
1195 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
1196 mFormatChangePending, mTimeChangePending, flushOnTimeChange);
1197
1198 // If we have format change, pause and wait to be killed;
1199 // If we have time change only, flush and restart fetching.
1200
1201 if (mFormatChangePending) {
1202 mPaused = true;
1203 } else if (mTimeChangePending) {
1204 if (flushOnTimeChange) {
1205 doFlush(false /* notifyComplete */);
1206 signalResume(false /* notifyComplete */);
1207 }
1208 }
1209
1210 // Notify NuPlayer2 to either shutdown decoder, or rescan sources
1211 sp<AMessage> msg = mNotify->dup();
1212 msg->setInt32("what", kWhatInputDiscontinuity);
1213 msg->setInt32("formatChange", mFormatChangePending);
1214 msg->post();
1215
1216 mFormatChangePending = false;
1217 mTimeChangePending = false;
1218 }
1219
supportsSeamlessAudioFormatChange(const sp<AMessage> & targetFormat) const1220 bool NuPlayer2::Decoder::supportsSeamlessAudioFormatChange(
1221 const sp<AMessage> &targetFormat) const {
1222 if (targetFormat == NULL) {
1223 return true;
1224 }
1225
1226 AString mime;
1227 if (!targetFormat->findString("mime", &mime)) {
1228 return false;
1229 }
1230
1231 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1232 // field-by-field comparison
1233 const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
1234 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
1235 int32_t oldVal, newVal;
1236 if (!mInputFormat->getInt32(keys[i], &oldVal) ||
1237 !targetFormat->findInt32(keys[i], &newVal) ||
1238 oldVal != newVal) {
1239 return false;
1240 }
1241 }
1242
1243 sp<ABuffer> newBuf;
1244 uint8_t *oldBufData = NULL;
1245 size_t oldBufSize = 0;
1246 if (mInputFormat->getBuffer("csd-0", (void**)&oldBufData, &oldBufSize) &&
1247 targetFormat->findBuffer("csd-0", &newBuf)) {
1248 if (oldBufSize != newBuf->size()) {
1249 return false;
1250 }
1251 return !memcmp(oldBufData, newBuf->data(), oldBufSize);
1252 }
1253 }
1254 return false;
1255 }
1256
supportsSeamlessFormatChange(const sp<AMessage> & targetFormat) const1257 bool NuPlayer2::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
1258 if (mInputFormat == NULL) {
1259 return false;
1260 }
1261
1262 if (targetFormat == NULL) {
1263 return true;
1264 }
1265
1266 AString oldMime, newMime;
1267 if (!mInputFormat->getString("mime", &oldMime)
1268 || !targetFormat->findString("mime", &newMime)
1269 || !(oldMime == newMime)) {
1270 return false;
1271 }
1272
1273 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
1274 bool seamless;
1275 if (audio) {
1276 seamless = supportsSeamlessAudioFormatChange(targetFormat);
1277 } else {
1278 int32_t isAdaptive;
1279 seamless = (mCodec != NULL &&
1280 mInputFormat->getInt32("adaptive-playback", &isAdaptive) &&
1281 isAdaptive);
1282 }
1283
1284 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
1285 return seamless;
1286 }
1287
rememberCodecSpecificData(const sp<AMessage> & format)1288 void NuPlayer2::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
1289 if (format == NULL) {
1290 return;
1291 }
1292 mCSDsForCurrentFormat.clear();
1293 for (int32_t i = 0; ; ++i) {
1294 AString tag = "csd-";
1295 tag.append(i);
1296 sp<ABuffer> buffer;
1297 if (!format->findBuffer(tag.c_str(), &buffer)) {
1298 break;
1299 }
1300 mCSDsForCurrentFormat.push(buffer);
1301 }
1302 }
1303
notifyResumeCompleteIfNecessary()1304 void NuPlayer2::Decoder::notifyResumeCompleteIfNecessary() {
1305 if (mResumePending) {
1306 mResumePending = false;
1307
1308 sp<AMessage> notify = mNotify->dup();
1309 notify->setInt32("what", kWhatResumeCompleted);
1310 notify->post();
1311 }
1312 }
1313
1314 } // namespace android
1315
1316