/* * Copyright (c) 2020 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ //#define LOG_NDEBUG 1 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #ifndef LINUX_COMPILE #include #endif #include #include "VideoTunnelDev.h" #include #define VT_ROLE_CONSUMER 1 #define VT_POLL_TIMEOUT 32 //ms std::mutex VideoTunnelDev::sLock; VideoTunnelDev * VideoTunnelDev::sInstance(nullptr); void VideoTunnelDev::resetInstanceForTest() { std::lock_guard lock(sLock); if (sInstance != nullptr) { delete sInstance; sInstance = nullptr; } } VideoTunnelDev::VideoTunnelDev() { mDrvFd = meson_vt_open(); MESON_ASSERT(mDrvFd >= 0, "/dev/videotunnel device open failed: %s", strerror(errno)); // set videotunnel to non block mode by default int ret = meson_vt_set_mode(mDrvFd, 0); if (ret != 0) MESON_LOGE("videotunnelDev set to non block mode failed(%d)", ret); } VideoTunnelDev &VideoTunnelDev::getInstance() { std::lock_guard lock(sLock); VideoTunnelDev *instance = sInstance; if (instance == nullptr) { instance = new VideoTunnelDev(); sInstance = instance; } return *instance; } VideoTunnelDev::~VideoTunnelDev() { if (mDrvFd > 0) meson_vt_close(mDrvFd); mDrvFd = -1; } int32_t VideoTunnelDev::connect(int tunnelId) { return meson_vt_connect(mDrvFd, tunnelId, VT_ROLE_CONSUMER); } int32_t VideoTunnelDev::disconnect(int tunnelId) { return meson_vt_disconnect(mDrvFd, tunnelId, VT_ROLE_CONSUMER); } int32_t VideoTunnelDev::acquireBuffer(int tunnelId, int& bufferFd, int64_t& timeStamp, struct vt_meta_data& meta_data) { int fenceFd; return meson_vt_acquire_buffer(mDrvFd, tunnelId, &bufferFd, &fenceFd, &timeStamp, &meta_data); } int32_t VideoTunnelDev::releaseBuffer(int tunnelId, int bufferFd, int fenceFd) { return meson_vt_release_buffer(mDrvFd, tunnelId, bufferFd, fenceFd); } int32_t VideoTunnelDev::receiveCmd(int tunnelId, enum vt_cmd& cmd, struct vt_cmd_data& cmdData) { return meson_vt_recv_cmd(mDrvFd, tunnelId, &cmd, &cmdData); } /* * Return of -EAGAIN means the operation timeout or error. * On success, return of 0 means videotunnel can receive game mode buffer */ int32_t VideoTunnelDev::pollGameModeBuffer() { struct pollfd pfd; pfd.fd = mDrvFd; pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND; pfd.revents = 0; int pollrtn = poll(&pfd, 1, VT_POLL_TIMEOUT); if (pollrtn > 0) { if ((pfd.revents & POLLERR) ||(pfd.revents & POLLRDBAND)) return -EINVAL; else if (pfd.revents & POLLIN) return 0; } return -EAGAIN; } int32_t VideoTunnelDev::setNonBlockMode() { return meson_vt_set_mode(mDrvFd, 0); } int32_t VideoTunnelDev::pollCmds() { return meson_vt_poll_cmd(mDrvFd, VT_POLL_TIMEOUT); } int32_t VideoTunnelDev::askRefresh(int tunnelId, bool flag) { return meson_vt_ask_refresh(mDrvFd, tunnelId, flag); } VideoTunnelDev::VtPollStatus VideoTunnelDev::pollBufferAndCmds() { struct pollfd pfd; pfd.fd = mDrvFd; pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND; pfd.revents = 0; int pollrtn = poll(&pfd, 1, VT_POLL_TIMEOUT); if (pollrtn > 0) { if (pfd.revents & POLLIN) return VtPollStatus::eBufferReady; if (pfd.revents & POLLOUT) return VtPollStatus::eCmdReady; } return VtPollStatus::eNotReady; } int32_t VideoTunnelDev::setDisplayVsyncInfo(uint64_t timestamp, uint32_t vsyncPeriodNanos) { // ignored tunnel id now return meson_vt_setDisplayVsyncAndPeriod(mDrvFd, -1, timestamp, vsyncPeriodNanos); }