253 lines
6.7 KiB
C++
253 lines
6.7 KiB
C++
/*
|
|
* Copyright (c) 2021 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
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "VtInstanceMgr.h"
|
|
#include "VideoTunnelDev.h"
|
|
|
|
std::mutex VtInstanceMgr::sLock;
|
|
VtInstanceMgr * VtInstanceMgr::sInstance(nullptr);
|
|
|
|
VtInstanceMgr::VtInstanceMgr() {
|
|
mInstances.clear();
|
|
mVtHandleEventsThread = nullptr;
|
|
mNeedTriggerRefresh = false;
|
|
}
|
|
|
|
VtInstanceMgr &VtInstanceMgr::getInstance() {
|
|
std::lock_guard<std::mutex> lock(sLock);
|
|
VtInstanceMgr *instance = sInstance;
|
|
if (instance == nullptr) {
|
|
instance = new VtInstanceMgr();
|
|
sInstance = instance;
|
|
}
|
|
|
|
return *instance;
|
|
}
|
|
|
|
VtInstanceMgr::~VtInstanceMgr() {
|
|
mInstances.clear();
|
|
if (mVtHandleEventsThread)
|
|
mVtHandleEventsThread->stopThread();
|
|
}
|
|
|
|
/* call from consumer, need hold mInstanceMutex before call*/
|
|
int32_t VtInstanceMgr::connectInstanceLocked(int tunnelId,
|
|
std::shared_ptr<VtConsumer>& consumer) {
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
int32_t ret = -1;
|
|
if (tunnelId < 0) {
|
|
MESON_LOGD("%s, get an invalid parameter %d", __func__, tunnelId);
|
|
return ret;
|
|
}
|
|
|
|
auto instanceIt = mInstances.find(tunnelId);
|
|
if (instanceIt == mInstances.end()) {
|
|
ptrInstance = std::make_shared<VtInstance> (tunnelId);
|
|
ret = ptrInstance->connect();
|
|
if (ret < 0) {
|
|
ptrInstance.reset();
|
|
MESON_LOGE("%s, [%d] connect video tunnel failed: %d",
|
|
__func__, tunnelId, ret);
|
|
return ret;
|
|
}
|
|
mNeedTriggerRefresh = false;
|
|
mInstances.emplace(tunnelId, ptrInstance);
|
|
} else {
|
|
mNeedTriggerRefresh = true;
|
|
ptrInstance = instanceIt->second;
|
|
}
|
|
|
|
if (ptrInstance.get())
|
|
ret = ptrInstance->registerVtConsumer(consumer, mNeedTriggerRefresh);
|
|
|
|
if (ret >= 0)
|
|
MESON_LOGD("%s, [%d] connect video tunnel succeeded",
|
|
__func__, tunnelId);
|
|
|
|
if (!mVtHandleEventsThread)
|
|
mVtHandleEventsThread = std::make_shared<VtHandleEventsThread>();
|
|
else
|
|
mVtHandleEventsThread->startThread();
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* call from consumer, need hold mInstanceMutex before call */
|
|
int32_t VtInstanceMgr::disconnectInstanceLocked(int tunnelId,
|
|
std::shared_ptr<VtConsumer>& consumer) {
|
|
int ret = -1;
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
|
|
if (tunnelId < 0 || !consumer.get()) {
|
|
MESON_LOGE("%s, [%d] parameters invalid",
|
|
__func__, tunnelId);
|
|
return ret;
|
|
}
|
|
|
|
if (mInstances.empty()) {
|
|
MESON_LOGW("%s, [%d] currently not found instance",
|
|
__func__, tunnelId);
|
|
return ret;
|
|
}
|
|
|
|
auto instanceIt = mInstances.find(tunnelId);
|
|
if (instanceIt != mInstances.end()) {
|
|
ptrInstance = instanceIt->second;
|
|
ret = ptrInstance->unregisterVtConsumer(consumer);
|
|
if (ret < 0)
|
|
MESON_LOGE("%s, [%d] unregister consumer failed: %d",
|
|
__func__, tunnelId, ret);
|
|
}
|
|
|
|
clearUpInstancesLocked();
|
|
return ret;
|
|
}
|
|
|
|
void VtInstanceMgr::clearUpInstances() {
|
|
std::lock_guard<std::mutex> lock(mInstanceMutex);
|
|
clearUpInstancesLocked();
|
|
}
|
|
|
|
void VtInstanceMgr::clearUpInstancesLocked() {
|
|
bool bRemove = false;
|
|
int id;
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
|
|
if (mInstances.empty())
|
|
return;
|
|
|
|
auto it = mInstances.begin();
|
|
for (; it != mInstances.end();) {
|
|
id = it->first;
|
|
ptrInstance = it->second;
|
|
bRemove = ptrInstance->needDestroyThisInstance();
|
|
if (bRemove) {
|
|
ptrInstance->disconnect();
|
|
it = mInstances.erase(it);
|
|
MESON_LOGD("%s, destroy instance %d succeeded",
|
|
__func__, id);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char * VtInstanceMgr::vtPollStatusToString(VideoTunnelDev::VtPollStatus status) {
|
|
const char * str;
|
|
switch (status) {
|
|
case VideoTunnelDev::VtPollStatus::eBufferReady:
|
|
str = "VT Buffer Ready";
|
|
break;
|
|
case VideoTunnelDev::VtPollStatus::eCmdReady:
|
|
str = "VT Cmd Ready";
|
|
break;
|
|
case VideoTunnelDev::VtPollStatus::eNotReady:
|
|
str = "VT Not Ready";
|
|
break;
|
|
case VideoTunnelDev::VtPollStatus::eRefresh:
|
|
str = "VT Need Refresh";
|
|
break;
|
|
default:
|
|
str = "Status is not found";
|
|
}
|
|
return str;
|
|
}
|
|
|
|
VideoTunnelDev::VtPollStatus VtInstanceMgr::pollVtEvents() {
|
|
VideoTunnelDev::VtPollStatus ret;
|
|
ret = VideoTunnelDev::VtPollStatus::eInvalidStatus;
|
|
|
|
clearUpInstances();
|
|
if (mInstances.empty()) {
|
|
/* will exit VtHandleEventsThread */
|
|
return ret;
|
|
}
|
|
|
|
ret = VideoTunnelDev::getInstance().pollBufferAndCmds();
|
|
if (ret == VideoTunnelDev::VtPollStatus::eNotReady && mNeedTriggerRefresh)
|
|
ret = VideoTunnelDev::VtPollStatus::eRefresh;
|
|
|
|
MESON_LOGV("VtInstanceMgr::%s %s",
|
|
__func__, vtPollStatusToString(ret));
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t VtInstanceMgr::handleBuffers() {
|
|
int32_t ret = -1;
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
|
|
std::lock_guard<std::mutex> lock(mInstanceMutex);
|
|
clearUpInstancesLocked();
|
|
if (mInstances.empty()) {
|
|
/* will exit VtHandleEventsThread */
|
|
return ret;
|
|
}
|
|
|
|
auto instanceIt = mInstances.begin();
|
|
for (; instanceIt != mInstances.end(); instanceIt++) {
|
|
ptrInstance = instanceIt->second;
|
|
ret = ptrInstance->acquireBuffer();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t VtInstanceMgr::handleCmds() {
|
|
int32_t ret = -1;
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
|
|
std::lock_guard<std::mutex> lock(mInstanceMutex);
|
|
clearUpInstancesLocked();
|
|
if (mInstances.empty()) {
|
|
/* will exit VtHandleEventsThread */
|
|
return ret;
|
|
}
|
|
|
|
auto instanceIt = mInstances.begin();
|
|
for (; instanceIt != mInstances.end(); instanceIt++) {
|
|
ptrInstance = instanceIt->second;
|
|
ret = ptrInstance->receiveCmds();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t VtInstanceMgr::handleRefresh() {
|
|
/* need refresh Cmds and last Buffer */
|
|
int32_t ret = -1;
|
|
std::shared_ptr<VtInstance> ptrInstance;
|
|
|
|
std::lock_guard<std::mutex> lock(mInstanceMutex);
|
|
mNeedTriggerRefresh = false;
|
|
|
|
if (mInstances.empty())
|
|
return ret;
|
|
|
|
auto instanceIt = mInstances.begin();
|
|
for (; instanceIt != mInstances.end(); instanceIt++) {
|
|
ptrInstance = instanceIt->second;
|
|
ret = ptrInstance->handleRefresh();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void VtInstanceMgr::lockInstancesMutex() {
|
|
mInstanceMutex.lock();
|
|
}
|
|
|
|
void VtInstanceMgr::unlockInstancesMutex() {
|
|
mInstanceMutex.unlock();
|
|
}
|