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