NuPlayerDecoder.cpp revision 2245fc625910e47d1ba3c339e205c21ab58a47ad
1/*
2 * Copyright (C) 2010 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 "NuPlayerDecoder.h"
23
24#include <media/ICrypto.h>
25#include <media/stagefright/foundation/ABitReader.h>
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaCodec.h>
31#include <media/stagefright/MediaDefs.h>
32#include <media/stagefright/MediaErrors.h>
33
34namespace android {
35
36NuPlayer::Decoder::Decoder(
37        const sp<AMessage> &notify,
38        const sp<NativeWindowWrapper> &nativeWindow)
39    : mNotify(notify),
40      mNativeWindow(nativeWindow),
41      mBufferGeneration(0),
42      mPaused(true),
43      mComponentName("decoder") {
44    // Every decoder has its own looper because MediaCodec operations
45    // are blocking, but NuPlayer needs asynchronous operations.
46    mDecoderLooper = new ALooper;
47    mDecoderLooper->setName("NPDecoder");
48    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
49
50    mCodecLooper = new ALooper;
51    mCodecLooper->setName("NPDecoder-CL");
52    mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
53}
54
55NuPlayer::Decoder::~Decoder() {
56    mDecoderLooper->unregisterHandler(id());
57    mDecoderLooper->stop();
58
59    releaseAndResetMediaBuffers();
60}
61
62static
63status_t PostAndAwaitResponse(
64        const sp<AMessage> &msg, sp<AMessage> *response) {
65    status_t err = msg->postAndAwaitResponse(response);
66
67    if (err != OK) {
68        return err;
69    }
70
71    if (!(*response)->findInt32("err", &err)) {
72        err = OK;
73    }
74
75    return err;
76}
77
78void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
79    mCSDsForCurrentFormat.clear();
80    for (int32_t i = 0; ; ++i) {
81        AString tag = "csd-";
82        tag.append(i);
83        sp<ABuffer> buffer;
84        if (!format->findBuffer(tag.c_str(), &buffer)) {
85            break;
86        }
87        mCSDsForCurrentFormat.push(buffer);
88    }
89}
90
91void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
92    CHECK(mCodec == NULL);
93
94    ++mBufferGeneration;
95
96    AString mime;
97    CHECK(format->findString("mime", &mime));
98
99    sp<Surface> surface = NULL;
100    if (mNativeWindow != NULL) {
101        surface = mNativeWindow->getSurfaceTextureClient();
102    }
103
104    mComponentName = mime;
105    mComponentName.append(" decoder");
106    ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get());
107
108    mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
109    int32_t secure = 0;
110    if (format->findInt32("secure", &secure) && secure != 0) {
111        if (mCodec != NULL) {
112            mCodec->getName(&mComponentName);
113            mComponentName.append(".secure");
114            mCodec->release();
115            ALOGI("[%s] creating", mComponentName.c_str());
116            mCodec = MediaCodec::CreateByComponentName(
117                    mCodecLooper, mComponentName.c_str());
118        }
119    }
120    if (mCodec == NULL) {
121        ALOGE("Failed to create %s%s decoder",
122                (secure ? "secure " : ""), mime.c_str());
123        handleError(UNKNOWN_ERROR);
124        return;
125    }
126
127    mCodec->getName(&mComponentName);
128
129    status_t err;
130    if (mNativeWindow != NULL) {
131        // disconnect from surface as MediaCodec will reconnect
132        err = native_window_api_disconnect(
133                surface.get(), NATIVE_WINDOW_API_MEDIA);
134        // We treat this as a warning, as this is a preparatory step.
135        // Codec will try to connect to the surface, which is where
136        // any error signaling will occur.
137        ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
138    }
139    err = mCodec->configure(
140            format, surface, NULL /* crypto */, 0 /* flags */);
141    if (err != OK) {
142        ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
143        handleError(err);
144        return;
145    }
146    rememberCodecSpecificData(format);
147
148    // the following should work in configured state
149    CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
150    CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
151
152    err = mCodec->start();
153    if (err != OK) {
154        ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
155        handleError(err);
156        return;
157    }
158
159    // the following should work after start
160    CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
161    releaseAndResetMediaBuffers();
162    CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers));
163    ALOGV("[%s] got %zu input and %zu output buffers",
164            mComponentName.c_str(),
165            mInputBuffers.size(),
166            mOutputBuffers.size());
167
168    requestCodecNotification();
169    mPaused = false;
170}
171
172void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
173    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
174        if (mMediaBuffers[i] != NULL) {
175            mMediaBuffers[i]->release();
176            mMediaBuffers.editItemAt(i) = NULL;
177        }
178    }
179    mMediaBuffers.resize(mInputBuffers.size());
180    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
181        mMediaBuffers.editItemAt(i) = NULL;
182    }
183    mInputBufferIsDequeued.clear();
184    mInputBufferIsDequeued.resize(mInputBuffers.size());
185    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
186        mInputBufferIsDequeued.editItemAt(i) = false;
187    }
188
189    mPendingInputMessages.clear();
190}
191
192void NuPlayer::Decoder::requestCodecNotification() {
193    if (mCodec != NULL) {
194        sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
195        reply->setInt32("generation", mBufferGeneration);
196        mCodec->requestActivityNotification(reply);
197    }
198}
199
200bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
201    int32_t generation;
202    CHECK(msg->findInt32("generation", &generation));
203    return generation != mBufferGeneration;
204}
205
206void NuPlayer::Decoder::init() {
207    mDecoderLooper->registerHandler(this);
208}
209
210void NuPlayer::Decoder::configure(const sp<AMessage> &format) {
211    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
212    msg->setMessage("format", format);
213    msg->post();
214}
215
216void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
217    sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
218    msg->setMessage("format", format);
219    msg->post();
220}
221
222status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
223    sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id());
224    msg->setPointer("buffers", buffers);
225
226    sp<AMessage> response;
227    return PostAndAwaitResponse(msg, &response);
228}
229
230void NuPlayer::Decoder::handleError(int32_t err)
231{
232    // We cannot immediately release the codec due to buffers still outstanding
233    // in the renderer.  We signal to the player the error so it can shutdown/release the
234    // decoder after flushing and increment the generation to discard unnecessary messages.
235
236    ++mBufferGeneration;
237
238    sp<AMessage> notify = mNotify->dup();
239    notify->setInt32("what", kWhatError);
240    notify->setInt32("err", err);
241    notify->post();
242}
243
244bool NuPlayer::Decoder::handleAnInputBuffer() {
245    size_t bufferIx = -1;
246    status_t res = mCodec->dequeueInputBuffer(&bufferIx);
247    ALOGV("[%s] dequeued input: %d",
248            mComponentName.c_str(), res == OK ? (int)bufferIx : res);
249    if (res != OK) {
250        if (res != -EAGAIN) {
251            ALOGE("Failed to dequeue input buffer for %s (err=%d)",
252                    mComponentName.c_str(), res);
253            handleError(res);
254        }
255        return false;
256    }
257
258    CHECK_LT(bufferIx, mInputBuffers.size());
259
260    if (mMediaBuffers[bufferIx] != NULL) {
261        mMediaBuffers[bufferIx]->release();
262        mMediaBuffers.editItemAt(bufferIx) = NULL;
263    }
264    mInputBufferIsDequeued.editItemAt(bufferIx) = true;
265
266    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
267    reply->setSize("buffer-ix", bufferIx);
268    reply->setInt32("generation", mBufferGeneration);
269
270    if (!mCSDsToSubmit.isEmpty()) {
271        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
272        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
273        reply->setBuffer("buffer", buffer);
274        mCSDsToSubmit.removeAt(0);
275        CHECK(onInputBufferFilled(reply));
276        return true;
277    }
278
279    while (!mPendingInputMessages.empty()) {
280        sp<AMessage> msg = *mPendingInputMessages.begin();
281        if (!onInputBufferFilled(msg)) {
282            break;
283        }
284        mPendingInputMessages.erase(mPendingInputMessages.begin());
285    }
286
287    if (!mInputBufferIsDequeued.editItemAt(bufferIx)) {
288        return true;
289    }
290
291    sp<AMessage> notify = mNotify->dup();
292    notify->setInt32("what", kWhatFillThisBuffer);
293    notify->setBuffer("buffer", mInputBuffers[bufferIx]);
294    notify->setMessage("reply", reply);
295    notify->post();
296    return true;
297}
298
299bool android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
300    size_t bufferIx;
301    CHECK(msg->findSize("buffer-ix", &bufferIx));
302    CHECK_LT(bufferIx, mInputBuffers.size());
303    sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
304
305    sp<ABuffer> buffer;
306    bool hasBuffer = msg->findBuffer("buffer", &buffer);
307
308    // handle widevine classic source - that fills an arbitrary input buffer
309    MediaBuffer *mediaBuffer = NULL;
310    if (hasBuffer) {
311        mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
312        if (mediaBuffer != NULL) {
313            // likely filled another buffer than we requested: adjust buffer index
314            size_t ix;
315            for (ix = 0; ix < mInputBuffers.size(); ix++) {
316                const sp<ABuffer> &buf = mInputBuffers[ix];
317                if (buf->data() == mediaBuffer->data()) {
318                    // all input buffers are dequeued on start, hence the check
319                    if (!mInputBufferIsDequeued[ix]) {
320                        ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
321                                mComponentName.c_str(), ix, bufferIx);
322                        mediaBuffer->release();
323                        return false;
324                    }
325
326                    // TRICKY: need buffer for the metadata, so instead, set
327                    // codecBuffer to the same (though incorrect) buffer to
328                    // avoid a memcpy into the codecBuffer
329                    codecBuffer = buffer;
330                    codecBuffer->setRange(
331                            mediaBuffer->range_offset(),
332                            mediaBuffer->range_length());
333                    bufferIx = ix;
334                    break;
335                }
336            }
337            CHECK(ix < mInputBuffers.size());
338        }
339    }
340
341
342
343    if (buffer == NULL /* includes !hasBuffer */) {
344        int32_t streamErr = ERROR_END_OF_STREAM;
345        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
346
347        if (streamErr == OK) {
348            /* buffers are returned to hold on to */
349            return true;
350        }
351
352        // attempt to queue EOS
353        status_t err = mCodec->queueInputBuffer(
354                bufferIx,
355                0,
356                0,
357                0,
358                MediaCodec::BUFFER_FLAG_EOS);
359        if (err == OK) {
360            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
361        } else if (streamErr == ERROR_END_OF_STREAM) {
362            streamErr = err;
363            // err will not be ERROR_END_OF_STREAM
364        }
365
366        if (streamErr != ERROR_END_OF_STREAM) {
367            ALOGE("Stream error for %s (err=%d), EOS %s queued",
368                    mComponentName.c_str(),
369                    streamErr,
370                    err == OK ? "successfully" : "unsuccessfully");
371            handleError(streamErr);
372        }
373    } else {
374        int64_t timeUs = 0;
375        uint32_t flags = 0;
376        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
377
378        int32_t eos, csd;
379        // we do not expect SYNCFRAME for decoder
380        if (buffer->meta()->findInt32("eos", &eos) && eos) {
381            flags |= MediaCodec::BUFFER_FLAG_EOS;
382        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
383            flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
384        }
385
386        // copy into codec buffer
387        if (buffer != codecBuffer) {
388            CHECK_LE(buffer->size(), codecBuffer->capacity());
389            codecBuffer->setRange(0, buffer->size());
390            memcpy(codecBuffer->data(), buffer->data(), buffer->size());
391        }
392
393        status_t err = mCodec->queueInputBuffer(
394                        bufferIx,
395                        codecBuffer->offset(),
396                        codecBuffer->size(),
397                        timeUs,
398                        flags);
399        if (err != OK) {
400            if (mediaBuffer != NULL) {
401                mediaBuffer->release();
402            }
403            ALOGE("Failed to queue input buffer for %s (err=%d)",
404                    mComponentName.c_str(), err);
405            handleError(err);
406        } else {
407            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
408            if (mediaBuffer != NULL) {
409                CHECK(mMediaBuffers[bufferIx] == NULL);
410                mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
411            }
412        }
413    }
414    return true;
415}
416
417bool NuPlayer::Decoder::handleAnOutputBuffer() {
418    size_t bufferIx = -1;
419    size_t offset;
420    size_t size;
421    int64_t timeUs;
422    uint32_t flags;
423    status_t res = mCodec->dequeueOutputBuffer(
424            &bufferIx, &offset, &size, &timeUs, &flags);
425
426    if (res != OK) {
427        ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
428    } else {
429        ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
430                mComponentName.c_str(), (int)bufferIx, timeUs, flags);
431    }
432
433    if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
434        res = mCodec->getOutputBuffers(&mOutputBuffers);
435        if (res != OK) {
436            ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
437                    mComponentName.c_str(), res);
438            handleError(res);
439            return false;
440        }
441        // NuPlayer ignores this
442        return true;
443    } else if (res == INFO_FORMAT_CHANGED) {
444        sp<AMessage> format = new AMessage();
445        res = mCodec->getOutputFormat(&format);
446        if (res != OK) {
447            ALOGE("Failed to get output format for %s after INFO event (err=%d)",
448                    mComponentName.c_str(), res);
449            handleError(res);
450            return false;
451        }
452
453        sp<AMessage> notify = mNotify->dup();
454        notify->setInt32("what", kWhatOutputFormatChanged);
455        notify->setMessage("format", format);
456        notify->post();
457        return true;
458    } else if (res == INFO_DISCONTINUITY) {
459        // nothing to do
460        return true;
461    } else if (res != OK) {
462        if (res != -EAGAIN) {
463            ALOGE("Failed to dequeue output buffer for %s (err=%d)",
464                    mComponentName.c_str(), res);
465            handleError(res);
466        }
467        return false;
468    }
469
470    CHECK_LT(bufferIx, mOutputBuffers.size());
471    sp<ABuffer> buffer = mOutputBuffers[bufferIx];
472    buffer->setRange(offset, size);
473    buffer->meta()->clear();
474    buffer->meta()->setInt64("timeUs", timeUs);
475    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
476        buffer->meta()->setInt32("eos", true);
477    }
478    // we do not expect CODECCONFIG or SYNCFRAME for decoder
479
480    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
481    reply->setSize("buffer-ix", bufferIx);
482    reply->setInt32("generation", mBufferGeneration);
483
484    sp<AMessage> notify = mNotify->dup();
485    notify->setInt32("what", kWhatDrainThisBuffer);
486    notify->setBuffer("buffer", buffer);
487    notify->setMessage("reply", reply);
488    notify->post();
489
490    // FIXME: This should be handled after rendering is complete,
491    // but Renderer needs it now
492    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
493        ALOGV("queueing eos [%s]", mComponentName.c_str());
494        sp<AMessage> notify = mNotify->dup();
495        notify->setInt32("what", kWhatEOS);
496        notify->setInt32("err", ERROR_END_OF_STREAM);
497        notify->post();
498    }
499    return true;
500}
501
502void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
503    status_t err;
504    int32_t render;
505    size_t bufferIx;
506    CHECK(msg->findSize("buffer-ix", &bufferIx));
507    if (msg->findInt32("render", &render) && render) {
508        int64_t timestampNs;
509        CHECK(msg->findInt64("timestampNs", &timestampNs));
510        err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
511    } else {
512        err = mCodec->releaseOutputBuffer(bufferIx);
513    }
514    if (err != OK) {
515        ALOGE("failed to release output buffer for %s (err=%d)",
516                mComponentName.c_str(), err);
517        handleError(err);
518    }
519}
520
521void NuPlayer::Decoder::onFlush() {
522    status_t err = OK;
523    if (mCodec != NULL) {
524        err = mCodec->flush();
525        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
526        ++mBufferGeneration;
527    }
528
529    if (err != OK) {
530        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
531        handleError(err);
532        return;
533    }
534
535    releaseAndResetMediaBuffers();
536
537    sp<AMessage> notify = mNotify->dup();
538    notify->setInt32("what", kWhatFlushCompleted);
539    notify->post();
540    mPaused = true;
541}
542
543void NuPlayer::Decoder::onResume() {
544    mPaused = false;
545}
546
547void NuPlayer::Decoder::onShutdown() {
548    status_t err = OK;
549    if (mCodec != NULL) {
550        err = mCodec->release();
551        mCodec = NULL;
552        ++mBufferGeneration;
553
554        if (mNativeWindow != NULL) {
555            // reconnect to surface as MediaCodec disconnected from it
556            status_t error =
557                    native_window_api_connect(
558                            mNativeWindow->getNativeWindow().get(),
559                            NATIVE_WINDOW_API_MEDIA);
560            ALOGW_IF(error != NO_ERROR,
561                    "[%s] failed to connect to native window, error=%d",
562                    mComponentName.c_str(), error);
563        }
564        mComponentName = "decoder";
565    }
566
567    releaseAndResetMediaBuffers();
568
569    if (err != OK) {
570        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
571        handleError(err);
572        return;
573    }
574
575    sp<AMessage> notify = mNotify->dup();
576    notify->setInt32("what", kWhatShutdownCompleted);
577    notify->post();
578    mPaused = true;
579}
580
581void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
582    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
583
584    switch (msg->what()) {
585        case kWhatConfigure:
586        {
587            sp<AMessage> format;
588            CHECK(msg->findMessage("format", &format));
589            onConfigure(format);
590            break;
591        }
592
593        case kWhatUpdateFormat:
594        {
595            sp<AMessage> format;
596            CHECK(msg->findMessage("format", &format));
597            rememberCodecSpecificData(format);
598            break;
599        }
600
601        case kWhatGetInputBuffers:
602        {
603            uint32_t replyID;
604            CHECK(msg->senderAwaitsResponse(&replyID));
605
606            Vector<sp<ABuffer> > *dstBuffers;
607            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
608
609            dstBuffers->clear();
610            for (size_t i = 0; i < mInputBuffers.size(); i++) {
611                dstBuffers->push(mInputBuffers[i]);
612            }
613
614            (new AMessage)->postReply(replyID);
615            break;
616        }
617
618        case kWhatCodecNotify:
619        {
620            if (!isStaleReply(msg)) {
621                if (!mPaused) {
622                    while (handleAnInputBuffer()) {
623                    }
624                }
625
626                while (handleAnOutputBuffer()) {
627                }
628            }
629
630            requestCodecNotification();
631            break;
632        }
633
634        case kWhatInputBufferFilled:
635        {
636            if (!isStaleReply(msg)) {
637                if (!mPendingInputMessages.empty()
638                        || !onInputBufferFilled(msg)) {
639                    mPendingInputMessages.push_back(msg);
640                }
641            }
642
643            break;
644        }
645
646        case kWhatRenderBuffer:
647        {
648            if (!isStaleReply(msg)) {
649                onRenderBuffer(msg);
650            }
651            break;
652        }
653
654        case kWhatFlush:
655        {
656            sp<AMessage> format;
657            if (msg->findMessage("new-format", &format)) {
658                rememberCodecSpecificData(format);
659            }
660            onFlush();
661            break;
662        }
663
664        case kWhatResume:
665        {
666            onResume();
667            break;
668        }
669
670        case kWhatShutdown:
671        {
672            onShutdown();
673            break;
674        }
675
676        default:
677            TRESPASS();
678            break;
679    }
680}
681
682void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) {
683    sp<AMessage> msg = new AMessage(kWhatFlush, id());
684    if (format != NULL) {
685        msg->setMessage("new-format", format);
686    }
687    msg->post();
688}
689
690void NuPlayer::Decoder::signalResume() {
691    (new AMessage(kWhatResume, id()))->post();
692}
693
694void NuPlayer::Decoder::initiateShutdown() {
695    (new AMessage(kWhatShutdown, id()))->post();
696}
697
698bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const {
699    if (targetFormat == NULL) {
700        return true;
701    }
702
703    AString mime;
704    if (!targetFormat->findString("mime", &mime)) {
705        return false;
706    }
707
708    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
709        // field-by-field comparison
710        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
711        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
712            int32_t oldVal, newVal;
713            if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
714                    !targetFormat->findInt32(keys[i], &newVal) ||
715                    oldVal != newVal) {
716                return false;
717            }
718        }
719
720        sp<ABuffer> oldBuf, newBuf;
721        if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
722                targetFormat->findBuffer("csd-0", &newBuf)) {
723            if (oldBuf->size() != newBuf->size()) {
724                return false;
725            }
726            return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
727        }
728    }
729    return false;
730}
731
732bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
733    if (mOutputFormat == NULL) {
734        return false;
735    }
736
737    if (targetFormat == NULL) {
738        return true;
739    }
740
741    AString oldMime, newMime;
742    if (!mOutputFormat->findString("mime", &oldMime)
743            || !targetFormat->findString("mime", &newMime)
744            || !(oldMime == newMime)) {
745        return false;
746    }
747
748    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
749    bool seamless;
750    if (audio) {
751        seamless = supportsSeamlessAudioFormatChange(targetFormat);
752    } else {
753        int32_t isAdaptive;
754        seamless = (mCodec != NULL &&
755                mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
756                isAdaptive);
757    }
758
759    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
760    return seamless;
761}
762
763struct CCData {
764    CCData(uint8_t type, uint8_t data1, uint8_t data2)
765        : mType(type), mData1(data1), mData2(data2) {
766    }
767    bool getChannel(size_t *channel) const {
768        if (mData1 >= 0x10 && mData1 <= 0x1f) {
769            *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0);
770            return true;
771        }
772        return false;
773    }
774
775    uint8_t mType;
776    uint8_t mData1;
777    uint8_t mData2;
778};
779
780static bool isNullPad(CCData *cc) {
781    return cc->mData1 < 0x10 && cc->mData2 < 0x10;
782}
783
784static void dumpBytePair(const sp<ABuffer> &ccBuf) {
785    size_t offset = 0;
786    AString out;
787
788    while (offset < ccBuf->size()) {
789        char tmp[128];
790
791        CCData *cc = (CCData *) (ccBuf->data() + offset);
792
793        if (isNullPad(cc)) {
794            // 1 null pad or XDS metadata, ignore
795            offset += sizeof(CCData);
796            continue;
797        }
798
799        if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
800            // 2 basic chars
801            sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
802        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
803                 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
804            // 1 special char
805            sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
806        } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
807                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
808            // 1 Spanish/French char
809            sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
810        } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
811                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
812            // 1 Portuguese/German/Danish char
813            sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
814        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
815                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
816            // Mid-Row Codes (Table 69)
817            sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
818        } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
819                  && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
820                  ||
821                   ((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
822                  && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
823            // Misc Control Codes (Table 70)
824            sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
825        } else if ((cc->mData1 & 0x70) == 0x10
826                && (cc->mData2 & 0x40) == 0x40
827                && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
828            // Preamble Address Codes (Table 71)
829            sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
830        } else {
831            sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
832        }
833
834        if (out.size() > 0) {
835            out.append(", ");
836        }
837
838        out.append(tmp);
839
840        offset += sizeof(CCData);
841    }
842
843    ALOGI("%s", out.c_str());
844}
845
846NuPlayer::CCDecoder::CCDecoder(const sp<AMessage> &notify)
847    : mNotify(notify),
848      mCurrentChannel(0),
849      mSelectedTrack(-1) {
850      for (size_t i = 0; i < sizeof(mTrackIndices)/sizeof(mTrackIndices[0]); ++i) {
851          mTrackIndices[i] = -1;
852      }
853}
854
855size_t NuPlayer::CCDecoder::getTrackCount() const {
856    return mFoundChannels.size();
857}
858
859sp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const {
860    if (!isTrackValid(index)) {
861        return NULL;
862    }
863
864    sp<AMessage> format = new AMessage();
865
866    format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE);
867    format->setString("language", "und");
868    format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608);
869    //CC1, field 0 channel 0
870    bool isDefaultAuto = (mFoundChannels[index] == 0);
871    format->setInt32("auto", isDefaultAuto);
872    format->setInt32("default", isDefaultAuto);
873    format->setInt32("forced", 0);
874
875    return format;
876}
877
878status_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) {
879    if (!isTrackValid(index)) {
880        return BAD_VALUE;
881    }
882
883    if (select) {
884        if (mSelectedTrack == (ssize_t)index) {
885            ALOGE("track %zu already selected", index);
886            return BAD_VALUE;
887        }
888        ALOGV("selected track %zu", index);
889        mSelectedTrack = index;
890    } else {
891        if (mSelectedTrack != (ssize_t)index) {
892            ALOGE("track %zu is not selected", index);
893            return BAD_VALUE;
894        }
895        ALOGV("unselected track %zu", index);
896        mSelectedTrack = -1;
897    }
898
899    return OK;
900}
901
902bool NuPlayer::CCDecoder::isSelected() const {
903    return mSelectedTrack >= 0 && mSelectedTrack < (int32_t) getTrackCount();
904}
905
906bool NuPlayer::CCDecoder::isTrackValid(size_t index) const {
907    return index < getTrackCount();
908}
909
910int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const {
911    if (channel < sizeof(mTrackIndices)/sizeof(mTrackIndices[0])) {
912        return mTrackIndices[channel];
913    }
914    return -1;
915}
916
917// returns true if a new CC track is found
918bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
919    int64_t timeUs;
920    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
921
922    sp<ABuffer> sei;
923    if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
924        return false;
925    }
926
927    bool trackAdded = false;
928
929    NALBitReader br(sei->data() + 1, sei->size() - 1);
930    // sei_message()
931    while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
932        uint32_t payload_type = 0;
933        size_t payload_size = 0;
934        uint8_t last_byte;
935
936        do {
937            last_byte = br.getBits(8);
938            payload_type += last_byte;
939        } while (last_byte == 0xFF);
940
941        do {
942            last_byte = br.getBits(8);
943            payload_size += last_byte;
944        } while (last_byte == 0xFF);
945
946        // sei_payload()
947        if (payload_type == 4) {
948            // user_data_registered_itu_t_t35()
949
950            // ATSC A/72: 6.4.2
951            uint8_t itu_t_t35_country_code = br.getBits(8);
952            uint16_t itu_t_t35_provider_code = br.getBits(16);
953            uint32_t user_identifier = br.getBits(32);
954            uint8_t user_data_type_code = br.getBits(8);
955
956            payload_size -= 1 + 2 + 4 + 1;
957
958            if (itu_t_t35_country_code == 0xB5
959                    && itu_t_t35_provider_code == 0x0031
960                    && user_identifier == 'GA94'
961                    && user_data_type_code == 0x3) {
962                // MPEG_cc_data()
963                // ATSC A/53 Part 4: 6.2.3.1
964                br.skipBits(1); //process_em_data_flag
965                bool process_cc_data_flag = br.getBits(1);
966                br.skipBits(1); //additional_data_flag
967                size_t cc_count = br.getBits(5);
968                br.skipBits(8); // em_data;
969                payload_size -= 2;
970
971                if (process_cc_data_flag) {
972                    AString out;
973
974                    sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
975                    ccBuf->setRange(0, 0);
976
977                    for (size_t i = 0; i < cc_count; i++) {
978                        uint8_t marker = br.getBits(5);
979                        CHECK_EQ(marker, 0x1f);
980
981                        bool cc_valid = br.getBits(1);
982                        uint8_t cc_type = br.getBits(2);
983                        // remove odd parity bit
984                        uint8_t cc_data_1 = br.getBits(8) & 0x7f;
985                        uint8_t cc_data_2 = br.getBits(8) & 0x7f;
986
987                        if (cc_valid
988                                && (cc_type == 0 || cc_type == 1)) {
989                            CCData cc(cc_type, cc_data_1, cc_data_2);
990                            if (!isNullPad(&cc)) {
991                                size_t channel;
992                                if (cc.getChannel(&channel) && getTrackIndex(channel) < 0) {
993                                    mTrackIndices[channel] = mFoundChannels.size();
994                                    mFoundChannels.push_back(channel);
995                                    trackAdded = true;
996                                }
997                                memcpy(ccBuf->data() + ccBuf->size(),
998                                        (void *)&cc, sizeof(cc));
999                                ccBuf->setRange(0, ccBuf->size() + sizeof(CCData));
1000                            }
1001                        }
1002                    }
1003                    payload_size -= cc_count * 3;
1004
1005                    mCCMap.add(timeUs, ccBuf);
1006                    break;
1007                }
1008            } else {
1009                ALOGV("Malformed SEI payload type 4");
1010            }
1011        } else {
1012            ALOGV("Unsupported SEI payload type %d", payload_type);
1013        }
1014
1015        // skipping remaining bits of this payload
1016        br.skipBits(payload_size * 8);
1017    }
1018
1019    return trackAdded;
1020}
1021
1022sp<ABuffer> NuPlayer::CCDecoder::filterCCBuf(
1023        const sp<ABuffer> &ccBuf, size_t index) {
1024    sp<ABuffer> filteredCCBuf = new ABuffer(ccBuf->size());
1025    filteredCCBuf->setRange(0, 0);
1026
1027    size_t cc_count = ccBuf->size() / sizeof(CCData);
1028    const CCData* cc_data = (const CCData*)ccBuf->data();
1029    for (size_t i = 0; i < cc_count; ++i) {
1030        size_t channel;
1031        if (cc_data[i].getChannel(&channel)) {
1032            mCurrentChannel = channel;
1033        }
1034        if (mCurrentChannel == mFoundChannels[index]) {
1035            memcpy(filteredCCBuf->data() + filteredCCBuf->size(),
1036                    (void *)&cc_data[i], sizeof(CCData));
1037            filteredCCBuf->setRange(0, filteredCCBuf->size() + sizeof(CCData));
1038        }
1039    }
1040
1041    return filteredCCBuf;
1042}
1043
1044void NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) {
1045    if (extractFromSEI(accessUnit)) {
1046        ALOGI("Found CEA-608 track");
1047        sp<AMessage> msg = mNotify->dup();
1048        msg->setInt32("what", kWhatTrackAdded);
1049        msg->post();
1050    }
1051    // TODO: extract CC from other sources
1052}
1053
1054void NuPlayer::CCDecoder::display(int64_t timeUs) {
1055    if (!isTrackValid(mSelectedTrack)) {
1056        ALOGE("Could not find current track(index=%d)", mSelectedTrack);
1057        return;
1058    }
1059
1060    ssize_t index = mCCMap.indexOfKey(timeUs);
1061    if (index < 0) {
1062        ALOGV("cc for timestamp %" PRId64 " not found", timeUs);
1063        return;
1064    }
1065
1066    sp<ABuffer> ccBuf = filterCCBuf(mCCMap.valueAt(index), mSelectedTrack);
1067
1068    if (ccBuf->size() > 0) {
1069#if 0
1070        dumpBytePair(ccBuf);
1071#endif
1072
1073        ccBuf->meta()->setInt32("trackIndex", mSelectedTrack);
1074        ccBuf->meta()->setInt64("timeUs", timeUs);
1075        ccBuf->meta()->setInt64("durationUs", 0ll);
1076
1077        sp<AMessage> msg = mNotify->dup();
1078        msg->setInt32("what", kWhatClosedCaptionData);
1079        msg->setBuffer("buffer", ccBuf);
1080        msg->post();
1081    }
1082
1083    // remove all entries before timeUs
1084    mCCMap.removeItemsAt(0, index + 1);
1085}
1086
1087void NuPlayer::CCDecoder::flush() {
1088    mCCMap.clear();
1089}
1090
1091}  // namespace android
1092
1093