NuPlayer.cpp revision a7fa1d9530b6870f2c7850e3025d7db963661803
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 "NuPlayer"
19#include <utils/Log.h>
20
21#include "NuPlayer.h"
22
23#include "HTTPLiveSource.h"
24#include "NuPlayerDecoder.h"
25#include "NuPlayerDriver.h"
26#include "NuPlayerRenderer.h"
27#include "NuPlayerSource.h"
28#include "RTSPSource.h"
29#include "StreamingSource.h"
30#include "GenericSource.h"
31
32#include "ATSParser.h"
33
34#include <media/stagefright/foundation/hexdump.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/MediaDefs.h>
39#include <media/stagefright/MediaErrors.h>
40#include <media/stagefright/MetaData.h>
41#include <gui/IGraphicBufferProducer.h>
42
43#include "avc_utils.h"
44
45#include "ESDS.h"
46#include <media/stagefright/Utils.h>
47
48namespace android {
49
50struct NuPlayer::Action : public RefBase {
51    Action() {}
52
53    virtual void execute(NuPlayer *player) = 0;
54
55private:
56    DISALLOW_EVIL_CONSTRUCTORS(Action);
57};
58
59struct NuPlayer::SeekAction : public Action {
60    SeekAction(int64_t seekTimeUs)
61        : mSeekTimeUs(seekTimeUs) {
62    }
63
64    virtual void execute(NuPlayer *player) {
65        player->performSeek(mSeekTimeUs);
66    }
67
68private:
69    int64_t mSeekTimeUs;
70
71    DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
72};
73
74struct NuPlayer::SetSurfaceAction : public Action {
75    SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
76        : mWrapper(wrapper) {
77    }
78
79    virtual void execute(NuPlayer *player) {
80        player->performSetSurface(mWrapper);
81    }
82
83private:
84    sp<NativeWindowWrapper> mWrapper;
85
86    DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
87};
88
89struct NuPlayer::ShutdownDecoderAction : public Action {
90    ShutdownDecoderAction(bool audio, bool video)
91        : mAudio(audio),
92          mVideo(video) {
93    }
94
95    virtual void execute(NuPlayer *player) {
96        player->performDecoderShutdown(mAudio, mVideo);
97    }
98
99private:
100    bool mAudio;
101    bool mVideo;
102
103    DISALLOW_EVIL_CONSTRUCTORS(ShutdownDecoderAction);
104};
105
106struct NuPlayer::PostMessageAction : public Action {
107    PostMessageAction(const sp<AMessage> &msg)
108        : mMessage(msg) {
109    }
110
111    virtual void execute(NuPlayer *) {
112        mMessage->post();
113    }
114
115private:
116    sp<AMessage> mMessage;
117
118    DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction);
119};
120
121// Use this if there's no state necessary to save in order to execute
122// the action.
123struct NuPlayer::SimpleAction : public Action {
124    typedef void (NuPlayer::*ActionFunc)();
125
126    SimpleAction(ActionFunc func)
127        : mFunc(func) {
128    }
129
130    virtual void execute(NuPlayer *player) {
131        (player->*mFunc)();
132    }
133
134private:
135    ActionFunc mFunc;
136
137    DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
138};
139
140////////////////////////////////////////////////////////////////////////////////
141
142NuPlayer::NuPlayer()
143    : mUIDValid(false),
144      mSourceFlags(0),
145      mVideoIsAVC(false),
146      mAudioEOS(false),
147      mVideoEOS(false),
148      mScanSourcesPending(false),
149      mScanSourcesGeneration(0),
150      mPollDurationGeneration(0),
151      mTimeDiscontinuityPending(false),
152      mFlushingAudio(NONE),
153      mFlushingVideo(NONE),
154      mSkipRenderingAudioUntilMediaTimeUs(-1ll),
155      mSkipRenderingVideoUntilMediaTimeUs(-1ll),
156      mVideoLateByUs(0ll),
157      mNumFramesTotal(0ll),
158      mNumFramesDropped(0ll),
159      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
160      mStarted(false) {
161}
162
163NuPlayer::~NuPlayer() {
164}
165
166void NuPlayer::setUID(uid_t uid) {
167    mUIDValid = true;
168    mUID = uid;
169}
170
171void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
172    mDriver = driver;
173}
174
175void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
176    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
177
178    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
179
180    msg->setObject("source", new StreamingSource(notify, source));
181    msg->post();
182}
183
184static bool IsHTTPLiveURL(const char *url) {
185    if (!strncasecmp("http://", url, 7)
186            || !strncasecmp("https://", url, 8)
187            || !strncasecmp("file://", url, 7)) {
188        size_t len = strlen(url);
189        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
190            return true;
191        }
192
193        if (strstr(url,"m3u8")) {
194            return true;
195        }
196    }
197
198    return false;
199}
200
201void NuPlayer::setDataSourceAsync(
202        const sp<IMediaHTTPService> &httpService,
203        const char *url,
204        const KeyedVector<String8, String8> *headers) {
205    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
206    size_t len = strlen(url);
207
208    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
209
210    sp<Source> source;
211    if (IsHTTPLiveURL(url)) {
212        source = new HTTPLiveSource(notify, httpService, url, headers);
213    } else if (!strncasecmp(url, "rtsp://", 7)) {
214        source = new RTSPSource(
215                notify, httpService, url, headers, mUIDValid, mUID);
216    } else if ((!strncasecmp(url, "http://", 7)
217                || !strncasecmp(url, "https://", 8))
218                    && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
219                    || strstr(url, ".sdp?"))) {
220        source = new RTSPSource(
221                notify, httpService, url, headers, mUIDValid, mUID, true);
222    } else {
223        source = new GenericSource(notify, httpService, url, headers);
224    }
225
226    msg->setObject("source", source);
227    msg->post();
228}
229
230void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
231    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
232
233    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
234
235    sp<Source> source = new GenericSource(notify, fd, offset, length);
236    msg->setObject("source", source);
237    msg->post();
238}
239
240void NuPlayer::prepareAsync() {
241    (new AMessage(kWhatPrepare, id()))->post();
242}
243
244void NuPlayer::setVideoSurfaceTextureAsync(
245        const sp<IGraphicBufferProducer> &bufferProducer) {
246    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
247
248    if (bufferProducer == NULL) {
249        msg->setObject("native-window", NULL);
250    } else {
251        msg->setObject(
252                "native-window",
253                new NativeWindowWrapper(
254                    new Surface(bufferProducer)));
255    }
256
257    msg->post();
258}
259
260void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
261    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
262    msg->setObject("sink", sink);
263    msg->post();
264}
265
266void NuPlayer::start() {
267    (new AMessage(kWhatStart, id()))->post();
268}
269
270void NuPlayer::pause() {
271    (new AMessage(kWhatPause, id()))->post();
272}
273
274void NuPlayer::resume() {
275    (new AMessage(kWhatResume, id()))->post();
276}
277
278void NuPlayer::resetAsync() {
279    (new AMessage(kWhatReset, id()))->post();
280}
281
282void NuPlayer::seekToAsync(int64_t seekTimeUs) {
283    sp<AMessage> msg = new AMessage(kWhatSeek, id());
284    msg->setInt64("seekTimeUs", seekTimeUs);
285    msg->post();
286}
287
288// static
289bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
290    switch (state) {
291        case FLUSHING_DECODER:
292            if (needShutdown != NULL) {
293                *needShutdown = false;
294            }
295            return true;
296
297        case FLUSHING_DECODER_SHUTDOWN:
298            if (needShutdown != NULL) {
299                *needShutdown = true;
300            }
301            return true;
302
303        default:
304            return false;
305    }
306}
307
308void NuPlayer::writeTrackInfo(
309        Parcel* reply, const sp<AMessage> format) const {
310    int32_t trackType;
311    CHECK(format->findInt32("type", &trackType));
312
313    AString lang;
314    CHECK(format->findString("language", &lang));
315
316    reply->writeInt32(2); // write something non-zero
317    reply->writeInt32(trackType);
318    reply->writeString16(String16(lang.c_str()));
319
320    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
321        AString mime;
322        CHECK(format->findString("mime", &mime));
323
324        int32_t isAuto, isDefault, isForced;
325        CHECK(format->findInt32("auto", &isAuto));
326        CHECK(format->findInt32("default", &isDefault));
327        CHECK(format->findInt32("forced", &isForced));
328
329        reply->writeString16(String16(mime.c_str()));
330        reply->writeInt32(isAuto);
331        reply->writeInt32(isDefault);
332        reply->writeInt32(isForced);
333    }
334}
335
336void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
337    switch (msg->what()) {
338        case kWhatSetDataSource:
339        {
340            ALOGV("kWhatSetDataSource");
341
342            CHECK(mSource == NULL);
343
344            sp<RefBase> obj;
345            CHECK(msg->findObject("source", &obj));
346
347            mSource = static_cast<Source *>(obj.get());
348
349            looper()->registerHandler(mSource);
350
351            CHECK(mDriver != NULL);
352            sp<NuPlayerDriver> driver = mDriver.promote();
353            if (driver != NULL) {
354                driver->notifySetDataSourceCompleted(OK);
355            }
356            break;
357        }
358
359        case kWhatPrepare:
360        {
361            mSource->prepareAsync();
362            break;
363        }
364
365        case kWhatGetTrackInfo:
366        {
367            uint32_t replyID;
368            CHECK(msg->senderAwaitsResponse(&replyID));
369
370            Parcel* reply;
371            CHECK(msg->findPointer("reply", (void**)&reply));
372
373            size_t inbandTracks = 0;
374            if (mSource != NULL) {
375                inbandTracks = mSource->getTrackCount();
376            }
377
378            size_t ccTracks = 0;
379            if (mCCDecoder != NULL) {
380                ccTracks = mCCDecoder->getTrackCount();
381            }
382
383            // total track count
384            reply->writeInt32(inbandTracks + ccTracks);
385
386            // write inband tracks
387            for (size_t i = 0; i < inbandTracks; ++i) {
388                writeTrackInfo(reply, mSource->getTrackInfo(i));
389            }
390
391            // write CC track
392            for (size_t i = 0; i < ccTracks; ++i) {
393                writeTrackInfo(reply, mCCDecoder->getTrackInfo(i));
394            }
395
396            sp<AMessage> response = new AMessage;
397            response->postReply(replyID);
398            break;
399        }
400
401        case kWhatSelectTrack:
402        {
403            uint32_t replyID;
404            CHECK(msg->senderAwaitsResponse(&replyID));
405
406            size_t trackIndex;
407            int32_t select;
408            CHECK(msg->findSize("trackIndex", &trackIndex));
409            CHECK(msg->findInt32("select", &select));
410
411            status_t err = INVALID_OPERATION;
412
413            size_t inbandTracks = 0;
414            if (mSource != NULL) {
415                inbandTracks = mSource->getTrackCount();
416            }
417            size_t ccTracks = 0;
418            if (mCCDecoder != NULL) {
419                ccTracks = mCCDecoder->getTrackCount();
420            }
421
422            if (trackIndex < inbandTracks) {
423                err = mSource->selectTrack(trackIndex, select);
424            } else {
425                trackIndex -= inbandTracks;
426
427                if (trackIndex < ccTracks) {
428                    err = mCCDecoder->selectTrack(trackIndex, select);
429                }
430            }
431
432            sp<AMessage> response = new AMessage;
433            response->setInt32("err", err);
434
435            response->postReply(replyID);
436            break;
437        }
438
439        case kWhatPollDuration:
440        {
441            int32_t generation;
442            CHECK(msg->findInt32("generation", &generation));
443
444            if (generation != mPollDurationGeneration) {
445                // stale
446                break;
447            }
448
449            int64_t durationUs;
450            if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
451                sp<NuPlayerDriver> driver = mDriver.promote();
452                if (driver != NULL) {
453                    driver->notifyDuration(durationUs);
454                }
455            }
456
457            msg->post(1000000ll);  // poll again in a second.
458            break;
459        }
460
461        case kWhatSetVideoNativeWindow:
462        {
463            ALOGV("kWhatSetVideoNativeWindow");
464
465            mDeferredActions.push_back(
466                    new ShutdownDecoderAction(
467                        false /* audio */, true /* video */));
468
469            sp<RefBase> obj;
470            CHECK(msg->findObject("native-window", &obj));
471
472            mDeferredActions.push_back(
473                    new SetSurfaceAction(
474                        static_cast<NativeWindowWrapper *>(obj.get())));
475
476            if (obj != NULL) {
477                // If there is a new surface texture, instantiate decoders
478                // again if possible.
479                mDeferredActions.push_back(
480                        new SimpleAction(&NuPlayer::performScanSources));
481            }
482
483            processDeferredActions();
484            break;
485        }
486
487        case kWhatSetAudioSink:
488        {
489            ALOGV("kWhatSetAudioSink");
490
491            sp<RefBase> obj;
492            CHECK(msg->findObject("sink", &obj));
493
494            mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
495            break;
496        }
497
498        case kWhatStart:
499        {
500            ALOGV("kWhatStart");
501
502            mVideoIsAVC = false;
503            mAudioEOS = false;
504            mVideoEOS = false;
505            mSkipRenderingAudioUntilMediaTimeUs = -1;
506            mSkipRenderingVideoUntilMediaTimeUs = -1;
507            mVideoLateByUs = 0;
508            mNumFramesTotal = 0;
509            mNumFramesDropped = 0;
510            mStarted = true;
511
512            mSource->start();
513
514            uint32_t flags = 0;
515
516            if (mSource->isRealTime()) {
517                flags |= Renderer::FLAG_REAL_TIME;
518            }
519
520            mRenderer = new Renderer(
521                    mAudioSink,
522                    new AMessage(kWhatRendererNotify, id()),
523                    flags);
524
525            looper()->registerHandler(mRenderer);
526
527            postScanSources();
528            break;
529        }
530
531        case kWhatScanSources:
532        {
533            int32_t generation;
534            CHECK(msg->findInt32("generation", &generation));
535            if (generation != mScanSourcesGeneration) {
536                // Drop obsolete msg.
537                break;
538            }
539
540            mScanSourcesPending = false;
541
542            ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
543                 mAudioDecoder != NULL, mVideoDecoder != NULL);
544
545            bool mHadAnySourcesBefore =
546                (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
547
548            if (mNativeWindow != NULL) {
549                instantiateDecoder(false, &mVideoDecoder);
550            }
551
552            if (mAudioSink != NULL) {
553                instantiateDecoder(true, &mAudioDecoder);
554            }
555
556            if (!mHadAnySourcesBefore
557                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
558                // This is the first time we've found anything playable.
559
560                if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
561                    schedulePollDuration();
562                }
563            }
564
565            status_t err;
566            if ((err = mSource->feedMoreTSData()) != OK) {
567                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
568                    // We're not currently decoding anything (no audio or
569                    // video tracks found) and we just ran out of input data.
570
571                    if (err == ERROR_END_OF_STREAM) {
572                        notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
573                    } else {
574                        notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
575                    }
576                }
577                break;
578            }
579
580            if ((mAudioDecoder == NULL && mAudioSink != NULL)
581                    || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
582                msg->post(100000ll);
583                mScanSourcesPending = true;
584            }
585            break;
586        }
587
588        case kWhatVideoNotify:
589        case kWhatAudioNotify:
590        {
591            bool audio = msg->what() == kWhatAudioNotify;
592
593            int32_t what;
594            CHECK(msg->findInt32("what", &what));
595
596            if (what == Decoder::kWhatFillThisBuffer) {
597                status_t err = feedDecoderInputData(
598                        audio, msg);
599
600                if (err == -EWOULDBLOCK) {
601                    if (mSource->feedMoreTSData() == OK) {
602                        msg->post(10000ll);
603                    }
604                }
605            } else if (what == Decoder::kWhatEOS) {
606                int32_t err;
607                CHECK(msg->findInt32("err", &err));
608
609                if (err == ERROR_END_OF_STREAM) {
610                    ALOGV("got %s decoder EOS", audio ? "audio" : "video");
611                } else {
612                    ALOGV("got %s decoder EOS w/ error %d",
613                         audio ? "audio" : "video",
614                         err);
615                }
616
617                mRenderer->queueEOS(audio, err);
618            } else if (what == Decoder::kWhatFlushCompleted) {
619                bool needShutdown;
620
621                if (audio) {
622                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
623                    mFlushingAudio = FLUSHED;
624                } else {
625                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
626                    mFlushingVideo = FLUSHED;
627
628                    mVideoLateByUs = 0;
629                }
630
631                ALOGV("decoder %s flush completed", audio ? "audio" : "video");
632
633                if (needShutdown) {
634                    ALOGV("initiating %s decoder shutdown",
635                         audio ? "audio" : "video");
636
637                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
638
639                    if (audio) {
640                        mFlushingAudio = SHUTTING_DOWN_DECODER;
641                    } else {
642                        mFlushingVideo = SHUTTING_DOWN_DECODER;
643                    }
644                }
645
646                finishFlushIfPossible();
647            } else if (what == Decoder::kWhatOutputFormatChanged) {
648                sp<AMessage> format;
649                CHECK(msg->findMessage("format", &format));
650
651                if (audio) {
652                    int32_t numChannels;
653                    CHECK(format->findInt32(
654                                "channel-count", &numChannels));
655
656                    int32_t sampleRate;
657                    CHECK(format->findInt32("sample-rate", &sampleRate));
658
659                    ALOGV("Audio output format changed to %d Hz, %d channels",
660                         sampleRate, numChannels);
661
662                    mAudioSink->close();
663
664                    audio_output_flags_t flags;
665                    int64_t durationUs;
666                    // FIXME: we should handle the case where the video decoder
667                    // is created after we receive the format change indication.
668                    // Current code will just make that we select deep buffer
669                    // with video which should not be a problem as it should
670                    // not prevent from keeping A/V sync.
671                    if (mVideoDecoder == NULL &&
672                            mSource->getDuration(&durationUs) == OK &&
673                            durationUs
674                                > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
675                        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
676                    } else {
677                        flags = AUDIO_OUTPUT_FLAG_NONE;
678                    }
679
680                    int32_t channelMask;
681                    if (!format->findInt32("channel-mask", &channelMask)) {
682                        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
683                    }
684
685                    CHECK_EQ(mAudioSink->open(
686                                sampleRate,
687                                numChannels,
688                                (audio_channel_mask_t)channelMask,
689                                AUDIO_FORMAT_PCM_16_BIT,
690                                8 /* bufferCount */,
691                                NULL,
692                                NULL,
693                                flags),
694                             (status_t)OK);
695                    mAudioSink->start();
696
697                    mRenderer->signalAudioSinkChanged();
698                } else {
699                    // video
700
701                    int32_t width, height;
702                    CHECK(format->findInt32("width", &width));
703                    CHECK(format->findInt32("height", &height));
704
705                    int32_t cropLeft, cropTop, cropRight, cropBottom;
706                    CHECK(format->findRect(
707                                "crop",
708                                &cropLeft, &cropTop, &cropRight, &cropBottom));
709
710                    int32_t displayWidth = cropRight - cropLeft + 1;
711                    int32_t displayHeight = cropBottom - cropTop + 1;
712
713                    ALOGV("Video output format changed to %d x %d "
714                         "(crop: %d x %d @ (%d, %d))",
715                         width, height,
716                         displayWidth,
717                         displayHeight,
718                         cropLeft, cropTop);
719
720                    sp<AMessage> videoInputFormat =
721                        mSource->getFormat(false /* audio */);
722
723                    // Take into account sample aspect ratio if necessary:
724                    int32_t sarWidth, sarHeight;
725                    if (videoInputFormat->findInt32("sar-width", &sarWidth)
726                            && videoInputFormat->findInt32(
727                                "sar-height", &sarHeight)) {
728                        ALOGV("Sample aspect ratio %d : %d",
729                              sarWidth, sarHeight);
730
731                        displayWidth = (displayWidth * sarWidth) / sarHeight;
732
733                        ALOGV("display dimensions %d x %d",
734                              displayWidth, displayHeight);
735                    }
736
737                    notifyListener(
738                            MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
739                }
740            } else if (what == Decoder::kWhatShutdownCompleted) {
741                ALOGV("%s shutdown completed", audio ? "audio" : "video");
742                if (audio) {
743                    mAudioDecoder.clear();
744
745                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
746                    mFlushingAudio = SHUT_DOWN;
747                } else {
748                    mVideoDecoder.clear();
749
750                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
751                    mFlushingVideo = SHUT_DOWN;
752                }
753
754                finishFlushIfPossible();
755            } else if (what == Decoder::kWhatError) {
756                ALOGE("Received error from %s decoder, aborting playback.",
757                     audio ? "audio" : "video");
758
759                mRenderer->queueEOS(audio, UNKNOWN_ERROR);
760            } else if (what == Decoder::kWhatDrainThisBuffer) {
761                renderBuffer(audio, msg);
762            } else {
763                ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
764                      what,
765                      what >> 24,
766                      (what >> 16) & 0xff,
767                      (what >> 8) & 0xff,
768                      what & 0xff);
769            }
770
771            break;
772        }
773
774        case kWhatRendererNotify:
775        {
776            int32_t what;
777            CHECK(msg->findInt32("what", &what));
778
779            if (what == Renderer::kWhatEOS) {
780                int32_t audio;
781                CHECK(msg->findInt32("audio", &audio));
782
783                int32_t finalResult;
784                CHECK(msg->findInt32("finalResult", &finalResult));
785
786                if (audio) {
787                    mAudioEOS = true;
788                } else {
789                    mVideoEOS = true;
790                }
791
792                if (finalResult == ERROR_END_OF_STREAM) {
793                    ALOGV("reached %s EOS", audio ? "audio" : "video");
794                } else {
795                    ALOGE("%s track encountered an error (%d)",
796                         audio ? "audio" : "video", finalResult);
797
798                    notifyListener(
799                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
800                }
801
802                if ((mAudioEOS || mAudioDecoder == NULL)
803                        && (mVideoEOS || mVideoDecoder == NULL)) {
804                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
805                }
806            } else if (what == Renderer::kWhatPosition) {
807                int64_t positionUs;
808                CHECK(msg->findInt64("positionUs", &positionUs));
809
810                CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
811
812                if (mDriver != NULL) {
813                    sp<NuPlayerDriver> driver = mDriver.promote();
814                    if (driver != NULL) {
815                        driver->notifyPosition(positionUs);
816
817                        driver->notifyFrameStats(
818                                mNumFramesTotal, mNumFramesDropped);
819                    }
820                }
821            } else if (what == Renderer::kWhatFlushComplete) {
822                int32_t audio;
823                CHECK(msg->findInt32("audio", &audio));
824
825                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
826            } else if (what == Renderer::kWhatVideoRenderingStart) {
827                notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
828            } else if (what == Renderer::kWhatMediaRenderingStart) {
829                ALOGV("media rendering started");
830                notifyListener(MEDIA_STARTED, 0, 0);
831            }
832            break;
833        }
834
835        case kWhatMoreDataQueued:
836        {
837            break;
838        }
839
840        case kWhatReset:
841        {
842            ALOGV("kWhatReset");
843
844            mDeferredActions.push_back(
845                    new ShutdownDecoderAction(
846                        true /* audio */, true /* video */));
847
848            mDeferredActions.push_back(
849                    new SimpleAction(&NuPlayer::performReset));
850
851            processDeferredActions();
852            break;
853        }
854
855        case kWhatSeek:
856        {
857            int64_t seekTimeUs;
858            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
859
860            ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
861
862            mDeferredActions.push_back(
863                    new SimpleAction(&NuPlayer::performDecoderFlush));
864
865            mDeferredActions.push_back(new SeekAction(seekTimeUs));
866
867            processDeferredActions();
868            break;
869        }
870
871        case kWhatPause:
872        {
873            CHECK(mRenderer != NULL);
874            mSource->pause();
875            mRenderer->pause();
876            break;
877        }
878
879        case kWhatResume:
880        {
881            CHECK(mRenderer != NULL);
882            mSource->resume();
883            mRenderer->resume();
884            break;
885        }
886
887        case kWhatSourceNotify:
888        {
889            onSourceNotify(msg);
890            break;
891        }
892
893        case kWhatClosedCaptionNotify:
894        {
895            onClosedCaptionNotify(msg);
896            break;
897        }
898
899        default:
900            TRESPASS();
901            break;
902    }
903}
904
905void NuPlayer::finishFlushIfPossible() {
906    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
907        return;
908    }
909
910    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
911        return;
912    }
913
914    ALOGV("both audio and video are flushed now.");
915
916    if (mTimeDiscontinuityPending) {
917        mRenderer->signalTimeDiscontinuity();
918        mTimeDiscontinuityPending = false;
919    }
920
921    if (mAudioDecoder != NULL) {
922        mAudioDecoder->signalResume();
923    }
924
925    if (mVideoDecoder != NULL) {
926        mVideoDecoder->signalResume();
927    }
928
929    mFlushingAudio = NONE;
930    mFlushingVideo = NONE;
931
932    processDeferredActions();
933}
934
935void NuPlayer::postScanSources() {
936    if (mScanSourcesPending) {
937        return;
938    }
939
940    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
941    msg->setInt32("generation", mScanSourcesGeneration);
942    msg->post();
943
944    mScanSourcesPending = true;
945}
946
947status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
948    if (*decoder != NULL) {
949        return OK;
950    }
951
952    sp<AMessage> format = mSource->getFormat(audio);
953
954    if (format == NULL) {
955        return -EWOULDBLOCK;
956    }
957
958    if (!audio) {
959        AString mime;
960        CHECK(format->findString("mime", &mime));
961        mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
962
963        sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, id());
964        mCCDecoder = new CCDecoder(ccNotify);
965    }
966
967    sp<AMessage> notify =
968        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
969                     id());
970
971    *decoder = audio ? new Decoder(notify) :
972                       new Decoder(notify, mNativeWindow);
973    (*decoder)->init();
974    (*decoder)->configure(format);
975
976    return OK;
977}
978
979status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
980    sp<AMessage> reply;
981    CHECK(msg->findMessage("reply", &reply));
982
983    if ((audio && IsFlushingState(mFlushingAudio))
984            || (!audio && IsFlushingState(mFlushingVideo))) {
985        reply->setInt32("err", INFO_DISCONTINUITY);
986        reply->post();
987        return OK;
988    }
989
990    sp<ABuffer> accessUnit;
991
992    bool dropAccessUnit;
993    do {
994        status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
995
996        if (err == -EWOULDBLOCK) {
997            return err;
998        } else if (err != OK) {
999            if (err == INFO_DISCONTINUITY) {
1000                int32_t type;
1001                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
1002
1003                bool formatChange =
1004                    (audio &&
1005                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
1006                    || (!audio &&
1007                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
1008
1009                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
1010
1011                ALOGI("%s discontinuity (formatChange=%d, time=%d)",
1012                     audio ? "audio" : "video", formatChange, timeChange);
1013
1014                if (audio) {
1015                    mSkipRenderingAudioUntilMediaTimeUs = -1;
1016                } else {
1017                    mSkipRenderingVideoUntilMediaTimeUs = -1;
1018                }
1019
1020                if (timeChange) {
1021                    sp<AMessage> extra;
1022                    if (accessUnit->meta()->findMessage("extra", &extra)
1023                            && extra != NULL) {
1024                        int64_t resumeAtMediaTimeUs;
1025                        if (extra->findInt64(
1026                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
1027                            ALOGI("suppressing rendering of %s until %lld us",
1028                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
1029
1030                            if (audio) {
1031                                mSkipRenderingAudioUntilMediaTimeUs =
1032                                    resumeAtMediaTimeUs;
1033                            } else {
1034                                mSkipRenderingVideoUntilMediaTimeUs =
1035                                    resumeAtMediaTimeUs;
1036                            }
1037                        }
1038                    }
1039                }
1040
1041                mTimeDiscontinuityPending =
1042                    mTimeDiscontinuityPending || timeChange;
1043
1044                if (formatChange || timeChange) {
1045                    if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
1046                        // And we'll resume scanning sources once we're done
1047                        // flushing.
1048                        mDeferredActions.push_front(
1049                                new SimpleAction(
1050                                    &NuPlayer::performScanSources));
1051                    }
1052
1053                    sp<AMessage> newFormat = mSource->getFormat(audio);
1054                    sp<Decoder> &decoder = audio ? mAudioDecoder : mVideoDecoder;
1055                    if (formatChange && !decoder->supportsSeamlessFormatChange(newFormat)) {
1056                        flushDecoder(audio, /* needShutdown = */ true);
1057                    } else {
1058                        flushDecoder(audio, /* needShutdown = */ false);
1059                        err = OK;
1060                    }
1061                } else {
1062                    // This stream is unaffected by the discontinuity
1063
1064                    if (audio) {
1065                        mFlushingAudio = FLUSHED;
1066                    } else {
1067                        mFlushingVideo = FLUSHED;
1068                    }
1069
1070                    finishFlushIfPossible();
1071
1072                    return -EWOULDBLOCK;
1073                }
1074            }
1075
1076            reply->setInt32("err", err);
1077            reply->post();
1078            return OK;
1079        }
1080
1081        if (!audio) {
1082            ++mNumFramesTotal;
1083        }
1084
1085        dropAccessUnit = false;
1086        if (!audio
1087                && mVideoLateByUs > 100000ll
1088                && mVideoIsAVC
1089                && !IsAVCReferenceFrame(accessUnit)) {
1090            dropAccessUnit = true;
1091            ++mNumFramesDropped;
1092        }
1093    } while (dropAccessUnit);
1094
1095    // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
1096
1097#if 0
1098    int64_t mediaTimeUs;
1099    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
1100    ALOGV("feeding %s input buffer at media time %.2f secs",
1101         audio ? "audio" : "video",
1102         mediaTimeUs / 1E6);
1103#endif
1104
1105    if (!audio) {
1106        mCCDecoder->decode(accessUnit);
1107    }
1108
1109    reply->setBuffer("buffer", accessUnit);
1110    reply->post();
1111
1112    return OK;
1113}
1114
1115void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
1116    // ALOGV("renderBuffer %s", audio ? "audio" : "video");
1117
1118    sp<AMessage> reply;
1119    CHECK(msg->findMessage("reply", &reply));
1120
1121    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
1122        // We're currently attempting to flush the decoder, in order
1123        // to complete this, the decoder wants all its buffers back,
1124        // so we don't want any output buffers it sent us (from before
1125        // we initiated the flush) to be stuck in the renderer's queue.
1126
1127        ALOGV("we're still flushing the %s decoder, sending its output buffer"
1128             " right back.", audio ? "audio" : "video");
1129
1130        reply->post();
1131        return;
1132    }
1133
1134    sp<ABuffer> buffer;
1135    CHECK(msg->findBuffer("buffer", &buffer));
1136
1137    int64_t mediaTimeUs;
1138    CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
1139
1140    int64_t &skipUntilMediaTimeUs =
1141        audio
1142            ? mSkipRenderingAudioUntilMediaTimeUs
1143            : mSkipRenderingVideoUntilMediaTimeUs;
1144
1145    if (skipUntilMediaTimeUs >= 0) {
1146
1147        if (mediaTimeUs < skipUntilMediaTimeUs) {
1148            ALOGV("dropping %s buffer at time %lld as requested.",
1149                 audio ? "audio" : "video",
1150                 mediaTimeUs);
1151
1152            reply->post();
1153            return;
1154        }
1155
1156        skipUntilMediaTimeUs = -1;
1157    }
1158
1159    if (!audio && mCCDecoder->isSelected()) {
1160        mCCDecoder->display(mediaTimeUs);
1161    }
1162
1163    mRenderer->queueBuffer(audio, buffer, reply);
1164}
1165
1166void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
1167    if (mDriver == NULL) {
1168        return;
1169    }
1170
1171    sp<NuPlayerDriver> driver = mDriver.promote();
1172
1173    if (driver == NULL) {
1174        return;
1175    }
1176
1177    driver->notifyListener(msg, ext1, ext2, in);
1178}
1179
1180void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
1181    ALOGV("[%s] flushDecoder needShutdown=%d",
1182          audio ? "audio" : "video", needShutdown);
1183
1184    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
1185        ALOGI("flushDecoder %s without decoder present",
1186             audio ? "audio" : "video");
1187    }
1188
1189    // Make sure we don't continue to scan sources until we finish flushing.
1190    ++mScanSourcesGeneration;
1191    mScanSourcesPending = false;
1192
1193    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
1194    mRenderer->flush(audio);
1195
1196    FlushStatus newStatus =
1197        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1198
1199    if (audio) {
1200        CHECK(mFlushingAudio == NONE
1201                || mFlushingAudio == AWAITING_DISCONTINUITY);
1202
1203        mFlushingAudio = newStatus;
1204
1205        if (mFlushingVideo == NONE) {
1206            mFlushingVideo = (mVideoDecoder != NULL)
1207                ? AWAITING_DISCONTINUITY
1208                : FLUSHED;
1209        }
1210    } else {
1211        CHECK(mFlushingVideo == NONE
1212                || mFlushingVideo == AWAITING_DISCONTINUITY);
1213
1214        mFlushingVideo = newStatus;
1215
1216        if (mFlushingAudio == NONE) {
1217            mFlushingAudio = (mAudioDecoder != NULL)
1218                ? AWAITING_DISCONTINUITY
1219                : FLUSHED;
1220        }
1221    }
1222}
1223
1224sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1225    sp<MetaData> meta = getFormatMeta(audio);
1226
1227    if (meta == NULL) {
1228        return NULL;
1229    }
1230
1231    sp<AMessage> msg = new AMessage;
1232
1233    if(convertMetaDataToMessage(meta, &msg) == OK) {
1234        return msg;
1235    }
1236    return NULL;
1237}
1238
1239status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1240    mVideoScalingMode = mode;
1241    if (mNativeWindow != NULL) {
1242        status_t ret = native_window_set_scaling_mode(
1243                mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1244        if (ret != OK) {
1245            ALOGE("Failed to set scaling mode (%d): %s",
1246                -ret, strerror(-ret));
1247            return ret;
1248        }
1249    }
1250    return OK;
1251}
1252
1253status_t NuPlayer::getTrackInfo(Parcel* reply) const {
1254    sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, id());
1255    msg->setPointer("reply", reply);
1256
1257    sp<AMessage> response;
1258    status_t err = msg->postAndAwaitResponse(&response);
1259    return err;
1260}
1261
1262status_t NuPlayer::selectTrack(size_t trackIndex, bool select) {
1263    sp<AMessage> msg = new AMessage(kWhatSelectTrack, id());
1264    msg->setSize("trackIndex", trackIndex);
1265    msg->setInt32("select", select);
1266
1267    sp<AMessage> response;
1268    status_t err = msg->postAndAwaitResponse(&response);
1269
1270    if (err != OK) {
1271        return err;
1272    }
1273
1274    if (!response->findInt32("err", &err)) {
1275        err = OK;
1276    }
1277
1278    return err;
1279}
1280
1281void NuPlayer::schedulePollDuration() {
1282    sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1283    msg->setInt32("generation", mPollDurationGeneration);
1284    msg->post();
1285}
1286
1287void NuPlayer::cancelPollDuration() {
1288    ++mPollDurationGeneration;
1289}
1290
1291void NuPlayer::processDeferredActions() {
1292    while (!mDeferredActions.empty()) {
1293        // We won't execute any deferred actions until we're no longer in
1294        // an intermediate state, i.e. one more more decoders are currently
1295        // flushing or shutting down.
1296
1297        if (mRenderer != NULL) {
1298            // There's an edge case where the renderer owns all output
1299            // buffers and is paused, therefore the decoder will not read
1300            // more input data and will never encounter the matching
1301            // discontinuity. To avoid this, we resume the renderer.
1302
1303            if (mFlushingAudio == AWAITING_DISCONTINUITY
1304                    || mFlushingVideo == AWAITING_DISCONTINUITY) {
1305                mRenderer->resume();
1306            }
1307        }
1308
1309        if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1310            // We're currently flushing, postpone the reset until that's
1311            // completed.
1312
1313            ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1314                  mFlushingAudio, mFlushingVideo);
1315
1316            break;
1317        }
1318
1319        sp<Action> action = *mDeferredActions.begin();
1320        mDeferredActions.erase(mDeferredActions.begin());
1321
1322        action->execute(this);
1323    }
1324}
1325
1326void NuPlayer::performSeek(int64_t seekTimeUs) {
1327    ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1328          seekTimeUs,
1329          seekTimeUs / 1E6);
1330
1331    mSource->seekTo(seekTimeUs);
1332
1333    if (mDriver != NULL) {
1334        sp<NuPlayerDriver> driver = mDriver.promote();
1335        if (driver != NULL) {
1336            driver->notifyPosition(seekTimeUs);
1337            driver->notifySeekComplete();
1338        }
1339    }
1340
1341    // everything's flushed, continue playback.
1342}
1343
1344void NuPlayer::performDecoderFlush() {
1345    ALOGV("performDecoderFlush");
1346
1347    if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
1348        return;
1349    }
1350
1351    mTimeDiscontinuityPending = true;
1352
1353    if (mAudioDecoder != NULL) {
1354        flushDecoder(true /* audio */, false /* needShutdown */);
1355    }
1356
1357    if (mVideoDecoder != NULL) {
1358        flushDecoder(false /* audio */, false /* needShutdown */);
1359    }
1360}
1361
1362void NuPlayer::performDecoderShutdown(bool audio, bool video) {
1363    ALOGV("performDecoderShutdown audio=%d, video=%d", audio, video);
1364
1365    if ((!audio || mAudioDecoder == NULL)
1366            && (!video || mVideoDecoder == NULL)) {
1367        return;
1368    }
1369
1370    mTimeDiscontinuityPending = true;
1371
1372    if (mFlushingAudio == NONE && (!audio || mAudioDecoder == NULL)) {
1373        mFlushingAudio = FLUSHED;
1374    }
1375
1376    if (mFlushingVideo == NONE && (!video || mVideoDecoder == NULL)) {
1377        mFlushingVideo = FLUSHED;
1378    }
1379
1380    if (audio && mAudioDecoder != NULL) {
1381        flushDecoder(true /* audio */, true /* needShutdown */);
1382    }
1383
1384    if (video && mVideoDecoder != NULL) {
1385        flushDecoder(false /* audio */, true /* needShutdown */);
1386    }
1387}
1388
1389void NuPlayer::performReset() {
1390    ALOGV("performReset");
1391
1392    CHECK(mAudioDecoder == NULL);
1393    CHECK(mVideoDecoder == NULL);
1394
1395    cancelPollDuration();
1396
1397    ++mScanSourcesGeneration;
1398    mScanSourcesPending = false;
1399
1400    mRenderer.clear();
1401
1402    if (mSource != NULL) {
1403        mSource->stop();
1404
1405        looper()->unregisterHandler(mSource->id());
1406
1407        mSource.clear();
1408    }
1409
1410    if (mDriver != NULL) {
1411        sp<NuPlayerDriver> driver = mDriver.promote();
1412        if (driver != NULL) {
1413            driver->notifyResetComplete();
1414        }
1415    }
1416
1417    mStarted = false;
1418}
1419
1420void NuPlayer::performScanSources() {
1421    ALOGV("performScanSources");
1422
1423    if (!mStarted) {
1424        return;
1425    }
1426
1427    if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1428        postScanSources();
1429    }
1430}
1431
1432void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1433    ALOGV("performSetSurface");
1434
1435    mNativeWindow = wrapper;
1436
1437    // XXX - ignore error from setVideoScalingMode for now
1438    setVideoScalingMode(mVideoScalingMode);
1439
1440    if (mDriver != NULL) {
1441        sp<NuPlayerDriver> driver = mDriver.promote();
1442        if (driver != NULL) {
1443            driver->notifySetSurfaceComplete();
1444        }
1445    }
1446}
1447
1448void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1449    int32_t what;
1450    CHECK(msg->findInt32("what", &what));
1451
1452    switch (what) {
1453        case Source::kWhatPrepared:
1454        {
1455            if (mSource == NULL) {
1456                // This is a stale notification from a source that was
1457                // asynchronously preparing when the client called reset().
1458                // We handled the reset, the source is gone.
1459                break;
1460            }
1461
1462            int32_t err;
1463            CHECK(msg->findInt32("err", &err));
1464
1465            sp<NuPlayerDriver> driver = mDriver.promote();
1466            if (driver != NULL) {
1467                // notify duration first, so that it's definitely set when
1468                // the app received the "prepare complete" callback.
1469                int64_t durationUs;
1470                if (mSource->getDuration(&durationUs) == OK) {
1471                    driver->notifyDuration(durationUs);
1472                }
1473                driver->notifyPrepareCompleted(err);
1474            }
1475
1476            break;
1477        }
1478
1479        case Source::kWhatFlagsChanged:
1480        {
1481            uint32_t flags;
1482            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1483
1484            sp<NuPlayerDriver> driver = mDriver.promote();
1485            if (driver != NULL) {
1486                driver->notifyFlagsChanged(flags);
1487            }
1488
1489            if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1490                    && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1491                cancelPollDuration();
1492            } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1493                    && (flags & Source::FLAG_DYNAMIC_DURATION)
1494                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1495                schedulePollDuration();
1496            }
1497
1498            mSourceFlags = flags;
1499            break;
1500        }
1501
1502        case Source::kWhatVideoSizeChanged:
1503        {
1504            int32_t width, height;
1505            CHECK(msg->findInt32("width", &width));
1506            CHECK(msg->findInt32("height", &height));
1507
1508            notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
1509            break;
1510        }
1511
1512        case Source::kWhatBufferingStart:
1513        {
1514            notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
1515            break;
1516        }
1517
1518        case Source::kWhatBufferingEnd:
1519        {
1520            notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
1521            break;
1522        }
1523
1524        case Source::kWhatSubtitleData:
1525        {
1526            sp<ABuffer> buffer;
1527            CHECK(msg->findBuffer("buffer", &buffer));
1528
1529            sendSubtitleData(buffer, 0 /* baseIndex */);
1530            break;
1531        }
1532
1533        case Source::kWhatQueueDecoderShutdown:
1534        {
1535            int32_t audio, video;
1536            CHECK(msg->findInt32("audio", &audio));
1537            CHECK(msg->findInt32("video", &video));
1538
1539            sp<AMessage> reply;
1540            CHECK(msg->findMessage("reply", &reply));
1541
1542            queueDecoderShutdown(audio, video, reply);
1543            break;
1544        }
1545
1546        default:
1547            TRESPASS();
1548    }
1549}
1550
1551void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) {
1552    int32_t what;
1553    CHECK(msg->findInt32("what", &what));
1554
1555    switch (what) {
1556        case NuPlayer::CCDecoder::kWhatClosedCaptionData:
1557        {
1558            sp<ABuffer> buffer;
1559            CHECK(msg->findBuffer("buffer", &buffer));
1560
1561            size_t inbandTracks = 0;
1562            if (mSource != NULL) {
1563                inbandTracks = mSource->getTrackCount();
1564            }
1565
1566            sendSubtitleData(buffer, inbandTracks);
1567            break;
1568        }
1569
1570        case NuPlayer::CCDecoder::kWhatTrackAdded:
1571        {
1572            notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0);
1573
1574            break;
1575        }
1576
1577        default:
1578            TRESPASS();
1579    }
1580
1581
1582}
1583
1584void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) {
1585    int32_t trackIndex;
1586    int64_t timeUs, durationUs;
1587    CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex));
1588    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1589    CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
1590
1591    Parcel in;
1592    in.writeInt32(trackIndex + baseIndex);
1593    in.writeInt64(timeUs);
1594    in.writeInt64(durationUs);
1595    in.writeInt32(buffer->size());
1596    in.writeInt32(buffer->size());
1597    in.write(buffer->data(), buffer->size());
1598
1599    notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in);
1600}
1601////////////////////////////////////////////////////////////////////////////////
1602
1603void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1604    sp<AMessage> notify = dupNotify();
1605    notify->setInt32("what", kWhatFlagsChanged);
1606    notify->setInt32("flags", flags);
1607    notify->post();
1608}
1609
1610void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
1611    sp<AMessage> notify = dupNotify();
1612    notify->setInt32("what", kWhatVideoSizeChanged);
1613    notify->setInt32("width", width);
1614    notify->setInt32("height", height);
1615    notify->post();
1616}
1617
1618void NuPlayer::Source::notifyPrepared(status_t err) {
1619    sp<AMessage> notify = dupNotify();
1620    notify->setInt32("what", kWhatPrepared);
1621    notify->setInt32("err", err);
1622    notify->post();
1623}
1624
1625void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) {
1626    TRESPASS();
1627}
1628
1629void NuPlayer::queueDecoderShutdown(
1630        bool audio, bool video, const sp<AMessage> &reply) {
1631    ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
1632
1633    mDeferredActions.push_back(
1634            new ShutdownDecoderAction(audio, video));
1635
1636    mDeferredActions.push_back(
1637            new SimpleAction(&NuPlayer::performScanSources));
1638
1639    mDeferredActions.push_back(new PostMessageAction(reply));
1640
1641    processDeferredActions();
1642}
1643
1644}  // namespace android
1645