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