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