Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright 2015 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 "MediaSync"
     19 #include <inttypes.h>
     20 
     21 #include <gui/BufferQueue.h>
     22 #include <gui/IGraphicBufferConsumer.h>
     23 #include <gui/IGraphicBufferProducer.h>
     24 
     25 #include <media/AudioTrack.h>
     26 #include <media/stagefright/MediaClock.h>
     27 #include <media/stagefright/MediaSync.h>
     28 #include <media/stagefright/VideoFrameScheduler.h>
     29 #include <media/stagefright/foundation/ADebug.h>
     30 #include <media/stagefright/foundation/ALooper.h>
     31 #include <media/stagefright/foundation/AMessage.h>
     32 
     33 #include <ui/GraphicBuffer.h>
     34 
     35 #include <system/window.h>
     36 
     37 // Maximum late time allowed for a video frame to be rendered. When a video
     38 // frame arrives later than this number, it will be discarded without rendering.
     39 static const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
     40 
     41 namespace android {
     42 
     43 // static
     44 sp<MediaSync> MediaSync::create() {
     45     sp<MediaSync> sync = new MediaSync();
     46     sync->mLooper->registerHandler(sync);
     47     return sync;
     48 }
     49 
     50 MediaSync::MediaSync()
     51       : mIsAbandoned(false),
     52         mMutex(),
     53         mReleaseCondition(),
     54         mNumOutstandingBuffers(0),
     55         mUsageFlagsFromOutput(0),
     56         mMaxAcquiredBufferCount(1),
     57         mReturnPendingInputFrame(false),
     58         mNativeSampleRateInHz(0),
     59         mNumFramesWritten(0),
     60         mHasAudio(false),
     61         mNextBufferItemMediaUs(-1),
     62         mPlaybackRate(0.0) {
     63     mMediaClock = new MediaClock;
     64     mMediaClock->init();
     65 
     66     // initialize settings
     67     mPlaybackSettings = AUDIO_PLAYBACK_RATE_DEFAULT;
     68     mPlaybackSettings.mSpeed = mPlaybackRate;
     69 
     70     mLooper = new ALooper;
     71     mLooper->setName("MediaSync");
     72     mLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
     73 }
     74 
     75 MediaSync::~MediaSync() {
     76     if (mInput != NULL) {
     77         mInput->consumerDisconnect();
     78     }
     79     if (mOutput != NULL) {
     80         mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
     81     }
     82 
     83     if (mLooper != NULL) {
     84         mLooper->unregisterHandler(id());
     85         mLooper->stop();
     86     }
     87 }
     88 
     89 status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
     90     Mutex::Autolock lock(mMutex);
     91 
     92     if (output == mOutput) {
     93         return NO_ERROR;  // same output surface.
     94     }
     95 
     96     if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
     97         ALOGE("setSurface: output surface is used as sync source and cannot be removed.");
     98         return INVALID_OPERATION;
     99     }
    100 
    101     if (output != NULL) {
    102         int newUsage = 0;
    103         output->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &newUsage);
    104 
    105         // Check usage flags only when current output surface has been used to create input surface.
    106         if (mOutput != NULL && mInput != NULL) {
    107             int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER
    108                     | GRALLOC_USAGE_EXTERNAL_DISP);
    109             // New output surface is not allowed to add new usage flag except ignored ones.
    110             if ((newUsage & ~(mUsageFlagsFromOutput | ignoredFlags)) != 0) {
    111                 ALOGE("setSurface: new output surface has new usage flag not used by current one.");
    112                 return BAD_VALUE;
    113             }
    114         }
    115 
    116         // Try to connect to new output surface. If failed, current output surface will not
    117         // be changed.
    118         IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
    119         sp<OutputListener> listener(new OutputListener(this, output));
    120         IInterface::asBinder(output)->linkToDeath(listener);
    121         status_t status =
    122             output->connect(listener,
    123                             NATIVE_WINDOW_API_MEDIA,
    124                             true /* producerControlledByApp */,
    125                             &queueBufferOutput);
    126         if (status != NO_ERROR) {
    127             ALOGE("setSurface: failed to connect (%d)", status);
    128             return status;
    129         }
    130 
    131         if (mFrameScheduler == NULL) {
    132             mFrameScheduler = new VideoFrameScheduler();
    133             mFrameScheduler->init();
    134         }
    135     }
    136 
    137     if (mOutput != NULL) {
    138         mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
    139         while (!mBuffersSentToOutput.isEmpty()) {
    140             returnBufferToInput_l(mBuffersSentToOutput.valueAt(0), Fence::NO_FENCE);
    141             mBuffersSentToOutput.removeItemsAt(0);
    142         }
    143     }
    144 
    145     mOutput = output;
    146 
    147     return NO_ERROR;
    148 }
    149 
    150 // |audioTrack| is used only for querying information.
    151 status_t MediaSync::setAudioTrack(const sp<AudioTrack> &audioTrack) {
    152     Mutex::Autolock lock(mMutex);
    153 
    154     // TODO: support audio track change.
    155     if (mAudioTrack != NULL) {
    156         ALOGE("setAudioTrack: audioTrack has already been configured.");
    157         return INVALID_OPERATION;
    158     }
    159 
    160     if (audioTrack == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_AUDIO) {
    161         ALOGE("setAudioTrack: audioTrack is used as sync source and cannot be removed.");
    162         return INVALID_OPERATION;
    163     }
    164 
    165     if (audioTrack != NULL) {
    166         // check if audio track supports the playback settings
    167         if (mPlaybackSettings.mSpeed != 0.f
    168                 && audioTrack->setPlaybackRate(mPlaybackSettings) != OK) {
    169             ALOGE("playback settings are not supported by the audio track");
    170             return INVALID_OPERATION;
    171         }
    172         uint32_t nativeSampleRateInHz = audioTrack->getOriginalSampleRate();
    173         if (nativeSampleRateInHz <= 0) {
    174             ALOGE("setAudioTrack: native sample rate should be positive.");
    175             return BAD_VALUE;
    176         }
    177         mAudioTrack = audioTrack;
    178         mNativeSampleRateInHz = nativeSampleRateInHz;
    179         (void)setPlaybackSettings_l(mPlaybackSettings);
    180     }
    181     else {
    182         mAudioTrack = NULL;
    183         mNativeSampleRateInHz = 0;
    184     }
    185 
    186     // potentially resync to new source
    187     resync_l();
    188     return OK;
    189 }
    190 
    191 status_t MediaSync::createInputSurface(
    192         sp<IGraphicBufferProducer> *outBufferProducer) {
    193     if (outBufferProducer == NULL) {
    194         return BAD_VALUE;
    195     }
    196 
    197     Mutex::Autolock lock(mMutex);
    198 
    199     if (mOutput == NULL) {
    200         return NO_INIT;
    201     }
    202 
    203     if (mInput != NULL) {
    204         return INVALID_OPERATION;
    205     }
    206 
    207     sp<IGraphicBufferProducer> bufferProducer;
    208     sp<IGraphicBufferConsumer> bufferConsumer;
    209     BufferQueue::createBufferQueue(&bufferProducer, &bufferConsumer);
    210 
    211     sp<InputListener> listener(new InputListener(this));
    212     IInterface::asBinder(bufferConsumer)->linkToDeath(listener);
    213     status_t status =
    214         bufferConsumer->consumerConnect(listener, false /* controlledByApp */);
    215     if (status == NO_ERROR) {
    216         bufferConsumer->setConsumerName(String8("MediaSync"));
    217         // propagate usage bits from output surface
    218         mUsageFlagsFromOutput = 0;
    219         mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mUsageFlagsFromOutput);
    220         bufferConsumer->setConsumerUsageBits(mUsageFlagsFromOutput);
    221         *outBufferProducer = bufferProducer;
    222         mInput = bufferConsumer;
    223 
    224         // set undequeued buffer count
    225         int minUndequeuedBuffers;
    226         mOutput->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
    227         mMaxAcquiredBufferCount = minUndequeuedBuffers;
    228         bufferConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount);
    229     }
    230     return status;
    231 }
    232 
    233 void MediaSync::resync_l() {
    234     AVSyncSource src = mSyncSettings.mSource;
    235     if (src == AVSYNC_SOURCE_DEFAULT) {
    236         if (mAudioTrack != NULL) {
    237             src = AVSYNC_SOURCE_AUDIO;
    238         } else {
    239             src = AVSYNC_SOURCE_SYSTEM_CLOCK;
    240         }
    241     }
    242 
    243     // TODO: resync ourselves to the current clock (e.g. on sync source change)
    244     updatePlaybackRate_l(mPlaybackRate);
    245 }
    246 
    247 void MediaSync::updatePlaybackRate_l(float rate) {
    248     if (rate > mPlaybackRate) {
    249         mNextBufferItemMediaUs = -1;
    250     }
    251     mPlaybackRate = rate;
    252     // TODO: update frame scheduler with this info
    253     mMediaClock->setPlaybackRate(rate);
    254     onDrainVideo_l();
    255 }
    256 
    257 sp<const MediaClock> MediaSync::getMediaClock() {
    258     return mMediaClock;
    259 }
    260 
    261 status_t MediaSync::getPlayTimeForPendingAudioFrames(int64_t *outTimeUs) {
    262     Mutex::Autolock lock(mMutex);
    263     // User should check the playback rate if it doesn't want to receive a
    264     // huge number for play time.
    265     if (mPlaybackRate == 0.0f) {
    266         *outTimeUs = INT64_MAX;
    267         return OK;
    268     }
    269 
    270     uint32_t numFramesPlayed = 0;
    271     if (mAudioTrack != NULL) {
    272         status_t res = mAudioTrack->getPosition(&numFramesPlayed);
    273         if (res != OK) {
    274             return res;
    275         }
    276     }
    277 
    278     int64_t numPendingFrames = mNumFramesWritten - numFramesPlayed;
    279     if (numPendingFrames < 0) {
    280         numPendingFrames = 0;
    281         ALOGW("getPlayTimeForPendingAudioFrames: pending frame count is negative.");
    282     }
    283     double timeUs = numPendingFrames * 1000000.0
    284             / (mNativeSampleRateInHz * (double)mPlaybackRate);
    285     if (timeUs > (double)INT64_MAX) {
    286         // Overflow.
    287         *outTimeUs = INT64_MAX;
    288         ALOGW("getPlayTimeForPendingAudioFrames: play time for pending audio frames "
    289               "is too high, possibly due to super low playback rate(%f)", mPlaybackRate);
    290     } else {
    291         *outTimeUs = (int64_t)timeUs;
    292     }
    293 
    294     return OK;
    295 }
    296 
    297 status_t MediaSync::updateQueuedAudioData(
    298         size_t sizeInBytes, int64_t presentationTimeUs) {
    299     if (sizeInBytes == 0) {
    300         return OK;
    301     }
    302 
    303     Mutex::Autolock lock(mMutex);
    304 
    305     if (mAudioTrack == NULL) {
    306         ALOGW("updateQueuedAudioData: audioTrack has NOT been configured.");
    307         return INVALID_OPERATION;
    308     }
    309 
    310     int64_t numFrames = sizeInBytes / mAudioTrack->frameSize();
    311     int64_t maxMediaTimeUs = presentationTimeUs
    312             + getDurationIfPlayedAtNativeSampleRate_l(numFrames);
    313 
    314     int64_t nowUs = ALooper::GetNowUs();
    315     int64_t nowMediaUs = presentationTimeUs
    316             - getDurationIfPlayedAtNativeSampleRate_l(mNumFramesWritten)
    317             + getPlayedOutAudioDurationMedia_l(nowUs);
    318 
    319     mNumFramesWritten += numFrames;
    320 
    321     int64_t oldRealTime = -1;
    322     if (mNextBufferItemMediaUs != -1) {
    323         oldRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
    324     }
    325 
    326     mMediaClock->updateAnchor(nowMediaUs, nowUs, maxMediaTimeUs);
    327     mHasAudio = true;
    328 
    329     if (oldRealTime != -1) {
    330         int64_t newRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
    331         if (newRealTime >= oldRealTime) {
    332             return OK;
    333         }
    334     }
    335 
    336     mNextBufferItemMediaUs = -1;
    337     onDrainVideo_l();
    338     return OK;
    339 }
    340 
    341 void MediaSync::setName(const AString &name) {
    342     Mutex::Autolock lock(mMutex);
    343     mInput->setConsumerName(String8(name.c_str()));
    344 }
    345 
    346 void MediaSync::flush() {
    347     Mutex::Autolock lock(mMutex);
    348     if (mFrameScheduler != NULL) {
    349         mFrameScheduler->restart();
    350     }
    351     while (!mBufferItems.empty()) {
    352         BufferItem *bufferItem = &*mBufferItems.begin();
    353         returnBufferToInput_l(bufferItem->mGraphicBuffer, bufferItem->mFence);
    354         mBufferItems.erase(mBufferItems.begin());
    355     }
    356     mNextBufferItemMediaUs = -1;
    357     mNumFramesWritten = 0;
    358     mReturnPendingInputFrame = true;
    359     mReleaseCondition.signal();
    360     mMediaClock->clearAnchor();
    361 }
    362 
    363 status_t MediaSync::setVideoFrameRateHint(float rate) {
    364     Mutex::Autolock lock(mMutex);
    365     if (rate < 0.f) {
    366         return BAD_VALUE;
    367     }
    368     if (mFrameScheduler != NULL) {
    369         mFrameScheduler->init(rate);
    370     }
    371     return OK;
    372 }
    373 
    374 float MediaSync::getVideoFrameRate() {
    375     Mutex::Autolock lock(mMutex);
    376     if (mFrameScheduler != NULL) {
    377         float fps = mFrameScheduler->getFrameRate();
    378         if (fps > 0.f) {
    379             return fps;
    380         }
    381     }
    382 
    383     // we don't have or know the frame rate
    384     return -1.f;
    385 }
    386 
    387 status_t MediaSync::setSyncSettings(const AVSyncSettings &syncSettings) {
    388     // validate settings
    389     if (syncSettings.mSource >= AVSYNC_SOURCE_MAX
    390             || syncSettings.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
    391             || syncSettings.mTolerance < 0.f
    392             || syncSettings.mTolerance >= AVSYNC_TOLERANCE_MAX) {
    393         return BAD_VALUE;
    394     }
    395 
    396     Mutex::Autolock lock(mMutex);
    397 
    398     // verify that we have the sync source
    399     switch (syncSettings.mSource) {
    400         case AVSYNC_SOURCE_AUDIO:
    401             if (mAudioTrack == NULL) {
    402                 ALOGE("setSyncSettings: audio sync source requires an audio track");
    403                 return BAD_VALUE;
    404             }
    405             break;
    406         case AVSYNC_SOURCE_VSYNC:
    407             if (mOutput == NULL) {
    408                 ALOGE("setSyncSettings: vsync sync source requires an output surface");
    409                 return BAD_VALUE;
    410             }
    411             break;
    412         default:
    413             break;
    414     }
    415 
    416     mSyncSettings = syncSettings;
    417     resync_l();
    418     return OK;
    419 }
    420 
    421 void MediaSync::getSyncSettings(AVSyncSettings *syncSettings) {
    422     Mutex::Autolock lock(mMutex);
    423     *syncSettings = mSyncSettings;
    424 }
    425 
    426 status_t MediaSync::setPlaybackSettings(const AudioPlaybackRate &rate) {
    427     Mutex::Autolock lock(mMutex);
    428 
    429     status_t err = setPlaybackSettings_l(rate);
    430     if (err == OK) {
    431         // TODO: adjust rate if using VSYNC as source
    432         updatePlaybackRate_l(rate.mSpeed);
    433     }
    434     return err;
    435 }
    436 
    437 status_t MediaSync::setPlaybackSettings_l(const AudioPlaybackRate &rate) {
    438     if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
    439         // We don't validate other audio settings.
    440         // They will be validated when/if audiotrack is set.
    441         return BAD_VALUE;
    442     }
    443 
    444     if (mAudioTrack != NULL) {
    445         if (rate.mSpeed == 0.f) {
    446             mAudioTrack->pause();
    447         } else {
    448             status_t err = mAudioTrack->setPlaybackRate(rate);
    449             if (err != OK) {
    450                 return BAD_VALUE;
    451             }
    452 
    453             // ignore errors
    454             (void)mAudioTrack->start();
    455         }
    456     }
    457     mPlaybackSettings = rate;
    458     return OK;
    459 }
    460 
    461 void MediaSync::getPlaybackSettings(AudioPlaybackRate *rate) {
    462     Mutex::Autolock lock(mMutex);
    463     *rate = mPlaybackSettings;
    464 }
    465 
    466 int64_t MediaSync::getRealTime(int64_t mediaTimeUs, int64_t nowUs) {
    467     int64_t realUs;
    468     if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
    469         // If failed to get current position, e.g. due to audio clock is
    470         // not ready, then just play out video immediately without delay.
    471         return nowUs;
    472     }
    473     return realUs;
    474 }
    475 
    476 int64_t MediaSync::getDurationIfPlayedAtNativeSampleRate_l(int64_t numFrames) {
    477     return (numFrames * 1000000LL / mNativeSampleRateInHz);
    478 }
    479 
    480 int64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) {
    481     CHECK(mAudioTrack != NULL);
    482 
    483     uint32_t numFramesPlayed;
    484     int64_t numFramesPlayedAtUs;
    485     AudioTimestamp ts;
    486 
    487     status_t res = mAudioTrack->getTimestamp(ts);
    488     if (res == OK) {
    489         // case 1: mixing audio tracks.
    490         numFramesPlayed = ts.mPosition;
    491         numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
    492         //ALOGD("getTimestamp: OK %d %lld",
    493         //      numFramesPlayed, (long long)numFramesPlayedAtUs);
    494     } else if (res == WOULD_BLOCK) {
    495         // case 2: transitory state on start of a new track
    496         numFramesPlayed = 0;
    497         numFramesPlayedAtUs = nowUs;
    498         //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
    499         //      numFramesPlayed, (long long)numFramesPlayedAtUs);
    500     } else {
    501         // case 3: transitory at new track or audio fast tracks.
    502         res = mAudioTrack->getPosition(&numFramesPlayed);
    503         CHECK_EQ(res, (status_t)OK);
    504         numFramesPlayedAtUs = nowUs;
    505         numFramesPlayedAtUs += 1000LL * mAudioTrack->latency() / 2; /* XXX */
    506         //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
    507     }
    508 
    509     //can't be negative until 12.4 hrs, test.
    510     //CHECK_EQ(numFramesPlayed & (1 << 31), 0);
    511     int64_t durationUs =
    512         getDurationIfPlayedAtNativeSampleRate_l(numFramesPlayed)
    513             + nowUs - numFramesPlayedAtUs;
    514     if (durationUs < 0) {
    515         // Occurs when numFramesPlayed position is very small and the following:
    516         // (1) In case 1, the time nowUs is computed before getTimestamp() is
    517         //     called and numFramesPlayedAtUs is greater than nowUs by time more
    518         //     than numFramesPlayed.
    519         // (2) In case 3, using getPosition and adding mAudioTrack->latency()
    520         //     to numFramesPlayedAtUs, by a time amount greater than
    521         //     numFramesPlayed.
    522         //
    523         // Both of these are transitory conditions.
    524         ALOGV("getPlayedOutAudioDurationMedia_l: negative duration %lld "
    525               "set to zero", (long long)durationUs);
    526         durationUs = 0;
    527     }
    528     ALOGV("getPlayedOutAudioDurationMedia_l(%lld) nowUs(%lld) frames(%u) "
    529           "framesAt(%lld)",
    530           (long long)durationUs, (long long)nowUs, numFramesPlayed,
    531           (long long)numFramesPlayedAtUs);
    532     return durationUs;
    533 }
    534 
    535 void MediaSync::onDrainVideo_l() {
    536     if (!isPlaying()) {
    537         return;
    538     }
    539 
    540     while (!mBufferItems.empty()) {
    541         int64_t nowUs = ALooper::GetNowUs();
    542         BufferItem *bufferItem = &*mBufferItems.begin();
    543         int64_t itemMediaUs = bufferItem->mTimestamp / 1000;
    544         int64_t itemRealUs = getRealTime(itemMediaUs, nowUs);
    545 
    546         // adjust video frame PTS based on vsync
    547         itemRealUs = mFrameScheduler->schedule(itemRealUs * 1000) / 1000;
    548         int64_t twoVsyncsUs = 2 * (mFrameScheduler->getVsyncPeriod() / 1000);
    549 
    550         // post 2 display refreshes before rendering is due
    551         if (itemRealUs <= nowUs + twoVsyncsUs) {
    552             ALOGV("adjusting PTS from %lld to %lld",
    553                     (long long)bufferItem->mTimestamp / 1000, (long long)itemRealUs);
    554             bufferItem->mTimestamp = itemRealUs * 1000;
    555             bufferItem->mIsAutoTimestamp = false;
    556 
    557             if (mHasAudio) {
    558                 if (nowUs - itemRealUs <= kMaxAllowedVideoLateTimeUs) {
    559                     renderOneBufferItem_l(*bufferItem);
    560                 } else {
    561                     // too late.
    562                     returnBufferToInput_l(
    563                             bufferItem->mGraphicBuffer, bufferItem->mFence);
    564                     mFrameScheduler->restart();
    565                 }
    566             } else {
    567                 // always render video buffer in video-only mode.
    568                 renderOneBufferItem_l(*bufferItem);
    569 
    570                 // smooth out videos >= 10fps
    571                 mMediaClock->updateAnchor(
    572                         itemMediaUs, nowUs, itemMediaUs + 100000);
    573             }
    574 
    575             mBufferItems.erase(mBufferItems.begin());
    576             mNextBufferItemMediaUs = -1;
    577         } else {
    578             if (mNextBufferItemMediaUs == -1
    579                     || mNextBufferItemMediaUs > itemMediaUs) {
    580                 sp<AMessage> msg = new AMessage(kWhatDrainVideo, this);
    581                 msg->post(itemRealUs - nowUs - twoVsyncsUs);
    582                 mNextBufferItemMediaUs = itemMediaUs;
    583             }
    584             break;
    585         }
    586     }
    587 }
    588 
    589 void MediaSync::onFrameAvailableFromInput() {
    590     Mutex::Autolock lock(mMutex);
    591 
    592     const static nsecs_t kAcquireWaitTimeout = 2000000000; // 2 seconds
    593 
    594     mReturnPendingInputFrame = false;
    595 
    596     // If there are too many outstanding buffers, wait until a buffer is
    597     // released back to the input in onBufferReleased.
    598     // NOTE: BufferQueue allows dequeuing maxAcquiredBufferCount + 1 buffers
    599     while (mNumOutstandingBuffers > mMaxAcquiredBufferCount
    600             && !mIsAbandoned && !mReturnPendingInputFrame) {
    601         if (mReleaseCondition.waitRelative(mMutex, kAcquireWaitTimeout) != OK) {
    602             ALOGI_IF(mPlaybackRate != 0.f, "still waiting to release a buffer before acquire");
    603         }
    604 
    605         // If the sync is abandoned while we are waiting, the release
    606         // condition variable will be broadcast, and we should just return
    607         // without attempting to do anything more (since the input queue will
    608         // also be abandoned).
    609         if (mIsAbandoned) {
    610             return;
    611         }
    612     }
    613 
    614     // Acquire and detach the buffer from the input.
    615     BufferItem bufferItem;
    616     status_t status = mInput->acquireBuffer(&bufferItem, 0 /* presentWhen */);
    617     if (status != NO_ERROR) {
    618         ALOGE("acquiring buffer from input failed (%d)", status);
    619         return;
    620     }
    621     ++mNumOutstandingBuffers;
    622 
    623     ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId());
    624 
    625     status = mInput->detachBuffer(bufferItem.mSlot);
    626     if (status != NO_ERROR) {
    627         ALOGE("detaching buffer from input failed (%d)", status);
    628         if (status == NO_INIT) {
    629             // If the input has been abandoned, move on.
    630             onAbandoned_l(true /* isInput */);
    631         }
    632         return;
    633     }
    634 
    635     if (mBuffersFromInput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
    636         // Something is wrong since this buffer should be at our hands, bail.
    637         ALOGE("received buffer multiple times from input");
    638         mInput->consumerDisconnect();
    639         onAbandoned_l(true /* isInput */);
    640         return;
    641     }
    642     mBuffersFromInput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
    643 
    644     // If flush happened while waiting for a buffer to be released, simply return it
    645     // TRICKY: do it here after it is detached so that we don't have to cache mGraphicBuffer.
    646     if (mReturnPendingInputFrame) {
    647         mReturnPendingInputFrame = false;
    648         returnBufferToInput_l(bufferItem.mGraphicBuffer, bufferItem.mFence);
    649         return;
    650     }
    651 
    652     mBufferItems.push_back(bufferItem);
    653 
    654     if (mBufferItems.size() == 1) {
    655         onDrainVideo_l();
    656     }
    657 }
    658 
    659 void MediaSync::renderOneBufferItem_l(const BufferItem &bufferItem) {
    660     IGraphicBufferProducer::QueueBufferInput queueInput(
    661             bufferItem.mTimestamp,
    662             bufferItem.mIsAutoTimestamp,
    663             bufferItem.mDataSpace,
    664             bufferItem.mCrop,
    665             static_cast<int32_t>(bufferItem.mScalingMode),
    666             bufferItem.mTransform,
    667             bufferItem.mFence);
    668 
    669     // Attach and queue the buffer to the output.
    670     int slot;
    671     mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber());
    672     status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer);
    673     ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status);
    674     if (status == NO_ERROR) {
    675         IGraphicBufferProducer::QueueBufferOutput queueOutput;
    676         status = mOutput->queueBuffer(slot, queueInput, &queueOutput);
    677         ALOGE_IF(status != NO_ERROR, "queueing buffer to output failed (%d)", status);
    678     }
    679 
    680     if (status != NO_ERROR) {
    681         returnBufferToInput_l(bufferItem.mGraphicBuffer, bufferItem.mFence);
    682         if (status == NO_INIT) {
    683             // If the output has been abandoned, move on.
    684             onAbandoned_l(false /* isInput */);
    685         }
    686         return;
    687     }
    688 
    689     if (mBuffersSentToOutput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
    690         // Something is wrong since this buffer should be held by output now, bail.
    691         mInput->consumerDisconnect();
    692         onAbandoned_l(true /* isInput */);
    693         return;
    694     }
    695     mBuffersSentToOutput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
    696 
    697     ALOGV("queued buffer %#llx to output", (long long)bufferItem.mGraphicBuffer->getId());
    698 }
    699 
    700 void MediaSync::onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output) {
    701     Mutex::Autolock lock(mMutex);
    702 
    703     if (output != mOutput) {
    704         return;  // This is not the current output, ignore.
    705     }
    706 
    707     sp<GraphicBuffer> buffer;
    708     sp<Fence> fence;
    709     status_t status = mOutput->detachNextBuffer(&buffer, &fence);
    710     ALOGE_IF(status != NO_ERROR, "detaching buffer from output failed (%d)", status);
    711 
    712     if (status == NO_INIT) {
    713         // If the output has been abandoned, we can't do anything else,
    714         // since buffer is invalid.
    715         onAbandoned_l(false /* isInput */);
    716         return;
    717     }
    718 
    719     ALOGV("detached buffer %#llx from output", (long long)buffer->getId());
    720 
    721     // If we've been abandoned, we can't return the buffer to the input, so just
    722     // move on.
    723     if (mIsAbandoned) {
    724         return;
    725     }
    726 
    727     ssize_t ix = mBuffersSentToOutput.indexOfKey(buffer->getId());
    728     if (ix < 0) {
    729         // The buffer is unknown, maybe leftover, ignore.
    730         return;
    731     }
    732     mBuffersSentToOutput.removeItemsAt(ix);
    733 
    734     returnBufferToInput_l(buffer, fence);
    735 }
    736 
    737 void MediaSync::returnBufferToInput_l(
    738         const sp<GraphicBuffer> &buffer, const sp<Fence> &fence) {
    739     ssize_t ix = mBuffersFromInput.indexOfKey(buffer->getId());
    740     if (ix < 0) {
    741         // The buffer is unknown, something is wrong, bail.
    742         ALOGE("output returned unknown buffer");
    743         mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
    744         onAbandoned_l(false /* isInput */);
    745         return;
    746     }
    747     sp<GraphicBuffer> oldBuffer = mBuffersFromInput.valueAt(ix);
    748     mBuffersFromInput.removeItemsAt(ix);
    749 
    750     // Attach and release the buffer back to the input.
    751     int consumerSlot;
    752     status_t status = mInput->attachBuffer(&consumerSlot, oldBuffer);
    753     ALOGE_IF(status != NO_ERROR, "attaching buffer to input failed (%d)", status);
    754     if (status == NO_ERROR) {
    755         status = mInput->releaseBuffer(consumerSlot, 0 /* frameNumber */,
    756                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
    757         ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status);
    758     }
    759 
    760     // Notify any waiting onFrameAvailable calls.
    761     --mNumOutstandingBuffers;
    762     mReleaseCondition.signal();
    763 
    764     if (status == NO_ERROR) {
    765         ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
    766     }
    767 }
    768 
    769 void MediaSync::onAbandoned_l(bool isInput) {
    770     ALOGE("the %s has abandoned me", (isInput ? "input" : "output"));
    771     if (!mIsAbandoned) {
    772         if (isInput) {
    773             mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
    774         } else {
    775             mInput->consumerDisconnect();
    776         }
    777         mIsAbandoned = true;
    778     }
    779     mReleaseCondition.broadcast();
    780 }
    781 
    782 void MediaSync::onMessageReceived(const sp<AMessage> &msg) {
    783     switch (msg->what()) {
    784         case kWhatDrainVideo:
    785         {
    786             Mutex::Autolock lock(mMutex);
    787             if (mNextBufferItemMediaUs != -1) {
    788                 int64_t nowUs = ALooper::GetNowUs();
    789                 int64_t itemRealUs = getRealTime(mNextBufferItemMediaUs, nowUs);
    790 
    791                 // The message could arrive earlier than expected due to
    792                 // various reasons, e.g., media clock has been changed because
    793                 // of new anchor time or playback rate. In such cases, the
    794                 // message needs to be re-posted.
    795                 if (itemRealUs > nowUs) {
    796                     msg->post(itemRealUs - nowUs);
    797                     break;
    798                 }
    799             }
    800 
    801             onDrainVideo_l();
    802             break;
    803         }
    804 
    805         default:
    806             TRESPASS();
    807             break;
    808     }
    809 }
    810 
    811 MediaSync::InputListener::InputListener(const sp<MediaSync> &sync)
    812       : mSync(sync) {}
    813 
    814 MediaSync::InputListener::~InputListener() {}
    815 
    816 void MediaSync::InputListener::onFrameAvailable(const BufferItem &/* item */) {
    817     mSync->onFrameAvailableFromInput();
    818 }
    819 
    820 // We don't care about sideband streams, since we won't relay them.
    821 void MediaSync::InputListener::onSidebandStreamChanged() {
    822     ALOGE("onSidebandStreamChanged: got sideband stream unexpectedly.");
    823 }
    824 
    825 
    826 void MediaSync::InputListener::binderDied(const wp<IBinder> &/* who */) {
    827     Mutex::Autolock lock(mSync->mMutex);
    828     mSync->onAbandoned_l(true /* isInput */);
    829 }
    830 
    831 MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync,
    832         const sp<IGraphicBufferProducer> &output)
    833       : mSync(sync),
    834         mOutput(output) {}
    835 
    836 MediaSync::OutputListener::~OutputListener() {}
    837 
    838 void MediaSync::OutputListener::onBufferReleased() {
    839     mSync->onBufferReleasedByOutput(mOutput);
    840 }
    841 
    842 void MediaSync::OutputListener::binderDied(const wp<IBinder> &/* who */) {
    843     Mutex::Autolock lock(mSync->mMutex);
    844     mSync->onAbandoned_l(false /* isInput */);
    845 }
    846 
    847 } // namespace android
    848