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