You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.5 KiB
324 lines
9.5 KiB
/*
|
|
* Copyright (C) 2024 Rockchip Electronics Co. LTD
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#undef ROCKCHIP_LOG_TAG
|
|
#define ROCKCHIP_LOG_TAG "C2RKTunneledSession"
|
|
|
|
#include <dlfcn.h>
|
|
#include <string.h>
|
|
|
|
#include "C2RKLog.h"
|
|
#include "C2RKTunneledSession.h"
|
|
|
|
|
|
#define C2_TUNNELED_RESEVED_SIZE 3
|
|
|
|
|
|
namespace android {
|
|
|
|
typedef int32_t OpenTunnelFunc();
|
|
typedef int32_t CloseTunnelFunc(int32_t fd);
|
|
typedef int32_t AllocTunnelIdFunc(int32_t fd, int32_t *id);
|
|
typedef int32_t FreeTunnelIdFunc(int32_t fd, int32_t id);
|
|
typedef int32_t ResetTunnelFunc(int32_t fd, int32_t id);
|
|
typedef int32_t ConnectTunnelFunc(int32_t fd, int32_t id, int32_t role);
|
|
typedef int32_t DisconnectTunnelFunc(int32_t fd, int32_t id, int32_t role);
|
|
|
|
typedef int32_t DequeueBufferFunc(int32_t fd, int32_t id, int32_t timeout, VTBuffer_t **buffer);
|
|
typedef int32_t QueueBufferFunc(int32_t fd, int32_t id, VTBuffer_t *buffer, int64_t presentTime);
|
|
typedef int32_t CancelBufferFunc(int32_t fd, int32_t id, VTBuffer_t *buffer);
|
|
|
|
typedef int32_t FreeVtBufferFunc(VTBuffer_t **buffer);
|
|
typedef VTBuffer_t* MallocVtBufferFunc();
|
|
|
|
class VTunnelImpl {
|
|
public:
|
|
VTunnelImpl() {
|
|
mDevFd = 0;
|
|
mTunnelId = 0;
|
|
}
|
|
|
|
~VTunnelImpl() {
|
|
closeConnection();
|
|
}
|
|
|
|
int openConnection() {
|
|
mLibFd = dlopen("librkvt.so", RTLD_LAZY);
|
|
if (mLibFd == nullptr) {
|
|
c2_err("failed to open librkvt, %s", dlerror());
|
|
return 0;
|
|
}
|
|
|
|
mCreateFunc = (OpenTunnelFunc *)dlsym(mLibFd, "rk_vt_open");
|
|
mDestroyFunc = (CloseTunnelFunc *)dlsym(mLibFd, "rk_vt_close");
|
|
mAllocIdFunc = (AllocTunnelIdFunc *)dlsym(mLibFd, "rk_vt_alloc_id");
|
|
mFreeIdFunc = (FreeTunnelIdFunc *)dlsym(mLibFd, "rk_vt_free_id");
|
|
mResetFunc = (ResetTunnelFunc *)dlsym(mLibFd, "rk_vt_reset");
|
|
mConnectFunc = (ConnectTunnelFunc *)dlsym(mLibFd, "rk_vt_connect");
|
|
mDisconnectFunc = (DisconnectTunnelFunc *)dlsym(mLibFd, "rk_vt_disconnect");
|
|
|
|
mDequeueBufferFunc = (DequeueBufferFunc *)dlsym(mLibFd, "rk_vt_dequeue_buffer");
|
|
mQueueBufferFunc = (QueueBufferFunc *)dlsym(mLibFd, "rk_vt_queue_buffer");
|
|
mCancelBufferFunc = (CancelBufferFunc *)dlsym(mLibFd, "rk_vt_cancel_buffer");
|
|
mMallocVTBufferFunc = (MallocVtBufferFunc *)dlsym(mLibFd, "rk_vt_buffer_malloc");
|
|
mFreeVTBufferFunc = (FreeVtBufferFunc *)dlsym(mLibFd, "rk_vt_buffer_free");
|
|
|
|
if (!mCreateFunc || !mDestroyFunc || !mAllocIdFunc || !mFreeIdFunc ||
|
|
!mResetFunc || !mConnectFunc || !mDisconnectFunc || !mDequeueBufferFunc ||
|
|
!mQueueBufferFunc || !mCancelBufferFunc ||
|
|
!mMallocVTBufferFunc || !mFreeVTBufferFunc) {
|
|
c2_err("could not find symbol, %s", dlerror());
|
|
mDevFd = 0;
|
|
mTunnelId = 0;
|
|
goto error;
|
|
}
|
|
|
|
if (mDevFd <= 0) {
|
|
mDevFd = mCreateFunc();
|
|
if (mDevFd <= 0) {
|
|
c2_err("open error");
|
|
goto error;
|
|
}
|
|
if (mAllocIdFunc(mDevFd, &mTunnelId)) {
|
|
c2_err("alloc error");
|
|
goto error;
|
|
}
|
|
if (mConnectFunc(mDevFd, mTunnelId, RKVT_ROLE_PRODUCER)) {
|
|
c2_err("connect error");
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
c2_trace("open tunnel sesion: devFd %d tunnleId %d", mDevFd, mTunnelId);
|
|
return mTunnelId;
|
|
|
|
error:
|
|
closeConnection();
|
|
return 0;
|
|
}
|
|
|
|
void closeConnection() {
|
|
if (mDevFd > 0) {
|
|
if (mTunnelId > 0) {
|
|
mFreeIdFunc(mDevFd, mTunnelId);
|
|
mDisconnectFunc(mDevFd, mTunnelId, RKVT_ROLE_PRODUCER);
|
|
}
|
|
mDestroyFunc(mDevFd);
|
|
}
|
|
if (mLibFd) {
|
|
dlclose(mLibFd);
|
|
}
|
|
|
|
mDevFd = 0;
|
|
mLibFd = 0;
|
|
mTunnelId = 0;
|
|
}
|
|
|
|
void reset() {
|
|
if (mDevFd > 0) {
|
|
mResetFunc(mDevFd, mTunnelId);
|
|
}
|
|
}
|
|
|
|
bool dequeueBuffer(VTBuffer_t **buffer, int timeout) {
|
|
int32_t err = mDequeueBufferFunc(mDevFd, mTunnelId, timeout, buffer);
|
|
return (err == 0) ? true : false;
|
|
}
|
|
|
|
bool queueBuffer(VTBuffer_t *buffer, int64_t presentTime) {
|
|
int32_t err = mQueueBufferFunc(mDevFd, mTunnelId, buffer, presentTime);
|
|
return (err == 0) ? true : false;
|
|
}
|
|
|
|
bool cancelBuffer(VTBuffer_t *buffer) {
|
|
int32_t err = mCancelBufferFunc(mDevFd, mTunnelId, buffer);
|
|
return (err == 0) ? true : false;
|
|
}
|
|
|
|
void allocVTBuffer(VTBuffer_t **buffer) {
|
|
(*buffer) = mMallocVTBufferFunc();
|
|
}
|
|
|
|
void freeVTBuffer(VTBuffer_t *buffer) {
|
|
mFreeVTBufferFunc(&buffer);
|
|
}
|
|
|
|
private:
|
|
OpenTunnelFunc *mCreateFunc;
|
|
CloseTunnelFunc *mDestroyFunc;
|
|
AllocTunnelIdFunc *mAllocIdFunc;
|
|
FreeTunnelIdFunc *mFreeIdFunc;
|
|
ResetTunnelFunc *mResetFunc;
|
|
ConnectTunnelFunc *mConnectFunc;
|
|
DisconnectTunnelFunc *mDisconnectFunc;
|
|
|
|
DequeueBufferFunc *mDequeueBufferFunc;
|
|
QueueBufferFunc *mQueueBufferFunc;
|
|
CancelBufferFunc *mCancelBufferFunc;
|
|
MallocVtBufferFunc *mMallocVTBufferFunc;
|
|
FreeVtBufferFunc *mFreeVTBufferFunc;
|
|
|
|
private:
|
|
void *mLibFd;
|
|
int32_t mDevFd;
|
|
int32_t mTunnelId;
|
|
};
|
|
|
|
C2RKTunneledSession::C2RKTunneledSession() {
|
|
mImpl = new VTunnelImpl();
|
|
|
|
mTunnelId = 0;
|
|
mNeedReservedCnt = C2_TUNNELED_RESEVED_SIZE;
|
|
}
|
|
|
|
C2RKTunneledSession::~C2RKTunneledSession() {
|
|
if (mImpl) {
|
|
mImpl->closeConnection();
|
|
delete mImpl;
|
|
mImpl = nullptr;
|
|
}
|
|
}
|
|
|
|
bool C2RKTunneledSession::configure(TunnelParams_t params) {
|
|
if (mTunnelId <= 0) {
|
|
mTunnelId = mImpl->openConnection();
|
|
if (mTunnelId <= 0) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static uint64_t gSessionId = 0;
|
|
|
|
memset(&mSideband, 0, sizeof(mSideband));
|
|
|
|
++gSessionId;
|
|
mSideband.version = sizeof(SidebandHandler_t);
|
|
mSideband.tunnelId = mTunnelId;
|
|
mSideband.sessionId = gSessionId;
|
|
mSideband.crop.left = params.left;
|
|
mSideband.crop.top = params.top;
|
|
mSideband.crop.right = params.right;
|
|
mSideband.crop.bottom = params.bottom;
|
|
mSideband.width = params.width;
|
|
mSideband.height = params.height;
|
|
mSideband.format = params.format;
|
|
mSideband.transform = 0;
|
|
mSideband.usage = params.usage;
|
|
mSideband.dataSpace = params.dataSpace;
|
|
mSideband.compressMode = params.compressMode;
|
|
|
|
c2_info("sideband config: w %d h %d crop[%d %d %d %d] fmt 0x%x compress %d id %d",
|
|
mSideband.width, mSideband.height, mSideband.crop.left,
|
|
mSideband.crop.top, mSideband.crop.right, mSideband.crop.bottom,
|
|
mSideband.format, mSideband.compressMode, mSideband.tunnelId);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool C2RKTunneledSession::disconnect() {
|
|
this->reset();
|
|
mImpl->closeConnection();
|
|
return true;
|
|
}
|
|
|
|
bool C2RKTunneledSession::reset() {
|
|
c2_trace_func_enter();
|
|
mImpl->reset();
|
|
|
|
while (!mVTBuffers.isEmpty()) {
|
|
VTBuffer_t *buffer = mVTBuffers.editItemAt(0);
|
|
if (buffer != nullptr) {
|
|
freeVTBuffer(buffer);
|
|
}
|
|
mVTBuffers.removeAt(0);
|
|
}
|
|
|
|
mNeedReservedCnt = C2_TUNNELED_RESEVED_SIZE;
|
|
return true;
|
|
}
|
|
|
|
bool C2RKTunneledSession::needReservedBuffer() {
|
|
return (mNeedReservedCnt > 0);
|
|
}
|
|
|
|
bool C2RKTunneledSession::dequeueBuffer(VTBuffer_t **buffer, int32_t timeout) {
|
|
mImpl->dequeueBuffer(buffer, timeout);
|
|
if (*buffer) {
|
|
c2_trace("dequeue buffer %p", (*buffer));
|
|
(*buffer)->state = RKVT_STATE_DEQUEUED;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool C2RKTunneledSession::renderBuffer(VTBuffer_t *buffer, int64_t presentTime) {
|
|
if (mImpl->queueBuffer(buffer, presentTime)) {
|
|
c2_trace("render buffer %p", buffer);
|
|
buffer->state = RKVT_STATE_QUEUED;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool C2RKTunneledSession::cancelBuffer(VTBuffer_t *buffer) {
|
|
if (mImpl->cancelBuffer(buffer)) {
|
|
c2_trace("reseved buffer %p", buffer);
|
|
mNeedReservedCnt -= 1;
|
|
buffer->state = RKVT_STATE_QUEUED;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void C2RKTunneledSession::newVTBuffer(VTBuffer_t **buffer) {
|
|
mImpl->allocVTBuffer(buffer);
|
|
if (*buffer) {
|
|
c2_trace("alloc buffer %p", (*buffer));
|
|
(*buffer)->state = (mNeedReservedCnt > 0) ? RKVT_STATE_RESERVED : RTVT_STATE_NEW;
|
|
(*buffer)->crop = mSideband.crop;
|
|
|
|
mVTBuffers.push((*buffer));
|
|
}
|
|
}
|
|
|
|
void C2RKTunneledSession::freeVTBuffer(VTBuffer_t *buffer) {
|
|
c2_trace("free buffer %p", buffer);
|
|
mImpl->freeVTBuffer(buffer);
|
|
}
|
|
|
|
void* C2RKTunneledSession::getTunnelSideband() {
|
|
return &mSideband;
|
|
}
|
|
|
|
int32_t C2RKTunneledSession::getNeedDequeueCnt() {
|
|
int32_t count = 0;
|
|
|
|
for (int32_t i = 0; i < mVTBuffers.size(); i++) {
|
|
VTBuffer_t *buffer = mVTBuffers.editItemAt(i);
|
|
if (buffer->state == RKVT_STATE_QUEUED) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return (count - C2_TUNNELED_RESEVED_SIZE);
|
|
}
|
|
|
|
int32_t C2RKTunneledSession::getSmoothnessFactor() {
|
|
return C2_TUNNELED_RESEVED_SIZE;
|
|
}
|
|
|
|
}
|