/* * Copyright (C) 2021 Amlogic Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "Logger.h" #include "drm_display.h" #include "drm_framerecycle.h" using namespace ATools; #define TAG "rlib:drm_framerecycle" DrmFrameRecycle::DrmFrameRecycle(DrmDisplay *drmDisplay, int logCategory) { mDrmDisplay = drmDisplay; mLogCategory = logCategory; mStop = false; mWaitVideoFence = false; mQueue = new ATools::Queue(); } DrmFrameRecycle::~DrmFrameRecycle() { if (isRunning()) { mStop = true; DEBUG(mLogCategory,"stop frame recycle thread"); requestExitAndWait(); } if (mQueue) { mQueue->flushAndCallback(this, DrmFrameRecycle::queueFlushCallback); delete mQueue; mQueue = NULL; } } bool DrmFrameRecycle::start() { DEBUG(mLogCategory,"start frame recycle thread"); mStop = false; run("frame recycle thread"); return true; } bool DrmFrameRecycle::stop() { if (isRunning()) { mStop = true; DEBUG(mLogCategory,"stop frame recycle thread"); requestExitAndWait(); } mWaitVideoFence = false; ATools::Mutex::Autolock _l(mMutex); mQueue->flushAndCallback(this, DrmFrameRecycle::queueFlushCallback); return true; } bool DrmFrameRecycle::recycleFrame(FrameEntity * frameEntity) { ATools::Mutex::Autolock _l(mMutex); if (mStop) { mDrmDisplay->handleReleaseFrameEntity(frameEntity); return true; } mQueue->push(frameEntity); TRACE(mLogCategory,"queue cnt:%d",mQueue->getCnt()); /* when two frame are posted, fence can be retrieved. * So waiting video fence starts */ if (!mWaitVideoFence && mQueue->getCnt() > 2) { mWaitVideoFence = true; } return true; } void DrmFrameRecycle::queueFlushCallback(void *userdata,void *data) { DrmFrameRecycle* self = static_cast(userdata); self->mDrmDisplay->handleReleaseFrameEntity((FrameEntity *)data); } void DrmFrameRecycle::readyToRun() { } bool DrmFrameRecycle::threadLoop() { int rc; FrameEntity *frameEntity; DrmMesonLib *drmMesonLib = mDrmDisplay->getDrmMesonLib(); struct drm_display * disp = mDrmDisplay->getDrmHandle(); if (mStop) { return false; } if (!mWaitVideoFence || mQueue->getCnt() < 2) { usleep(8000); return true; } rc = mQueue->popAndWait((void**)&frameEntity); if (rc != Q_OK) { return true; } TRACE(mLogCategory,"wait video fence for frame:%lld(pts:%lld)",frameEntity->displayTime,frameEntity->renderBuf->pts); if (drmMesonLib && disp) { rc = drmMesonLib->libDrmWaitVideoFence(disp, frameEntity->drmBuf->fd[0]); } if (rc <= 0) { WARNING(mLogCategory, "wait fence error %d", rc); } mDrmDisplay->handleReleaseFrameEntity(frameEntity); return true; }