NuPlayer.cpp revision 516dacfb02d0b0eafe21114330c98ce0e7d90da9
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#include "mp4/MP4Source.h"
32
33#include "ATSParser.h"
34
35#include <cutils/properties.h> // for property_get
36#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/foundation/ABuffer.h>
38#include <media/stagefright/foundation/ADebug.h>
39#include <media/stagefright/foundation/AMessage.h>
40#include <media/stagefright/ACodec.h>
41#include <media/stagefright/MediaDefs.h>
42#include <media/stagefright/MediaErrors.h>
43#include <media/stagefright/MetaData.h>
44#include <gui/ISurfaceTexture.h>
45
46#include "avc_utils.h"
47
48#include "ESDS.h"
49#include <media/stagefright/Utils.h>
50
51namespace android {
52
53struct NuPlayer::Action : public RefBase {
54    Action() {}
55
56    virtual void execute(NuPlayer *player) = 0;
57
58private:
59    DISALLOW_EVIL_CONSTRUCTORS(Action);
60};
61
62struct NuPlayer::SeekAction : public Action {
63    SeekAction(int64_t seekTimeUs)
64        : mSeekTimeUs(seekTimeUs) {
65    }
66
67    virtual void execute(NuPlayer *player) {
68        player->performSeek(mSeekTimeUs);
69    }
70
71private:
72    int64_t mSeekTimeUs;
73
74    DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
75};
76
77// Use this if there's no state necessary to save in order to execute
78// the action.
79struct NuPlayer::SimpleAction : public Action {
80    typedef void (NuPlayer::*ActionFunc)();
81
82    SimpleAction(ActionFunc func)
83        : mFunc(func) {
84    }
85
86    virtual void execute(NuPlayer *player) {
87        (player->*mFunc)();
88    }
89
90private:
91    ActionFunc mFunc;
92
93    DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
94};
95
96////////////////////////////////////////////////////////////////////////////////
97
98NuPlayer::NuPlayer()
99    : mUIDValid(false),
100      mVideoIsAVC(false),
101      mAudioEOS(false),
102      mVideoEOS(false),
103      mScanSourcesPending(false),
104      mScanSourcesGeneration(0),
105      mPollDurationGeneration(0),
106      mTimeDiscontinuityPending(false),
107      mFlushingAudio(NONE),
108      mFlushingVideo(NONE),
109      mSkipRenderingAudioUntilMediaTimeUs(-1ll),
110      mSkipRenderingVideoUntilMediaTimeUs(-1ll),
111      mVideoLateByUs(0ll),
112      mNumFramesTotal(0ll),
113      mNumFramesDropped(0ll),
114      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) {
115}
116
117NuPlayer::~NuPlayer() {
118}
119
120void NuPlayer::setUID(uid_t uid) {
121    mUIDValid = true;
122    mUID = uid;
123}
124
125void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
126    mDriver = driver;
127}
128
129void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
130    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
131
132    char prop[PROPERTY_VALUE_MAX];
133    if (property_get("media.stagefright.use-mp4source", prop, NULL)
134            && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
135        msg->setObject("source", new MP4Source(source));
136    } else {
137        msg->setObject("source", new StreamingSource(source));
138    }
139
140    msg->post();
141}
142
143static bool IsHTTPLiveURL(const char *url) {
144    if (!strncasecmp("http://", url, 7)
145            || !strncasecmp("https://", url, 8)) {
146        size_t len = strlen(url);
147        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
148            return true;
149        }
150
151        if (strstr(url,"m3u8")) {
152            return true;
153        }
154    }
155
156    return false;
157}
158
159void NuPlayer::setDataSource(
160        const char *url, const KeyedVector<String8, String8> *headers) {
161    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
162
163    sp<Source> source;
164    if (IsHTTPLiveURL(url)) {
165        source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
166    } else if (!strncasecmp(url, "rtsp://", 7)) {
167        source = new RTSPSource(url, headers, mUIDValid, mUID);
168    } else {
169        source = new GenericSource(url, headers, mUIDValid, mUID);
170    }
171
172    msg->setObject("source", source);
173    msg->post();
174}
175
176void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
177    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
178
179    sp<Source> source = new GenericSource(fd, offset, length);
180    msg->setObject("source", source);
181    msg->post();
182}
183
184void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
185    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
186    sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
187                new SurfaceTextureClient(surfaceTexture) : NULL);
188    msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient));
189    msg->post();
190}
191
192void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
193    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
194    msg->setObject("sink", sink);
195    msg->post();
196}
197
198void NuPlayer::start() {
199    (new AMessage(kWhatStart, id()))->post();
200}
201
202void NuPlayer::pause() {
203    (new AMessage(kWhatPause, id()))->post();
204}
205
206void NuPlayer::resume() {
207    (new AMessage(kWhatResume, id()))->post();
208}
209
210void NuPlayer::resetAsync() {
211    (new AMessage(kWhatReset, id()))->post();
212}
213
214void NuPlayer::seekToAsync(int64_t seekTimeUs) {
215    sp<AMessage> msg = new AMessage(kWhatSeek, id());
216    msg->setInt64("seekTimeUs", seekTimeUs);
217    msg->post();
218}
219
220// static
221bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
222    switch (state) {
223        case FLUSHING_DECODER:
224            if (needShutdown != NULL) {
225                *needShutdown = false;
226            }
227            return true;
228
229        case FLUSHING_DECODER_SHUTDOWN:
230            if (needShutdown != NULL) {
231                *needShutdown = true;
232            }
233            return true;
234
235        default:
236            return false;
237    }
238}
239
240void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
241    switch (msg->what()) {
242        case kWhatSetDataSource:
243        {
244            ALOGV("kWhatSetDataSource");
245
246            CHECK(mSource == NULL);
247
248            sp<RefBase> obj;
249            CHECK(msg->findObject("source", &obj));
250
251            mSource = static_cast<Source *>(obj.get());
252            break;
253        }
254
255        case kWhatPollDuration:
256        {
257            int32_t generation;
258            CHECK(msg->findInt32("generation", &generation));
259
260            if (generation != mPollDurationGeneration) {
261                // stale
262                break;
263            }
264
265            int64_t durationUs;
266            if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
267                sp<NuPlayerDriver> driver = mDriver.promote();
268                if (driver != NULL) {
269                    driver->notifyDuration(durationUs);
270                }
271            }
272
273            msg->post(1000000ll);  // poll again in a second.
274            break;
275        }
276
277        case kWhatSetVideoNativeWindow:
278        {
279            ALOGV("kWhatSetVideoNativeWindow");
280
281            sp<RefBase> obj;
282            CHECK(msg->findObject("native-window", &obj));
283
284            mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
285
286            // XXX - ignore error from setVideoScalingMode for now
287            setVideoScalingMode(mVideoScalingMode);
288            break;
289        }
290
291        case kWhatSetAudioSink:
292        {
293            ALOGV("kWhatSetAudioSink");
294
295            sp<RefBase> obj;
296            CHECK(msg->findObject("sink", &obj));
297
298            mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
299            break;
300        }
301
302        case kWhatStart:
303        {
304            ALOGV("kWhatStart");
305
306            mVideoIsAVC = false;
307            mAudioEOS = false;
308            mVideoEOS = false;
309            mSkipRenderingAudioUntilMediaTimeUs = -1;
310            mSkipRenderingVideoUntilMediaTimeUs = -1;
311            mVideoLateByUs = 0;
312            mNumFramesTotal = 0;
313            mNumFramesDropped = 0;
314
315            mSource->start();
316
317            mRenderer = new Renderer(
318                    mAudioSink,
319                    new AMessage(kWhatRendererNotify, id()));
320
321            looper()->registerHandler(mRenderer);
322
323            postScanSources();
324            break;
325        }
326
327        case kWhatScanSources:
328        {
329            int32_t generation;
330            CHECK(msg->findInt32("generation", &generation));
331            if (generation != mScanSourcesGeneration) {
332                // Drop obsolete msg.
333                break;
334            }
335
336            mScanSourcesPending = false;
337
338            ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
339                 mAudioDecoder != NULL, mVideoDecoder != NULL);
340
341            bool mHadAnySourcesBefore =
342                (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
343
344            if (mNativeWindow != NULL) {
345                instantiateDecoder(false, &mVideoDecoder);
346            }
347
348            if (mAudioSink != NULL) {
349                instantiateDecoder(true, &mAudioDecoder);
350            }
351
352            if (!mHadAnySourcesBefore
353                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
354                // This is the first time we've found anything playable.
355
356                uint32_t flags = mSource->flags();
357
358                if (flags & Source::FLAG_DYNAMIC_DURATION) {
359                    schedulePollDuration();
360                }
361            }
362
363            status_t err;
364            if ((err = mSource->feedMoreTSData()) != OK) {
365                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
366                    // We're not currently decoding anything (no audio or
367                    // video tracks found) and we just ran out of input data.
368
369                    if (err == ERROR_END_OF_STREAM) {
370                        notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
371                    } else {
372                        notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
373                    }
374                }
375                break;
376            }
377
378            if ((mAudioDecoder == NULL && mAudioSink != NULL)
379                    || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
380                msg->post(100000ll);
381                mScanSourcesPending = true;
382            }
383            break;
384        }
385
386        case kWhatVideoNotify:
387        case kWhatAudioNotify:
388        {
389            bool audio = msg->what() == kWhatAudioNotify;
390
391            sp<AMessage> codecRequest;
392            CHECK(msg->findMessage("codec-request", &codecRequest));
393
394            int32_t what;
395            CHECK(codecRequest->findInt32("what", &what));
396
397            if (what == ACodec::kWhatFillThisBuffer) {
398                status_t err = feedDecoderInputData(
399                        audio, codecRequest);
400
401                if (err == -EWOULDBLOCK) {
402                    if (mSource->feedMoreTSData() == OK) {
403                        msg->post(10000ll);
404                    }
405                }
406            } else if (what == ACodec::kWhatEOS) {
407                int32_t err;
408                CHECK(codecRequest->findInt32("err", &err));
409
410                if (err == ERROR_END_OF_STREAM) {
411                    ALOGV("got %s decoder EOS", audio ? "audio" : "video");
412                } else {
413                    ALOGV("got %s decoder EOS w/ error %d",
414                         audio ? "audio" : "video",
415                         err);
416                }
417
418                mRenderer->queueEOS(audio, err);
419            } else if (what == ACodec::kWhatFlushCompleted) {
420                bool needShutdown;
421
422                if (audio) {
423                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
424                    mFlushingAudio = FLUSHED;
425                } else {
426                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
427                    mFlushingVideo = FLUSHED;
428
429                    mVideoLateByUs = 0;
430                }
431
432                ALOGV("decoder %s flush completed", audio ? "audio" : "video");
433
434                if (needShutdown) {
435                    ALOGV("initiating %s decoder shutdown",
436                         audio ? "audio" : "video");
437
438                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
439
440                    if (audio) {
441                        mFlushingAudio = SHUTTING_DOWN_DECODER;
442                    } else {
443                        mFlushingVideo = SHUTTING_DOWN_DECODER;
444                    }
445                }
446
447                finishFlushIfPossible();
448            } else if (what == ACodec::kWhatOutputFormatChanged) {
449                if (audio) {
450                    int32_t numChannels;
451                    CHECK(codecRequest->findInt32(
452                                "channel-count", &numChannels));
453
454                    int32_t sampleRate;
455                    CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
456
457                    ALOGV("Audio output format changed to %d Hz, %d channels",
458                         sampleRate, numChannels);
459
460                    mAudioSink->close();
461
462                    audio_output_flags_t flags;
463                    int64_t durationUs;
464                    // FIXME: we should handle the case where the video decoder
465                    // is created after we receive the format change indication.
466                    // Current code will just make that we select deep buffer
467                    // with video which should not be a problem as it should
468                    // not prevent from keeping A/V sync.
469                    if (mVideoDecoder == NULL &&
470                            mSource->getDuration(&durationUs) == OK &&
471                            durationUs
472                                > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
473                        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
474                    } else {
475                        flags = AUDIO_OUTPUT_FLAG_NONE;
476                    }
477
478                    int32_t channelMask;
479                    if (!codecRequest->findInt32("channel-mask", &channelMask)) {
480                        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
481                    }
482
483                    CHECK_EQ(mAudioSink->open(
484                                sampleRate,
485                                numChannels,
486                                (audio_channel_mask_t)channelMask,
487                                AUDIO_FORMAT_PCM_16_BIT,
488                                8 /* bufferCount */,
489                                NULL,
490                                NULL,
491                                flags),
492                             (status_t)OK);
493                    mAudioSink->start();
494
495                    mRenderer->signalAudioSinkChanged();
496                } else {
497                    // video
498
499                    int32_t width, height;
500                    CHECK(codecRequest->findInt32("width", &width));
501                    CHECK(codecRequest->findInt32("height", &height));
502
503                    int32_t cropLeft, cropTop, cropRight, cropBottom;
504                    CHECK(codecRequest->findRect(
505                                "crop",
506                                &cropLeft, &cropTop, &cropRight, &cropBottom));
507
508                    int32_t displayWidth = cropRight - cropLeft + 1;
509                    int32_t displayHeight = cropBottom - cropTop + 1;
510
511                    ALOGV("Video output format changed to %d x %d "
512                         "(crop: %d x %d @ (%d, %d))",
513                         width, height,
514                         displayWidth,
515                         displayHeight,
516                         cropLeft, cropTop);
517
518                    sp<AMessage> videoInputFormat =
519                        mSource->getFormat(false /* audio */);
520
521                    // Take into account sample aspect ratio if necessary:
522                    int32_t sarWidth, sarHeight;
523                    if (videoInputFormat->findInt32("sar-width", &sarWidth)
524                            && videoInputFormat->findInt32(
525                                "sar-height", &sarHeight)) {
526                        ALOGV("Sample aspect ratio %d : %d",
527                              sarWidth, sarHeight);
528
529                        displayWidth = (displayWidth * sarWidth) / sarHeight;
530
531                        ALOGV("display dimensions %d x %d",
532                              displayWidth, displayHeight);
533                    }
534
535                    notifyListener(
536                            MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
537                }
538            } else if (what == ACodec::kWhatShutdownCompleted) {
539                ALOGV("%s shutdown completed", audio ? "audio" : "video");
540                if (audio) {
541                    mAudioDecoder.clear();
542
543                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
544                    mFlushingAudio = SHUT_DOWN;
545                } else {
546                    mVideoDecoder.clear();
547
548                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
549                    mFlushingVideo = SHUT_DOWN;
550                }
551
552                finishFlushIfPossible();
553            } else if (what == ACodec::kWhatError) {
554                ALOGE("Received error from %s decoder, aborting playback.",
555                     audio ? "audio" : "video");
556
557                mRenderer->queueEOS(audio, UNKNOWN_ERROR);
558            } else if (what == ACodec::kWhatDrainThisBuffer) {
559                renderBuffer(audio, codecRequest);
560            } else if (what != ACodec::kWhatComponentAllocated
561                    && what != ACodec::kWhatComponentConfigured
562                    && what != ACodec::kWhatBuffersAllocated) {
563                ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
564                      what,
565                      what >> 24,
566                      (what >> 16) & 0xff,
567                      (what >> 8) & 0xff,
568                      what & 0xff);
569            }
570
571            break;
572        }
573
574        case kWhatRendererNotify:
575        {
576            int32_t what;
577            CHECK(msg->findInt32("what", &what));
578
579            if (what == Renderer::kWhatEOS) {
580                int32_t audio;
581                CHECK(msg->findInt32("audio", &audio));
582
583                int32_t finalResult;
584                CHECK(msg->findInt32("finalResult", &finalResult));
585
586                if (audio) {
587                    mAudioEOS = true;
588                } else {
589                    mVideoEOS = true;
590                }
591
592                if (finalResult == ERROR_END_OF_STREAM) {
593                    ALOGV("reached %s EOS", audio ? "audio" : "video");
594                } else {
595                    ALOGE("%s track encountered an error (%d)",
596                         audio ? "audio" : "video", finalResult);
597
598                    notifyListener(
599                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
600                }
601
602                if ((mAudioEOS || mAudioDecoder == NULL)
603                        && (mVideoEOS || mVideoDecoder == NULL)) {
604                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
605                }
606            } else if (what == Renderer::kWhatPosition) {
607                int64_t positionUs;
608                CHECK(msg->findInt64("positionUs", &positionUs));
609
610                CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
611
612                if (mDriver != NULL) {
613                    sp<NuPlayerDriver> driver = mDriver.promote();
614                    if (driver != NULL) {
615                        driver->notifyPosition(positionUs);
616
617                        driver->notifyFrameStats(
618                                mNumFramesTotal, mNumFramesDropped);
619                    }
620                }
621            } else if (what == Renderer::kWhatFlushComplete) {
622                int32_t audio;
623                CHECK(msg->findInt32("audio", &audio));
624
625                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
626            } else if (what == Renderer::kWhatVideoRenderingStart) {
627                notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
628            }
629            break;
630        }
631
632        case kWhatMoreDataQueued:
633        {
634            break;
635        }
636
637        case kWhatReset:
638        {
639            ALOGV("kWhatReset");
640
641            mDeferredActions.push_back(
642                    new SimpleAction(&NuPlayer::performDecoderShutdown));
643
644            mDeferredActions.push_back(
645                    new SimpleAction(&NuPlayer::performReset));
646
647            processDeferredActions();
648            break;
649        }
650
651        case kWhatSeek:
652        {
653            int64_t seekTimeUs;
654            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
655
656            ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
657
658            mDeferredActions.push_back(
659                    new SimpleAction(&NuPlayer::performDecoderFlush));
660
661            mDeferredActions.push_back(new SeekAction(seekTimeUs));
662
663            processDeferredActions();
664            break;
665        }
666
667        case kWhatPause:
668        {
669            CHECK(mRenderer != NULL);
670            mRenderer->pause();
671            break;
672        }
673
674        case kWhatResume:
675        {
676            CHECK(mRenderer != NULL);
677            mRenderer->resume();
678            break;
679        }
680
681        default:
682            TRESPASS();
683            break;
684    }
685}
686
687void NuPlayer::finishFlushIfPossible() {
688    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
689        return;
690    }
691
692    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
693        return;
694    }
695
696    ALOGV("both audio and video are flushed now.");
697
698    if (mTimeDiscontinuityPending) {
699        mRenderer->signalTimeDiscontinuity();
700        mTimeDiscontinuityPending = false;
701    }
702
703    if (mAudioDecoder != NULL) {
704        mAudioDecoder->signalResume();
705    }
706
707    if (mVideoDecoder != NULL) {
708        mVideoDecoder->signalResume();
709    }
710
711    mFlushingAudio = NONE;
712    mFlushingVideo = NONE;
713
714    processDeferredActions();
715}
716
717void NuPlayer::postScanSources() {
718    if (mScanSourcesPending) {
719        return;
720    }
721
722    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
723    msg->setInt32("generation", mScanSourcesGeneration);
724    msg->post();
725
726    mScanSourcesPending = true;
727}
728
729status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
730    if (*decoder != NULL) {
731        return OK;
732    }
733
734    sp<AMessage> format = mSource->getFormat(audio);
735
736    if (format == NULL) {
737        return -EWOULDBLOCK;
738    }
739
740    if (!audio) {
741        AString mime;
742        CHECK(format->findString("mime", &mime));
743        mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
744    }
745
746    sp<AMessage> notify =
747        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
748                     id());
749
750    *decoder = audio ? new Decoder(notify) :
751                       new Decoder(notify, mNativeWindow);
752    looper()->registerHandler(*decoder);
753
754    (*decoder)->configure(format);
755
756    int64_t durationUs;
757    if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
758        sp<NuPlayerDriver> driver = mDriver.promote();
759        if (driver != NULL) {
760            driver->notifyDuration(durationUs);
761        }
762    }
763
764    return OK;
765}
766
767status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
768    sp<AMessage> reply;
769    CHECK(msg->findMessage("reply", &reply));
770
771    if ((audio && IsFlushingState(mFlushingAudio))
772            || (!audio && IsFlushingState(mFlushingVideo))) {
773        reply->setInt32("err", INFO_DISCONTINUITY);
774        reply->post();
775        return OK;
776    }
777
778    sp<ABuffer> accessUnit;
779
780    bool dropAccessUnit;
781    do {
782        status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
783
784        if (err == -EWOULDBLOCK) {
785            return err;
786        } else if (err != OK) {
787            if (err == INFO_DISCONTINUITY) {
788                int32_t type;
789                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
790
791                bool formatChange =
792                    (audio &&
793                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
794                    || (!audio &&
795                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
796
797                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
798
799                ALOGI("%s discontinuity (formatChange=%d, time=%d)",
800                     audio ? "audio" : "video", formatChange, timeChange);
801
802                if (audio) {
803                    mSkipRenderingAudioUntilMediaTimeUs = -1;
804                } else {
805                    mSkipRenderingVideoUntilMediaTimeUs = -1;
806                }
807
808                if (timeChange) {
809                    sp<AMessage> extra;
810                    if (accessUnit->meta()->findMessage("extra", &extra)
811                            && extra != NULL) {
812                        int64_t resumeAtMediaTimeUs;
813                        if (extra->findInt64(
814                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
815                            ALOGI("suppressing rendering of %s until %lld us",
816                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
817
818                            if (audio) {
819                                mSkipRenderingAudioUntilMediaTimeUs =
820                                    resumeAtMediaTimeUs;
821                            } else {
822                                mSkipRenderingVideoUntilMediaTimeUs =
823                                    resumeAtMediaTimeUs;
824                            }
825                        }
826                    }
827                }
828
829                mTimeDiscontinuityPending =
830                    mTimeDiscontinuityPending || timeChange;
831
832                if (formatChange || timeChange) {
833                    if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
834                        // And we'll resume scanning sources once we're done
835                        // flushing.
836                        mDeferredActions.push_front(
837                                new SimpleAction(
838                                    &NuPlayer::performScanSources));
839                    }
840
841                    flushDecoder(audio, formatChange);
842                } else {
843                    // This stream is unaffected by the discontinuity
844
845                    if (audio) {
846                        mFlushingAudio = FLUSHED;
847                    } else {
848                        mFlushingVideo = FLUSHED;
849                    }
850
851                    finishFlushIfPossible();
852
853                    return -EWOULDBLOCK;
854                }
855            }
856
857            reply->setInt32("err", err);
858            reply->post();
859            return OK;
860        }
861
862        if (!audio) {
863            ++mNumFramesTotal;
864        }
865
866        dropAccessUnit = false;
867        if (!audio
868                && mVideoLateByUs > 100000ll
869                && mVideoIsAVC
870                && !IsAVCReferenceFrame(accessUnit)) {
871            dropAccessUnit = true;
872            ++mNumFramesDropped;
873        }
874    } while (dropAccessUnit);
875
876    // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
877
878#if 0
879    int64_t mediaTimeUs;
880    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
881    ALOGV("feeding %s input buffer at media time %.2f secs",
882         audio ? "audio" : "video",
883         mediaTimeUs / 1E6);
884#endif
885
886    reply->setBuffer("buffer", accessUnit);
887    reply->post();
888
889    return OK;
890}
891
892void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
893    // ALOGV("renderBuffer %s", audio ? "audio" : "video");
894
895    sp<AMessage> reply;
896    CHECK(msg->findMessage("reply", &reply));
897
898    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
899        // We're currently attempting to flush the decoder, in order
900        // to complete this, the decoder wants all its buffers back,
901        // so we don't want any output buffers it sent us (from before
902        // we initiated the flush) to be stuck in the renderer's queue.
903
904        ALOGV("we're still flushing the %s decoder, sending its output buffer"
905             " right back.", audio ? "audio" : "video");
906
907        reply->post();
908        return;
909    }
910
911    sp<ABuffer> buffer;
912    CHECK(msg->findBuffer("buffer", &buffer));
913
914    int64_t &skipUntilMediaTimeUs =
915        audio
916            ? mSkipRenderingAudioUntilMediaTimeUs
917            : mSkipRenderingVideoUntilMediaTimeUs;
918
919    if (skipUntilMediaTimeUs >= 0) {
920        int64_t mediaTimeUs;
921        CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
922
923        if (mediaTimeUs < skipUntilMediaTimeUs) {
924            ALOGV("dropping %s buffer at time %lld as requested.",
925                 audio ? "audio" : "video",
926                 mediaTimeUs);
927
928            reply->post();
929            return;
930        }
931
932        skipUntilMediaTimeUs = -1;
933    }
934
935    mRenderer->queueBuffer(audio, buffer, reply);
936}
937
938void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
939    if (mDriver == NULL) {
940        return;
941    }
942
943    sp<NuPlayerDriver> driver = mDriver.promote();
944
945    if (driver == NULL) {
946        return;
947    }
948
949    driver->notifyListener(msg, ext1, ext2);
950}
951
952void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
953    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
954        ALOGI("flushDecoder %s without decoder present",
955             audio ? "audio" : "video");
956    }
957
958    // Make sure we don't continue to scan sources until we finish flushing.
959    ++mScanSourcesGeneration;
960    mScanSourcesPending = false;
961
962    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
963    mRenderer->flush(audio);
964
965    FlushStatus newStatus =
966        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
967
968    if (audio) {
969        CHECK(mFlushingAudio == NONE
970                || mFlushingAudio == AWAITING_DISCONTINUITY);
971
972        mFlushingAudio = newStatus;
973
974        if (mFlushingVideo == NONE) {
975            mFlushingVideo = (mVideoDecoder != NULL)
976                ? AWAITING_DISCONTINUITY
977                : FLUSHED;
978        }
979    } else {
980        CHECK(mFlushingVideo == NONE
981                || mFlushingVideo == AWAITING_DISCONTINUITY);
982
983        mFlushingVideo = newStatus;
984
985        if (mFlushingAudio == NONE) {
986            mFlushingAudio = (mAudioDecoder != NULL)
987                ? AWAITING_DISCONTINUITY
988                : FLUSHED;
989        }
990    }
991}
992
993sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
994    sp<MetaData> meta = getFormatMeta(audio);
995
996    if (meta == NULL) {
997        return NULL;
998    }
999
1000    sp<AMessage> msg = new AMessage;
1001
1002    if(convertMetaDataToMessage(meta, &msg) == OK) {
1003        return msg;
1004    }
1005    return NULL;
1006}
1007
1008status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1009    mVideoScalingMode = mode;
1010    if (mNativeWindow != NULL
1011            && mNativeWindow->getNativeWindow() != NULL) {
1012        status_t ret = native_window_set_scaling_mode(
1013                mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1014        if (ret != OK) {
1015            ALOGE("Failed to set scaling mode (%d): %s",
1016                -ret, strerror(-ret));
1017            return ret;
1018        }
1019    }
1020    return OK;
1021}
1022
1023void NuPlayer::schedulePollDuration() {
1024    sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1025    msg->setInt32("generation", mPollDurationGeneration);
1026    msg->post();
1027}
1028
1029void NuPlayer::cancelPollDuration() {
1030    ++mPollDurationGeneration;
1031}
1032
1033void NuPlayer::processDeferredActions() {
1034    while (!mDeferredActions.empty()) {
1035        // We won't execute any deferred actions until we're no longer in
1036        // an intermediate state, i.e. one more more decoders are currently
1037        // flushing or shutting down.
1038
1039        if (mRenderer != NULL) {
1040            // There's an edge case where the renderer owns all output
1041            // buffers and is paused, therefore the decoder will not read
1042            // more input data and will never encounter the matching
1043            // discontinuity. To avoid this, we resume the renderer.
1044
1045            if (mFlushingAudio == AWAITING_DISCONTINUITY
1046                    || mFlushingVideo == AWAITING_DISCONTINUITY) {
1047                mRenderer->resume();
1048            }
1049        }
1050
1051        if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1052            // We're currently flushing, postpone the reset until that's
1053            // completed.
1054
1055            ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1056                  mFlushingAudio, mFlushingVideo);
1057
1058            break;
1059        }
1060
1061        sp<Action> action = *mDeferredActions.begin();
1062        mDeferredActions.erase(mDeferredActions.begin());
1063
1064        action->execute(this);
1065    }
1066}
1067
1068void NuPlayer::performSeek(int64_t seekTimeUs) {
1069    ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1070          seekTimeUs,
1071          seekTimeUs / 1E6);
1072
1073    mSource->seekTo(seekTimeUs);
1074
1075    if (mDriver != NULL) {
1076        sp<NuPlayerDriver> driver = mDriver.promote();
1077        if (driver != NULL) {
1078            driver->notifyPosition(seekTimeUs);
1079            driver->notifySeekComplete();
1080        }
1081    }
1082
1083    // everything's flushed, continue playback.
1084}
1085
1086void NuPlayer::performDecoderFlush() {
1087    ALOGV("performDecoderFlush");
1088
1089    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1090        return;
1091    }
1092
1093    mTimeDiscontinuityPending = true;
1094
1095    if (mAudioDecoder != NULL) {
1096        flushDecoder(true /* audio */, false /* needShutdown */);
1097    }
1098
1099    if (mVideoDecoder != NULL) {
1100        flushDecoder(false /* audio */, false /* needShutdown */);
1101    }
1102}
1103
1104void NuPlayer::performDecoderShutdown() {
1105    ALOGV("performDecoderShutdown");
1106
1107    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1108        return;
1109    }
1110
1111    mTimeDiscontinuityPending = true;
1112
1113    if (mAudioDecoder != NULL) {
1114        flushDecoder(true /* audio */, true /* needShutdown */);
1115    }
1116
1117    if (mVideoDecoder != NULL) {
1118        flushDecoder(false /* audio */, true /* needShutdown */);
1119    }
1120}
1121
1122void NuPlayer::performReset() {
1123    ALOGV("performReset");
1124
1125    CHECK(mAudioDecoder == NULL);
1126    CHECK(mVideoDecoder == NULL);
1127
1128    cancelPollDuration();
1129
1130    ++mScanSourcesGeneration;
1131    mScanSourcesPending = false;
1132
1133    mRenderer.clear();
1134
1135    if (mSource != NULL) {
1136        mSource->stop();
1137        mSource.clear();
1138    }
1139
1140    if (mDriver != NULL) {
1141        sp<NuPlayerDriver> driver = mDriver.promote();
1142        if (driver != NULL) {
1143            driver->notifyResetComplete();
1144        }
1145    }
1146}
1147
1148void NuPlayer::performScanSources() {
1149    ALOGV("performScanSources");
1150
1151    if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1152        postScanSources();
1153    }
1154}
1155
1156}  // namespace android
1157