NuPlayer.cpp revision 484566c410afdfbc4b6bc5aa1732aef37428a5b8
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/IGraphicBufferProducer.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<IGraphicBufferProducer> &bufferProducer) {
202    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
203
204    if (bufferProducer == NULL) {
205        msg->setObject("native-window", NULL);
206    } else {
207        msg->setObject(
208                "native-window",
209                new NativeWindowWrapper(
210                    new SurfaceTextureClient(bufferProducer)));
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(
488                                "channel-count", &numChannels));
489
490                    int32_t sampleRate;
491                    CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
492
493                    ALOGV("Audio output format changed to %d Hz, %d channels",
494                         sampleRate, numChannels);
495
496                    mAudioSink->close();
497
498                    audio_output_flags_t flags;
499                    int64_t durationUs;
500                    // FIXME: we should handle the case where the video decoder
501                    // is created after we receive the format change indication.
502                    // Current code will just make that we select deep buffer
503                    // with video which should not be a problem as it should
504                    // not prevent from keeping A/V sync.
505                    if (mVideoDecoder == NULL &&
506                            mSource->getDuration(&durationUs) == OK &&
507                            durationUs
508                                > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
509                        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
510                    } else {
511                        flags = AUDIO_OUTPUT_FLAG_NONE;
512                    }
513
514                    int32_t channelMask;
515                    if (!codecRequest->findInt32("channel-mask", &channelMask)) {
516                        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
517                    }
518
519                    CHECK_EQ(mAudioSink->open(
520                                sampleRate,
521                                numChannels,
522                                (audio_channel_mask_t)channelMask,
523                                AUDIO_FORMAT_PCM_16_BIT,
524                                8 /* bufferCount */,
525                                NULL,
526                                NULL,
527                                flags),
528                             (status_t)OK);
529                    mAudioSink->start();
530
531                    mRenderer->signalAudioSinkChanged();
532                } else {
533                    // video
534
535                    int32_t width, height;
536                    CHECK(codecRequest->findInt32("width", &width));
537                    CHECK(codecRequest->findInt32("height", &height));
538
539                    int32_t cropLeft, cropTop, cropRight, cropBottom;
540                    CHECK(codecRequest->findRect(
541                                "crop",
542                                &cropLeft, &cropTop, &cropRight, &cropBottom));
543
544                    int32_t displayWidth = cropRight - cropLeft + 1;
545                    int32_t displayHeight = cropBottom - cropTop + 1;
546
547                    ALOGV("Video output format changed to %d x %d "
548                         "(crop: %d x %d @ (%d, %d))",
549                         width, height,
550                         displayWidth,
551                         displayHeight,
552                         cropLeft, cropTop);
553
554                    sp<AMessage> videoInputFormat =
555                        mSource->getFormat(false /* audio */);
556
557                    // Take into account sample aspect ratio if necessary:
558                    int32_t sarWidth, sarHeight;
559                    if (videoInputFormat->findInt32("sar-width", &sarWidth)
560                            && videoInputFormat->findInt32(
561                                "sar-height", &sarHeight)) {
562                        ALOGV("Sample aspect ratio %d : %d",
563                              sarWidth, sarHeight);
564
565                        displayWidth = (displayWidth * sarWidth) / sarHeight;
566
567                        ALOGV("display dimensions %d x %d",
568                              displayWidth, displayHeight);
569                    }
570
571                    notifyListener(
572                            MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
573                }
574            } else if (what == ACodec::kWhatShutdownCompleted) {
575                ALOGV("%s shutdown completed", audio ? "audio" : "video");
576                if (audio) {
577                    mAudioDecoder.clear();
578
579                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
580                    mFlushingAudio = SHUT_DOWN;
581                } else {
582                    mVideoDecoder.clear();
583
584                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
585                    mFlushingVideo = SHUT_DOWN;
586                }
587
588                finishFlushIfPossible();
589            } else if (what == ACodec::kWhatError) {
590                ALOGE("Received error from %s decoder, aborting playback.",
591                     audio ? "audio" : "video");
592
593                mRenderer->queueEOS(audio, UNKNOWN_ERROR);
594            } else if (what == ACodec::kWhatDrainThisBuffer) {
595                renderBuffer(audio, codecRequest);
596            } else if (what != ACodec::kWhatComponentAllocated
597                    && what != ACodec::kWhatComponentConfigured
598                    && what != ACodec::kWhatBuffersAllocated) {
599                ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
600                      what,
601                      what >> 24,
602                      (what >> 16) & 0xff,
603                      (what >> 8) & 0xff,
604                      what & 0xff);
605            }
606
607            break;
608        }
609
610        case kWhatRendererNotify:
611        {
612            int32_t what;
613            CHECK(msg->findInt32("what", &what));
614
615            if (what == Renderer::kWhatEOS) {
616                int32_t audio;
617                CHECK(msg->findInt32("audio", &audio));
618
619                int32_t finalResult;
620                CHECK(msg->findInt32("finalResult", &finalResult));
621
622                if (audio) {
623                    mAudioEOS = true;
624                } else {
625                    mVideoEOS = true;
626                }
627
628                if (finalResult == ERROR_END_OF_STREAM) {
629                    ALOGV("reached %s EOS", audio ? "audio" : "video");
630                } else {
631                    ALOGE("%s track encountered an error (%d)",
632                         audio ? "audio" : "video", finalResult);
633
634                    notifyListener(
635                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
636                }
637
638                if ((mAudioEOS || mAudioDecoder == NULL)
639                        && (mVideoEOS || mVideoDecoder == NULL)) {
640                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
641                }
642            } else if (what == Renderer::kWhatPosition) {
643                int64_t positionUs;
644                CHECK(msg->findInt64("positionUs", &positionUs));
645
646                CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
647
648                if (mDriver != NULL) {
649                    sp<NuPlayerDriver> driver = mDriver.promote();
650                    if (driver != NULL) {
651                        driver->notifyPosition(positionUs);
652
653                        driver->notifyFrameStats(
654                                mNumFramesTotal, mNumFramesDropped);
655                    }
656                }
657            } else if (what == Renderer::kWhatFlushComplete) {
658                int32_t audio;
659                CHECK(msg->findInt32("audio", &audio));
660
661                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
662            } else if (what == Renderer::kWhatVideoRenderingStart) {
663                notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
664            }
665            break;
666        }
667
668        case kWhatMoreDataQueued:
669        {
670            break;
671        }
672
673        case kWhatReset:
674        {
675            ALOGV("kWhatReset");
676
677            mDeferredActions.push_back(
678                    new SimpleAction(&NuPlayer::performDecoderShutdown));
679
680            mDeferredActions.push_back(
681                    new SimpleAction(&NuPlayer::performReset));
682
683            processDeferredActions();
684            break;
685        }
686
687        case kWhatSeek:
688        {
689            int64_t seekTimeUs;
690            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
691
692            ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
693
694            mDeferredActions.push_back(
695                    new SimpleAction(&NuPlayer::performDecoderFlush));
696
697            mDeferredActions.push_back(new SeekAction(seekTimeUs));
698
699            processDeferredActions();
700            break;
701        }
702
703        case kWhatPause:
704        {
705            CHECK(mRenderer != NULL);
706            mRenderer->pause();
707            break;
708        }
709
710        case kWhatResume:
711        {
712            CHECK(mRenderer != NULL);
713            mRenderer->resume();
714            break;
715        }
716
717        default:
718            TRESPASS();
719            break;
720    }
721}
722
723void NuPlayer::finishFlushIfPossible() {
724    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
725        return;
726    }
727
728    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
729        return;
730    }
731
732    ALOGV("both audio and video are flushed now.");
733
734    if (mTimeDiscontinuityPending) {
735        mRenderer->signalTimeDiscontinuity();
736        mTimeDiscontinuityPending = false;
737    }
738
739    if (mAudioDecoder != NULL) {
740        mAudioDecoder->signalResume();
741    }
742
743    if (mVideoDecoder != NULL) {
744        mVideoDecoder->signalResume();
745    }
746
747    mFlushingAudio = NONE;
748    mFlushingVideo = NONE;
749
750    processDeferredActions();
751}
752
753void NuPlayer::postScanSources() {
754    if (mScanSourcesPending) {
755        return;
756    }
757
758    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
759    msg->setInt32("generation", mScanSourcesGeneration);
760    msg->post();
761
762    mScanSourcesPending = true;
763}
764
765status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
766    if (*decoder != NULL) {
767        return OK;
768    }
769
770    sp<AMessage> format = mSource->getFormat(audio);
771
772    if (format == NULL) {
773        return -EWOULDBLOCK;
774    }
775
776    if (!audio) {
777        AString mime;
778        CHECK(format->findString("mime", &mime));
779        mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
780    }
781
782    sp<AMessage> notify =
783        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
784                     id());
785
786    *decoder = audio ? new Decoder(notify) :
787                       new Decoder(notify, mNativeWindow);
788    looper()->registerHandler(*decoder);
789
790    (*decoder)->configure(format);
791
792    int64_t durationUs;
793    if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
794        sp<NuPlayerDriver> driver = mDriver.promote();
795        if (driver != NULL) {
796            driver->notifyDuration(durationUs);
797        }
798    }
799
800    return OK;
801}
802
803status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
804    sp<AMessage> reply;
805    CHECK(msg->findMessage("reply", &reply));
806
807    if ((audio && IsFlushingState(mFlushingAudio))
808            || (!audio && IsFlushingState(mFlushingVideo))) {
809        reply->setInt32("err", INFO_DISCONTINUITY);
810        reply->post();
811        return OK;
812    }
813
814    sp<ABuffer> accessUnit;
815
816    bool dropAccessUnit;
817    do {
818        status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
819
820        if (err == -EWOULDBLOCK) {
821            return err;
822        } else if (err != OK) {
823            if (err == INFO_DISCONTINUITY) {
824                int32_t type;
825                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
826
827                bool formatChange =
828                    (audio &&
829                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
830                    || (!audio &&
831                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
832
833                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
834
835                ALOGI("%s discontinuity (formatChange=%d, time=%d)",
836                     audio ? "audio" : "video", formatChange, timeChange);
837
838                if (audio) {
839                    mSkipRenderingAudioUntilMediaTimeUs = -1;
840                } else {
841                    mSkipRenderingVideoUntilMediaTimeUs = -1;
842                }
843
844                if (timeChange) {
845                    sp<AMessage> extra;
846                    if (accessUnit->meta()->findMessage("extra", &extra)
847                            && extra != NULL) {
848                        int64_t resumeAtMediaTimeUs;
849                        if (extra->findInt64(
850                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
851                            ALOGI("suppressing rendering of %s until %lld us",
852                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
853
854                            if (audio) {
855                                mSkipRenderingAudioUntilMediaTimeUs =
856                                    resumeAtMediaTimeUs;
857                            } else {
858                                mSkipRenderingVideoUntilMediaTimeUs =
859                                    resumeAtMediaTimeUs;
860                            }
861                        }
862                    }
863                }
864
865                mTimeDiscontinuityPending =
866                    mTimeDiscontinuityPending || timeChange;
867
868                if (formatChange || timeChange) {
869                    if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
870                        // And we'll resume scanning sources once we're done
871                        // flushing.
872                        mDeferredActions.push_front(
873                                new SimpleAction(
874                                    &NuPlayer::performScanSources));
875                    }
876
877                    flushDecoder(audio, formatChange);
878                } else {
879                    // This stream is unaffected by the discontinuity
880
881                    if (audio) {
882                        mFlushingAudio = FLUSHED;
883                    } else {
884                        mFlushingVideo = FLUSHED;
885                    }
886
887                    finishFlushIfPossible();
888
889                    return -EWOULDBLOCK;
890                }
891            }
892
893            reply->setInt32("err", err);
894            reply->post();
895            return OK;
896        }
897
898        if (!audio) {
899            ++mNumFramesTotal;
900        }
901
902        dropAccessUnit = false;
903        if (!audio
904                && mVideoLateByUs > 100000ll
905                && mVideoIsAVC
906                && !IsAVCReferenceFrame(accessUnit)) {
907            dropAccessUnit = true;
908            ++mNumFramesDropped;
909        }
910    } while (dropAccessUnit);
911
912    // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
913
914#if 0
915    int64_t mediaTimeUs;
916    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
917    ALOGV("feeding %s input buffer at media time %.2f secs",
918         audio ? "audio" : "video",
919         mediaTimeUs / 1E6);
920#endif
921
922    reply->setBuffer("buffer", accessUnit);
923    reply->post();
924
925    return OK;
926}
927
928void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
929    // ALOGV("renderBuffer %s", audio ? "audio" : "video");
930
931    sp<AMessage> reply;
932    CHECK(msg->findMessage("reply", &reply));
933
934    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
935        // We're currently attempting to flush the decoder, in order
936        // to complete this, the decoder wants all its buffers back,
937        // so we don't want any output buffers it sent us (from before
938        // we initiated the flush) to be stuck in the renderer's queue.
939
940        ALOGV("we're still flushing the %s decoder, sending its output buffer"
941             " right back.", audio ? "audio" : "video");
942
943        reply->post();
944        return;
945    }
946
947    sp<ABuffer> buffer;
948    CHECK(msg->findBuffer("buffer", &buffer));
949
950    int64_t &skipUntilMediaTimeUs =
951        audio
952            ? mSkipRenderingAudioUntilMediaTimeUs
953            : mSkipRenderingVideoUntilMediaTimeUs;
954
955    if (skipUntilMediaTimeUs >= 0) {
956        int64_t mediaTimeUs;
957        CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
958
959        if (mediaTimeUs < skipUntilMediaTimeUs) {
960            ALOGV("dropping %s buffer at time %lld as requested.",
961                 audio ? "audio" : "video",
962                 mediaTimeUs);
963
964            reply->post();
965            return;
966        }
967
968        skipUntilMediaTimeUs = -1;
969    }
970
971    mRenderer->queueBuffer(audio, buffer, reply);
972}
973
974void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
975    if (mDriver == NULL) {
976        return;
977    }
978
979    sp<NuPlayerDriver> driver = mDriver.promote();
980
981    if (driver == NULL) {
982        return;
983    }
984
985    driver->notifyListener(msg, ext1, ext2);
986}
987
988void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
989    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
990        ALOGI("flushDecoder %s without decoder present",
991             audio ? "audio" : "video");
992    }
993
994    // Make sure we don't continue to scan sources until we finish flushing.
995    ++mScanSourcesGeneration;
996    mScanSourcesPending = false;
997
998    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
999    mRenderer->flush(audio);
1000
1001    FlushStatus newStatus =
1002        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1003
1004    if (audio) {
1005        CHECK(mFlushingAudio == NONE
1006                || mFlushingAudio == AWAITING_DISCONTINUITY);
1007
1008        mFlushingAudio = newStatus;
1009
1010        if (mFlushingVideo == NONE) {
1011            mFlushingVideo = (mVideoDecoder != NULL)
1012                ? AWAITING_DISCONTINUITY
1013                : FLUSHED;
1014        }
1015    } else {
1016        CHECK(mFlushingVideo == NONE
1017                || mFlushingVideo == AWAITING_DISCONTINUITY);
1018
1019        mFlushingVideo = newStatus;
1020
1021        if (mFlushingAudio == NONE) {
1022            mFlushingAudio = (mAudioDecoder != NULL)
1023                ? AWAITING_DISCONTINUITY
1024                : FLUSHED;
1025        }
1026    }
1027}
1028
1029sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1030    sp<MetaData> meta = getFormatMeta(audio);
1031
1032    if (meta == NULL) {
1033        return NULL;
1034    }
1035
1036    sp<AMessage> msg = new AMessage;
1037
1038    if(convertMetaDataToMessage(meta, &msg) == OK) {
1039        return msg;
1040    }
1041    return NULL;
1042}
1043
1044status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1045    mVideoScalingMode = mode;
1046    if (mNativeWindow != NULL) {
1047        status_t ret = native_window_set_scaling_mode(
1048                mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1049        if (ret != OK) {
1050            ALOGE("Failed to set scaling mode (%d): %s",
1051                -ret, strerror(-ret));
1052            return ret;
1053        }
1054    }
1055    return OK;
1056}
1057
1058void NuPlayer::schedulePollDuration() {
1059    sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1060    msg->setInt32("generation", mPollDurationGeneration);
1061    msg->post();
1062}
1063
1064void NuPlayer::cancelPollDuration() {
1065    ++mPollDurationGeneration;
1066}
1067
1068void NuPlayer::processDeferredActions() {
1069    while (!mDeferredActions.empty()) {
1070        // We won't execute any deferred actions until we're no longer in
1071        // an intermediate state, i.e. one more more decoders are currently
1072        // flushing or shutting down.
1073
1074        if (mRenderer != NULL) {
1075            // There's an edge case where the renderer owns all output
1076            // buffers and is paused, therefore the decoder will not read
1077            // more input data and will never encounter the matching
1078            // discontinuity. To avoid this, we resume the renderer.
1079
1080            if (mFlushingAudio == AWAITING_DISCONTINUITY
1081                    || mFlushingVideo == AWAITING_DISCONTINUITY) {
1082                mRenderer->resume();
1083            }
1084        }
1085
1086        if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1087            // We're currently flushing, postpone the reset until that's
1088            // completed.
1089
1090            ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1091                  mFlushingAudio, mFlushingVideo);
1092
1093            break;
1094        }
1095
1096        sp<Action> action = *mDeferredActions.begin();
1097        mDeferredActions.erase(mDeferredActions.begin());
1098
1099        action->execute(this);
1100    }
1101}
1102
1103void NuPlayer::performSeek(int64_t seekTimeUs) {
1104    ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1105          seekTimeUs,
1106          seekTimeUs / 1E6);
1107
1108    mSource->seekTo(seekTimeUs);
1109
1110    if (mDriver != NULL) {
1111        sp<NuPlayerDriver> driver = mDriver.promote();
1112        if (driver != NULL) {
1113            driver->notifyPosition(seekTimeUs);
1114            driver->notifySeekComplete();
1115        }
1116    }
1117
1118    // everything's flushed, continue playback.
1119}
1120
1121void NuPlayer::performDecoderFlush() {
1122    ALOGV("performDecoderFlush");
1123
1124    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1125        return;
1126    }
1127
1128    mTimeDiscontinuityPending = true;
1129
1130    if (mAudioDecoder != NULL) {
1131        flushDecoder(true /* audio */, false /* needShutdown */);
1132    }
1133
1134    if (mVideoDecoder != NULL) {
1135        flushDecoder(false /* audio */, false /* needShutdown */);
1136    }
1137}
1138
1139void NuPlayer::performDecoderShutdown() {
1140    ALOGV("performDecoderShutdown");
1141
1142    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1143        return;
1144    }
1145
1146    mTimeDiscontinuityPending = true;
1147
1148    if (mAudioDecoder != NULL) {
1149        flushDecoder(true /* audio */, true /* needShutdown */);
1150    }
1151
1152    if (mVideoDecoder != NULL) {
1153        flushDecoder(false /* audio */, true /* needShutdown */);
1154    }
1155}
1156
1157void NuPlayer::performReset() {
1158    ALOGV("performReset");
1159
1160    CHECK(mAudioDecoder == NULL);
1161    CHECK(mVideoDecoder == NULL);
1162
1163    cancelPollDuration();
1164
1165    ++mScanSourcesGeneration;
1166    mScanSourcesPending = false;
1167
1168    mRenderer.clear();
1169
1170    if (mSource != NULL) {
1171        mSource->stop();
1172        mSource.clear();
1173    }
1174
1175    if (mDriver != NULL) {
1176        sp<NuPlayerDriver> driver = mDriver.promote();
1177        if (driver != NULL) {
1178            driver->notifyResetComplete();
1179        }
1180    }
1181
1182    mStarted = false;
1183}
1184
1185void NuPlayer::performScanSources() {
1186    ALOGV("performScanSources");
1187
1188    if (!mStarted) {
1189        return;
1190    }
1191
1192    if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1193        postScanSources();
1194    }
1195}
1196
1197void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1198    ALOGV("performSetSurface");
1199
1200    mNativeWindow = wrapper;
1201
1202    // XXX - ignore error from setVideoScalingMode for now
1203    setVideoScalingMode(mVideoScalingMode);
1204
1205    if (mDriver != NULL) {
1206        sp<NuPlayerDriver> driver = mDriver.promote();
1207        if (driver != NULL) {
1208            driver->notifySetSurfaceComplete();
1209        }
1210    }
1211}
1212
1213}  // namespace android
1214