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