Files

137 lines
3.8 KiB
C++

/*
* 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 <utils/Trace.h>
#endif
#include <MesonLog.h>
#include "VideoTunnelDev.h"
#include <poll.h>
#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<std::mutex> 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<std::mutex> 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);
}