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