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