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