190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar/*
290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * Copyright 2015 The Android Open Source Project
390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar *
490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * you may not use this file except in compliance with the License.
690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * You may obtain a copy of the License at
790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar *
890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar *
1090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * Unless required by applicable law or agreed to in writing, software
1190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * See the License for the specific language governing permissions and
1490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar * limitations under the License.
1590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar */
1690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
1790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar//#define LOG_NDEBUG 0
1890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar#define LOG_TAG "FrameRenderTracker"
1990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
2090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar#include <inttypes.h>
2190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar#include <gui/Surface.h>
2290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
2390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar#include <media/stagefright/foundation/ADebug.h>
2490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar#include <media/stagefright/FrameRenderTracker.h>
2590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
2690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarnamespace android {
2790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
2890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos MolnarFrameRenderTracker::FrameRenderTracker()
2990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    : mLastRenderTimeNs(-1),
3090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar      mComponentName("unknown component") {
3190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
3290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
3390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos MolnarFrameRenderTracker::~FrameRenderTracker() {
3490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
3590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
3690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarvoid FrameRenderTracker::setComponentName(const AString &componentName) {
3790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mComponentName = componentName;
3890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
3990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
4090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarvoid FrameRenderTracker::clear(nsecs_t lastRenderTimeNs) {
4190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mRenderQueue.clear();
4290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mLastRenderTimeNs = lastRenderTimeNs;
4390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
4490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
4590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarvoid FrameRenderTracker::onFrameQueued(
4690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        int64_t mediaTimeUs, const sp<GraphicBuffer> &graphicBuffer, const sp<Fence> &fence) {
4790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mRenderQueue.emplace_back(mediaTimeUs, graphicBuffer, fence);
4890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
4990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
5090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos MolnarFrameRenderTracker::Info *FrameRenderTracker::updateInfoForDequeuedBuffer(
5190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        ANativeWindowBuffer *buf, int fenceFd, int index) {
5290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (index < 0) {
5390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return NULL;
5490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
5590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
5690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // see if this is a buffer that was to be rendered
5790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    std::list<Info>::iterator renderInfo = mRenderQueue.end();
5890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    for (std::list<Info>::iterator it = mRenderQueue.begin();
5990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            it != mRenderQueue.end(); ++it) {
6090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        if (it->mGraphicBuffer->handle == buf->handle) {
6190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            renderInfo = it;
6290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            break;
6390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
6490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
6590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (renderInfo == mRenderQueue.end()) {
6690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // could have been canceled after fence has signaled
6790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return NULL;
6890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
6990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
7090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (renderInfo->mIndex >= 0) {
7190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // buffer has been dequeued before, so there is nothing to do
7290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return NULL;
7390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
7490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
7590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // was this frame dropped (we could also infer this if the fence is invalid or a dup of
7690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // the queued fence; however, there is no way to figure that out.)
7790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (fenceFd < 0) {
7890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // frame is new or was dropped
7990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        mRenderQueue.erase(renderInfo);
8090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return NULL;
8190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
8290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
8390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // store dequeue fence and buffer index
8490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    renderInfo->mFence = new Fence(::dup(fenceFd));
8590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    renderInfo->mIndex = index;
8690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    return &*renderInfo;
8790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
8890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
8990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarstatus_t FrameRenderTracker::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
9090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // ensure monotonic timestamps
9190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (mLastRenderTimeNs >= systemNano) {
9290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        ALOGW("[%s] Ignoring out of order/stale system nano %lld for media time %lld from codec.",
9390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                mComponentName.c_str(), (long long)systemNano, (long long)mediaTimeUs);
9490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return BAD_VALUE;
9590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
9690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
9790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
9890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    if (systemNano > now) {
9990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        ALOGW("[%s] Ignoring system nano %lld in the future for media time %lld from codec.",
10090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                mComponentName.c_str(), (long long)systemNano, (long long)mediaTimeUs);
10190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        return OK;
10290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
10390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
10490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mRenderQueue.emplace_back(mediaTimeUs, systemNano);
10590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    mLastRenderTimeNs = systemNano;
10690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    return OK;
10790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
10890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
10990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarstd::list<FrameRenderTracker::Info> FrameRenderTracker::checkFencesAndGetRenderedFrames(
11090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        const FrameRenderTracker::Info *until, bool dropIncomplete) {
11190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    std::list<Info> done;
11290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
11390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    // complete any frames queued prior to this and drop any incomplete ones if requested
11490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    for (std::list<Info>::iterator it = mRenderQueue.begin();
11590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            it != mRenderQueue.end(); ) {
11690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        bool drop = false; // whether to drop each frame
11790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        if (it->mIndex < 0) {
11890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            // frame not yet dequeued (or already rendered on a tunneled surface)
11990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            drop = dropIncomplete;
12090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        } else if (it->mFence != NULL) {
12190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            // check if fence signaled
12290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            nsecs_t signalTime = it->mFence->getSignalTime();
12390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            if (signalTime < 0) { // invalid fence
12490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                drop = true;
12590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            } else if (signalTime == INT64_MAX) { // unsignaled fence
12690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                drop = dropIncomplete;
12790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            } else { // signaled
12890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                // save render time
12990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                it->mFence.clear();
13090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                it->mRenderTimeNs = signalTime;
13190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            }
13290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
13390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        bool foundFrame = (Info *)&*it == until;
13490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
13590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // Return frames with signaled fences at the start of the queue, as they are
13690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // in submit order, and we don't have to wait for any in-between frames.
13790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        // Also return any dropped frames.
13890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        if (drop || (it->mFence == NULL && it == mRenderQueue.begin())) {
13990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            // (unrendered) dropped frames have their mRenderTimeNs still set to -1
14090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            done.splice(done.end(), mRenderQueue, it++);
14190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        } else {
14290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            ++it;
14390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
14490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        if (foundFrame) {
14590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            break;
14690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
14790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
14890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
14990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    return done;
15090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
15190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
152604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnarvoid FrameRenderTracker::untrackFrame(const FrameRenderTracker::Info *info, ssize_t index) {
153604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar    if (info == NULL && index == SSIZE_MAX) {
154604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar        // nothing to do
155604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar        return;
156604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar    }
157604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar
158604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar    for (std::list<Info>::iterator it = mRenderQueue.begin();
159604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar            it != mRenderQueue.end(); ) {
160604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar        if (&*it == info) {
161604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar            mRenderQueue.erase(it++);
162604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar        } else {
163604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar            if (it->mIndex > index) {
164604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar                --(it->mIndex);
16590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            }
166604bb9ea6e9bec763ae231330066ecffa90a2786Lajos Molnar            ++it;
16790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
16890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
16990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
17090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
17190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnarvoid FrameRenderTracker::dumpRenderQueue() const {
17290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    ALOGI("[%s] Render Queue: (last render time: %lldns)",
17390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            mComponentName.c_str(), (long long)mLastRenderTimeNs);
17490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    for (std::list<Info>::const_iterator it = mRenderQueue.cbegin();
17590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            it != mRenderQueue.cend(); ++it) {
17690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        if (it->mFence == NULL) {
17790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            ALOGI("  RENDERED: handle: %p, media time: %lldus, index: %zd, render time: %lldns",
17890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                    it->mGraphicBuffer == NULL ? NULL : it->mGraphicBuffer->handle,
17990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                    (long long)it->mMediaTimeUs, it->mIndex, (long long)it->mRenderTimeNs);
18090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        } else if (it->mIndex < 0) {
18190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            ALOGI("    QUEUED: handle: %p, media time: %lldus, fence: %s",
18290fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                    it->mGraphicBuffer->handle, (long long)it->mMediaTimeUs,
18390fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                    it->mFence->isValid() ? "YES" : "NO");
18490fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        } else {
18590fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar            ALOGI("  DEQUEUED: handle: %p, media time: %lldus, index: %zd",
18690fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar                    it->mGraphicBuffer->handle, (long long)it->mMediaTimeUs, it->mIndex);
18790fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar        }
18890fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar    }
18990fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}
19090fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar
19190fcf68fd29f3cb695bd53a830ad984cb7d430c0Lajos Molnar}  // namespace android
192