blob: eb13c79770170f133a063ed8181bc744b16fe8ab [file] [log] [blame]
/*
* Copyright (C) 2019-2020 Intel 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.
*/
#define LOG_TAG "IntelAlgoServer"
#include "modules/sandboxing/server/IntelAlgoServer.h"
#include <ia_log.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <memory>
#include <string>
#include "iutils/Utils.h"
#ifndef GPU_ALGO_SERVER
#include "modules/sandboxing/server/IntelCPUAlgoServer.h"
#else
#include "modules/sandboxing/server/IntelGPUAlgoServer.h"
#endif
namespace icamera {
IntelAlgoServer* IntelAlgoServer::mInstance = nullptr;
void IntelAlgoServer::init() {
LOGIPC("@%s", __func__);
if (mInstance == nullptr) {
mInstance = new IntelAlgoServer;
}
}
void IntelAlgoServer::deInit() {
LOGIPC("@%s", __func__);
delete mInstance;
mInstance = nullptr;
}
IntelAlgoServer::IntelAlgoServer() : mCallback(nullptr) {
LOGIPC("@%s", __func__);
ia_env env = {&Log::ccaPrintDebug, &Log::ccaPrintError, &Log::ccaPrintInfo};
ia_log_init(&env);
for (int i = 0; i < kThreadNum; i++) {
std::string name = IntelAlgoServerThreadName(i);
mThreads[i] = std::unique_ptr<base::Thread>(new base::Thread(name));
mThreads[i]->Start();
}
#ifndef GPU_ALGO_SERVER
mRequestHandler = std::unique_ptr<RequestHandler>(new IntelCPUAlgoServer(this));
#else
mRequestHandler = std::unique_ptr<RequestHandler>(new IntelGPUAlgoServer(this));
#endif
for (int32_t i = 1; i <= HANDLE_INDEX_MAX_VALUE; i++) {
mHandlesQueue.push(i);
}
}
IntelAlgoServer::~IntelAlgoServer() {
LOGIPC("@%s", __func__);
ia_log_deinit();
}
int32_t IntelAlgoServer::initialize(const camera_algorithm_callback_ops_t* callback_ops) {
LOGIPC("@%s, callback_ops:%p", __func__, callback_ops);
CheckError((!callback_ops), -EINVAL, "@%s, the callback_ops is nullptr", __func__);
mCallback = callback_ops;
return 0;
}
int32_t IntelAlgoServer::registerBuffer(int buffer_fd) {
LOGIPC("@%s, buffer_fd:%d", __func__, buffer_fd);
std::lock_guard<std::mutex> l(mRegisterBufMutex);
CheckError((mHandles.find(buffer_fd) != mHandles.end()), -EINVAL,
"@%s, Buffer already registered", __func__);
CheckError(mHandlesQueue.empty(), -EBADFD, "@%s, Failed to get buffer handle index", __func__);
struct stat sb;
int ret = fstat(buffer_fd, &sb);
CheckError((ret == -1), -EBADFD, "@%s, Failed to get buffer status", __func__);
void* addr = mmap(0, sb.st_size, PROT_WRITE, MAP_SHARED, buffer_fd, 0);
CheckError((!addr), -EBADFD, "@%s, Failed to map buffer", __func__);
int32_t handle = mHandlesQueue.front();
mHandlesQueue.pop();
mHandles[buffer_fd] = handle;
mShmInfoMap[handle].fd = buffer_fd;
mShmInfoMap[handle].addr = addr;
mShmInfoMap[handle].size = sb.st_size;
return handle;
}
int IntelAlgoServer::parseReqHeader(const uint8_t req_header[], uint32_t size) {
LOGIPC("@%s, size:%d", __func__, size);
CheckError(size < IPC_REQUEST_HEADER_USED_NUM || req_header[0] != IPC_MATCHING_KEY, -1,
"@%s, fails, req_header[0]:%d, size:%d", __func__, req_header[0], size);
return 0;
}
void IntelAlgoServer::returnCallback(uint32_t req_id, status_t status, int32_t buffer_handle) {
LOGIPC("@%s, req_id:%d:%s, status:%d", __func__, req_id,
IntelAlgoIpcCmdToString(static_cast<IPC_CMD>(req_id)), status);
(*mCallback->return_callback)(mCallback, req_id, (status == OK ? 0 : 1), buffer_handle);
}
status_t IntelAlgoServer::getShmInfo(const int32_t buffer_handle, ShmInfo* memInfo) {
CheckError(!memInfo, UNKNOWN_ERROR, "%s, memInfo is nullptr", __func__);
if (buffer_handle == -1) return OK;
CheckError(mShmInfoMap.find(buffer_handle) == mShmInfoMap.end(), UNKNOWN_ERROR,
"%s, Invalid buffer handle", __func__);
*memInfo = mShmInfoMap[buffer_handle];
LOGIPC("@%s, fd:%d, size:%zu, addr: %p", __func__, memInfo->fd, memInfo->size, memInfo->addr);
return OK;
}
void IntelAlgoServer::handleRequest(const MsgReq& msg) {
LOGIPC("@%s", __func__);
CheckError(!mRequestHandler, VOID_VALUE, "@%s, handler is null", __func__);
mRequestHandler->handleRequest(msg);
}
void IntelAlgoServer::request(uint32_t req_id, const uint8_t req_header[], uint32_t size,
int32_t buffer_handle) {
LOGIPC("@%s, size:%d, buffer_handle:%d", __func__, size, buffer_handle);
LOGIPC("@%s, req_id:%d:%s", __func__, req_id,
IntelAlgoIpcCmdToString(static_cast<IPC_CMD>(req_id)));
IPC_GROUP group = IntelAlgoIpcCmdToGroup(static_cast<IPC_CMD>(req_id));
LOGIPC("@%s, group:%d", __func__, group);
int ret = parseReqHeader(req_header, size);
if (ret != 0) {
returnCallback(req_id, UNKNOWN_ERROR, buffer_handle);
return;
}
MsgReq msg = {req_id, buffer_handle};
#ifndef GPU_ALGO_SERVER
int threadId = group;
#else
// GPU server thread id start from IPC_GROUP_GPU
int threadId = group - IPC_GROUP_GPU;
#endif
if (threadId >= 0 && threadId < kThreadNum) {
if (mThreads[threadId] && mThreads[threadId]->task_runner()) {
mThreads[threadId]->task_runner()->PostTask(FROM_HERE,
base::Bind(&IntelAlgoServer::handleRequest, base::Unretained(this), msg));
}
}
}
void IntelAlgoServer::deregisterBuffers(const int32_t buffer_handles[], uint32_t size) {
LOGIPC("@%s, size:%d", __func__, size);
std::lock_guard<std::mutex> l(mRegisterBufMutex);
for (uint32_t i = 0; i < size; i++) {
int32_t handle = buffer_handles[i];
if (mShmInfoMap.find(handle) == mShmInfoMap.end()) {
continue;
}
mHandles.erase(mShmInfoMap[handle].fd);
munmap(mShmInfoMap[handle].addr, mShmInfoMap[handle].size);
close(mShmInfoMap[handle].fd);
mShmInfoMap.erase(handle);
mHandlesQueue.push(handle);
}
}
static int32_t initialize(const camera_algorithm_callback_ops_t* callback_ops) {
LOGIPC("@%s, callback_ops:%p", __func__, callback_ops);
return IntelAlgoServer::getInstance()->initialize(callback_ops);
}
static int32_t registerBuffer(int32_t buffer_fd) {
LOGIPC("@%s, buffer_fd:%d", __func__, buffer_fd);
return IntelAlgoServer::getInstance()->registerBuffer(buffer_fd);
}
static void request(uint32_t req_id, const uint8_t req_header[], uint32_t size,
int32_t buffer_handle) {
LOGIPC("@%s, size:%d, buffer_handle:%d", __func__, size, buffer_handle);
IntelAlgoServer::getInstance()->request(req_id, req_header, size, buffer_handle);
}
static void deregisterBuffers(const int32_t buffer_handles[], uint32_t size) {
LOGIPC("@%s, size:%d", __func__, size);
return IntelAlgoServer::getInstance()->deregisterBuffers(buffer_handles, size);
}
extern "C" {
camera_algorithm_ops_t CAMERA_ALGORITHM_MODULE_INFO_SYM
__attribute__((__visibility__("default"))) = {.initialize = initialize,
.register_buffer = registerBuffer,
.request = request,
.deregister_buffers = deregisterBuffers};
}
__attribute__((constructor)) void initIntelAlgoServer() {
icamera::Log::setDebugLevel();
IntelAlgoServer::init();
}
__attribute__((destructor)) void deinitIntelAlgoServer() {
IntelAlgoServer::deInit();
}
} /* namespace icamera */