|
|
/*
|
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2020. All rights reserved.
|
|
|
* Description: Support private hwgraphics hidl interface
|
|
|
* Author: Hisilicon
|
|
|
* Created: 2016.11.29
|
|
|
*/
|
|
|
#define LOG_TAG "HwGalleryIapiComImpl"
|
|
|
#include "HwGalleryIapiComImpl.h"
|
|
|
|
|
|
#include <cstdlib>
|
|
|
#include <utils/Log.h>
|
|
|
#include <cutils/properties.h>
|
|
|
#include <securec.h>
|
|
|
#include <arm_neon.h>
|
|
|
#include <pthread.h>
|
|
|
#include <thread>
|
|
|
|
|
|
#include <vendor/huanglong/hardware/hwgraphics/1.0/types.h>
|
|
|
|
|
|
#include "uapi_win.h"
|
|
|
#include "uapi_system.h"
|
|
|
#include "uapi_video.h"
|
|
|
#include "uapi_rm.h"
|
|
|
#include "uapi_gfx2d.h"
|
|
|
#include "uapi_memory.h"
|
|
|
#include "drv_video_ext.h"
|
|
|
|
|
|
namespace android {
|
|
|
static pthread_mutex_t g_deInitMutex;
|
|
|
static pthread_mutex_t g_frameCountMutex;
|
|
|
|
|
|
const int VIDEO_BUFFER_NUM = 3;
|
|
|
const int TDE_TIMEOUT_MS = 500;
|
|
|
|
|
|
const int MAX_8_K = 8096;
|
|
|
|
|
|
const int SLEEP_DEQUEUE = 10;
|
|
|
|
|
|
const int BUFFER_NAME_LEN = 32;
|
|
|
|
|
|
// dequeue time out 5ms
|
|
|
const int DEQUEUE_TIMEOUT_MS = 5;
|
|
|
|
|
|
const int FRAME_ASPECT_WIDTH = 16;
|
|
|
const int FRAME_ASPECT_HEIGHT = 9;
|
|
|
|
|
|
// while framecount > 2 , start dequeue
|
|
|
const int FRAME_DEQUEUE_VALVE = 2;
|
|
|
|
|
|
// default fps is 24000
|
|
|
const int FRAME_DEFAULT_RATE = 24000;
|
|
|
|
|
|
const int HALF = 2;
|
|
|
|
|
|
const int TRIPLE = 3;
|
|
|
|
|
|
const int MSG_VO_DEQUEUE = 0x100;
|
|
|
|
|
|
const int DEFAULT_VO_FORMAT_TYPE = TYPE_NORMAL_2K;
|
|
|
|
|
|
const int ARR_COLUMN = 3;
|
|
|
|
|
|
const int WidthHeightTypeArr[][ARR_COLUMN] = {
|
|
|
{WIDTH_K, HEIGHT_K, TYPE_NORMAL_K},
|
|
|
{WIDTH_2K, HEIGHT_2K, TYPE_NORMAL_2K},
|
|
|
{WIDTH_S4K, HEIGHT_S4K, TYPE_NORMAL_S4K},
|
|
|
{WIDTH_S4K, HEIGHT_2K, TYPE_NORMAL_S4K}, // HSR、DLG高刷场景下,4K屏soc输出分辨率为3840*1080
|
|
|
{WIDTH_4K, HEIGHT_4K, TYPE_NORMAL_4K},
|
|
|
{WIDTH_8K, HEIGHT_8K, TYPE_NORMAL_8K}
|
|
|
};
|
|
|
|
|
|
void HwGalleryIapiComImpl::GetDisplayId()
|
|
|
{
|
|
|
char masterDisplay[PROPERTY_VALUE_MAX] = {0};
|
|
|
property_get("persist.vendor.display.master", masterDisplay, "0");
|
|
|
ALOGI("getDisplayId: id = %s, LINE: %d", masterDisplay, __LINE__);
|
|
|
if (strncmp(masterDisplay, "1", strlen("1")) == 0) {
|
|
|
m_displayId = UAPI_DISPLAY1;
|
|
|
} else {
|
|
|
m_displayId = UAPI_DISPLAY0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool HwGalleryIapiComImpl::Is8KFormat()
|
|
|
{
|
|
|
if (m_formatType == -1) {
|
|
|
uint32_t type = 0;
|
|
|
VoGetFormat(type);
|
|
|
}
|
|
|
ALOGI("In Is8KFormat , m_formatType is %d, m_frameRate is %d", m_formatType, m_frameRate);
|
|
|
// 8K120 or 8k100 need to convert to yuv422
|
|
|
if (m_formatType == TYPE_NORMAL_8K && (m_frameRate == FRAME_MILL_100 || m_frameRate == FRAME_MILL_120)) {
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::GetDefaultWindowAttr(uapi_win_attr &pstWinAttr) const
|
|
|
{
|
|
|
errno_t eok = memset_s(&pstWinAttr, sizeof(uapi_win_attr), 0x0, sizeof(uapi_win_attr));
|
|
|
if (eok != EOK) {
|
|
|
ALOGE("pstWinAttr memset failed");
|
|
|
return;
|
|
|
}
|
|
|
pstWinAttr.is_virtual = TD_FALSE;
|
|
|
pstWinAttr.priority = UAPI_WIN_WIN_PRIORITY_AUTO;
|
|
|
pstWinAttr.disp_id = m_displayId;
|
|
|
pstWinAttr.video_format = UAPI_FORMAT_ARGB8888;
|
|
|
pstWinAttr.asp_convert_mode = UAPI_WIN_ASPECT_CONVERT_FULL;
|
|
|
}
|
|
|
|
|
|
HwGalleryIapiComImpl::HwGalleryIapiComImpl()
|
|
|
: m_frameRate(FRAME_DEFAULT_RATE),
|
|
|
m_formatType(-1),
|
|
|
m_isRmRegister(false),
|
|
|
m_frameIndex(0),
|
|
|
m_frameCount(0),
|
|
|
m_bufCount(0),
|
|
|
m_isInitialized(false),
|
|
|
m_looper(nullptr),
|
|
|
m_rmService(0),
|
|
|
m_socWindow(TD_INVALID_HANDLE),
|
|
|
m_displayId(UAPI_DISPLAY0)
|
|
|
{
|
|
|
m_colorSpaceMap = {
|
|
|
{CS_SRGB, UAPI_COLOR_PRIMARY_BT709},
|
|
|
{CS_DCIP3, UAPI_COLOR_PRIMARY_DCI_P3},
|
|
|
{CS_ADOBE_RGB, UAPI_COLOR_PRIMARY_ADOBE_RGB},
|
|
|
{CS_REC2020, UAPI_COLOR_PRIMARY_BT2020},
|
|
|
};
|
|
|
}
|
|
|
|
|
|
HwGalleryIapiComImpl::~HwGalleryIapiComImpl()
|
|
|
{
|
|
|
m_looper.clear();
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoWindowSetting(td_u32 w __unused, td_u32 h __unused)
|
|
|
{
|
|
|
uapi_win_attr stWinAttr;
|
|
|
GetDefaultWindowAttr(stWinAttr);
|
|
|
|
|
|
int ret = uapi_win_create(&stWinAttr, &m_socWindow);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_create Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
m_isInitialized = false;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = uapi_win_set_video_source(m_socWindow, UAPI_VIDEO_SOURCE_GRAPHIC);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_set_video_source Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
// set zorder for interactive scene
|
|
|
ret = uapi_win_set_abs_zorder(m_socWindow, 255);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_set_abs_zorder Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
ALOGI(" :%s LINE %d | uapi_win_set_abs_zorder to 255", __FUNCTION__, __LINE__);
|
|
|
|
|
|
ret = uapi_win_set_enable(m_socWindow, TD_TRUE);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_set_enable Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
ret = uapi_win_destroy(m_socWindow);
|
|
|
if (ret == TD_SUCCESS) {
|
|
|
return ret;
|
|
|
} else {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_destroy(m_socWindow) Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
m_isInitialized = false;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::InitVideoBuffer(uint32_t width, uint32_t height)
|
|
|
{
|
|
|
m_videoBuffers.resize(VIDEO_BUFFER_NUM);
|
|
|
for (size_t i = 0; i < m_videoBuffers.size(); i++) {
|
|
|
int ret = CreateVideoScreen(m_videoBuffers[i], width, height);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR: createVideoBuffer num [%zu]", i);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
ALOGI("VideoBuffer: createVideoBuffer bufferID = %zu", i);
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::CreateVideoScreen(VideoBufferHandle &videoBufHandle, uint32_t width, uint32_t height)
|
|
|
{
|
|
|
uint32_t size;
|
|
|
// 8K & DISP1 not support rgb, convert to yuv422
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
// yuv422sp pixel buffer size. y = width * height, u = y/2, v = y/2
|
|
|
size = width * height * HALF;
|
|
|
} else {
|
|
|
// yuv420sp pixel buffer size. y = width * height, u = y/4, v = y/4
|
|
|
size = width * height * TRIPLE / HALF;
|
|
|
}
|
|
|
char implClassStr[] = "HwgraphicsIapiComImpl";
|
|
|
videoBufHandle.handle = uapi_mem_new(implClassStr, BUFFER_NAME_LEN,
|
|
|
size, TD_TRUE);
|
|
|
if (videoBufHandle.handle < 0) {
|
|
|
ALOGE("uapi_mem_new Hwgraphics video buffer failed!");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
videoBufHandle.width = width;
|
|
|
videoBufHandle.height = height;
|
|
|
videoBufHandle.stride = width;
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::DestroyVideoScreen()
|
|
|
{
|
|
|
for (int i = 0; i < NUMOUTPUTBUFFER; i++) {
|
|
|
if (m_videoBuffers[i].handle == TD_INVALID_HANDLE) {
|
|
|
continue;
|
|
|
}
|
|
|
td_s32 ret = uapi_mem_delete(m_videoBuffers[i].handle);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR: uapi_mem_delete NUM[%d] destroyVideoScreen", i);
|
|
|
}
|
|
|
m_videoBuffers[i].handle = TD_INVALID_HANDLE;
|
|
|
ALOGI("VideoBuffer: destroyVideoBuffer bufferID = %d", i);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int DestoryHandlerAndExit(td_handle gfxHandle, int ret)
|
|
|
{
|
|
|
if (gfxHandle > 0) {
|
|
|
uapi_gfx2d_destroy(gfxHandle);
|
|
|
}
|
|
|
uapi_gfx2d_close(UAPI_GFX2D_DEV_ID_0);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::ConvertARGBToYUV420SP(const private_handle_t& srcBufHandle,
|
|
|
const VideoBufferHandle &videoBufHandle)
|
|
|
{
|
|
|
if (videoBufHandle.stride > MAX_8_K || videoBufHandle.width > MAX_8_K || videoBufHandle.height > MAX_8_K) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
uapi_gfx2d_list surfaceList;
|
|
|
uapi_gfx2d_surface srcSurface;
|
|
|
uapi_gfx2d_surface dstSurface;
|
|
|
uapi_gfx2d_attr attr;
|
|
|
if (memset_s(&srcSurface, sizeof(uapi_gfx2d_surface), 0, sizeof(uapi_gfx2d_surface)) != EOK ||
|
|
|
memset_s(&dstSurface, sizeof(uapi_gfx2d_surface), 0, sizeof(uapi_gfx2d_surface)) != EOK ||
|
|
|
memset_s(&attr, sizeof(uapi_gfx2d_surface), 0, sizeof(uapi_gfx2d_surface)) != EOK) {
|
|
|
ALOGE("memset surface failed");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
td_s32 ret = uapi_gfx2d_open(UAPI_GFX2D_DEV_ID_0);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("failed to open gfx2d dev");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
td_handle gfxHandle = uapi_gfx2d_create(UAPI_GFX2D_DEV_ID_0);
|
|
|
if (gfxHandle < 0) {
|
|
|
ALOGE("uapi_gfx2d_create failed");
|
|
|
return DestoryHandlerAndExit(gfxHandle, ret);
|
|
|
}
|
|
|
|
|
|
TdeCreateSrcSurface(srcSurface, srcBufHandle, attr);
|
|
|
TdeCreateDstSurface(dstSurface, videoBufHandle, attr);
|
|
|
|
|
|
surfaceList.src_surface_cnt = 1;
|
|
|
surfaceList.src_surfaces = &srcSurface;
|
|
|
surfaceList.dst_surface = &dstSurface;
|
|
|
surfaceList.ops_mode = UAPI_GFX2D_OPS_BIT_BLIT;
|
|
|
ret = uapi_gfx2d_bitblit(gfxHandle, &surfaceList);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("uapi_gfx2d_bitblit failed, ret = 0x%x", ret);
|
|
|
return DestoryHandlerAndExit(gfxHandle, ret);
|
|
|
}
|
|
|
|
|
|
ret = uapi_gfx2d_submit(gfxHandle, TD_TRUE, TDE_TIMEOUT_MS);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("uapi_gfx2d_submit failed, ret = 0x%x", ret);
|
|
|
return DestoryHandlerAndExit(gfxHandle, ret);
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
|
|
|
void HwGalleryIapiComImpl::TdeCreateSrcSurface(uapi_gfx2d_surface &srcSurface,
|
|
|
const private_handle_t &srcBufHandle, uapi_gfx2d_attr &attr) const
|
|
|
{
|
|
|
srcSurface.width = srcBufHandle.width;
|
|
|
srcSurface.height = srcBufHandle.height;
|
|
|
srcSurface.stride[0] = srcBufHandle.bytes_stride;
|
|
|
if (srcBufHandle.bytes_stride > 0 && srcBufHandle.height > 0 &&
|
|
|
(srcBufHandle.bytes_stride * srcBufHandle.height) > 0 &&
|
|
|
((ULONG_MAX / srcBufHandle.bytes_stride)) > (uint32_t)srcBufHandle.height) {
|
|
|
srcSurface.size[0] = srcBufHandle.bytes_stride * srcBufHandle.height;
|
|
|
}
|
|
|
srcSurface.mem_handle[0].mem_handle = srcBufHandle.fd;
|
|
|
srcSurface.mem_handle[0].addr_offset = 0;
|
|
|
srcSurface.format = UAPI_GFX2D_FMT_ARGB8888;
|
|
|
srcSurface.xdr_mode = UAPI_GFX2D_HDR_SDR;
|
|
|
srcSurface.color_space = UAPI_GFX2D_COLOR_SPACE_BT709;
|
|
|
srcSurface.compress_mode = UAPI_GFX2D_COMPRESS_NONE;
|
|
|
srcSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_MEM;
|
|
|
srcSurface.in_rect.x = 0;
|
|
|
srcSurface.in_rect.y = 0;
|
|
|
srcSurface.in_rect.width = srcBufHandle.bytes_stride;
|
|
|
srcSurface.in_rect.height = srcBufHandle.height;
|
|
|
srcSurface.attr = &attr;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::TdeCreateDstSurface(uapi_gfx2d_surface &dstSurface,
|
|
|
const VideoBufferHandle &videoBufHandle, uapi_gfx2d_attr &attr)
|
|
|
{
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
dstSurface.stride[0] = videoBufHandle.stride * HALF;
|
|
|
if (videoBufHandle.stride > 0 && videoBufHandle.height > 0 &&
|
|
|
((uint32_t)(ULONG_MAX / videoBufHandle.stride)) > (videoBufHandle.height * HALF)) {
|
|
|
dstSurface.size[0] = videoBufHandle.stride * videoBufHandle.height * HALF;
|
|
|
}
|
|
|
dstSurface.size[1] = dstSurface.size[0];
|
|
|
dstSurface.format = UAPI_GFX2D_FMT_YVYU422;
|
|
|
dstSurface.out_rect.width = videoBufHandle.stride * HALF;
|
|
|
// yuv422 pixel y height and uv height
|
|
|
dstSurface.out_rect.height = videoBufHandle.height;
|
|
|
} else {
|
|
|
dstSurface.stride[0] = videoBufHandle.stride;
|
|
|
if (videoBufHandle.stride > 0 && videoBufHandle.height > 0 &&
|
|
|
((uint32_t)(ULONG_MAX / videoBufHandle.stride)) > videoBufHandle.height) {
|
|
|
dstSurface.size[0] = videoBufHandle.stride * videoBufHandle.height;
|
|
|
}
|
|
|
dstSurface.size[1] = dstSurface.size[0] / HALF;
|
|
|
dstSurface.format = UAPI_GFX2D_FMT_SEMIPLANAR420UV;
|
|
|
dstSurface.out_rect.width = videoBufHandle.stride;
|
|
|
// yuv420 pixel y height and uv height
|
|
|
dstSurface.out_rect.height = videoBufHandle.height * TRIPLE / HALF;
|
|
|
}
|
|
|
dstSurface.width = videoBufHandle.width;
|
|
|
dstSurface.height = videoBufHandle.height;
|
|
|
dstSurface.stride[1] = videoBufHandle.stride;
|
|
|
dstSurface.mem_handle[0].mem_handle = videoBufHandle.handle;
|
|
|
dstSurface.mem_handle[0].addr_offset = 0;
|
|
|
dstSurface.mem_handle[1].mem_handle = videoBufHandle.handle;
|
|
|
dstSurface.mem_handle[1].addr_offset = dstSurface.size[0];
|
|
|
dstSurface.xdr_mode = UAPI_GFX2D_HDR_SDR;
|
|
|
dstSurface.color_space = UAPI_GFX2D_COLOR_SPACE_BT709;
|
|
|
dstSurface.compress_mode = UAPI_GFX2D_COMPRESS_NONE;
|
|
|
dstSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_MEM;
|
|
|
dstSurface.out_rect.x = 0;
|
|
|
dstSurface.out_rect.y = 0;
|
|
|
dstSurface.attr = &attr;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoInit(uint32_t w, uint32_t h)
|
|
|
{
|
|
|
int ret = uapi_disp_open(m_displayId);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_disp_open Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
ret = VoWindowSetting(w, h);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | VoWindowSetting Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
ret = uapi_disp_close(m_displayId);
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::Init(uint32_t w, uint32_t h)
|
|
|
{
|
|
|
pthread_mutex_lock(&g_deInitMutex);
|
|
|
|
|
|
if (m_isInitialized) {
|
|
|
ALOGI("vo has been Initialized, return");
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int ret;
|
|
|
#ifndef SUPPORT_ARGB
|
|
|
ret = InitVideoBuffer(w, h);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("init video buffer failed");
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
#else
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
ret = InitVideoBuffer(w, h);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("init video buffer failed");
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
m_frameIndex = 0;
|
|
|
GetDisplayId();
|
|
|
ret = uapi_disp_init();
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_disp_init Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return ret;
|
|
|
}
|
|
|
ret = VoInit(w, h);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
m_isInitialized = true;
|
|
|
pthread_mutex_lock(&g_frameCountMutex);
|
|
|
m_frameCount = 0;
|
|
|
pthread_mutex_unlock(&g_frameCountMutex);
|
|
|
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoDeinit()
|
|
|
{
|
|
|
pthread_mutex_lock(&g_deInitMutex);
|
|
|
if (!m_isInitialized || m_socWindow == TD_INVALID_HANDLE) {
|
|
|
ALOGE("ERR :%s LINE %d: vo has not been initialized or m_socWindow is invalid", __FUNCTION__, __LINE__);
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
m_isInitialized = false;
|
|
|
ALOGI("%s LINE %d | =================vo_deinit========setdisable first========== ", __FUNCTION__, __LINE__);
|
|
|
int ret = uapi_win_set_enable(m_socWindow, TD_FALSE);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | UAPI_VO_SetWindowEnable(m_socWindow) Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
|
|
|
ret = uapi_win_reset(m_socWindow, UAPI_WIN_RESET_MODE_BLACK);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_reset() Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
uapi_video_frame_info stDqueframe;
|
|
|
if (memset_s(&stDqueframe, sizeof(uapi_video_frame_info), 0, sizeof(uapi_video_frame_info)) != EOK) {
|
|
|
ALOGE("stDqueframe memset failed");
|
|
|
}
|
|
|
uapi_win_dequeue_frame(m_socWindow, &stDqueframe, DEQUEUE_TIMEOUT_MS);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_dequeue_frame() Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
|
|
|
ret = uapi_win_destroy(m_socWindow);
|
|
|
if (ret == TD_SUCCESS) {
|
|
|
m_socWindow = TD_NULL;
|
|
|
int err = uapi_disp_close(m_displayId);
|
|
|
if (err == -1) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_disp_close Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
} else {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_win_destroy(m_socWindow) Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
m_socWindow = TD_INVALID_HANDLE;
|
|
|
#ifndef SUPPORT_ARGB
|
|
|
DestroyVideoScreen();
|
|
|
#else
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
DestroyVideoScreen();
|
|
|
}
|
|
|
#endif
|
|
|
m_formatType = -1;
|
|
|
pthread_mutex_unlock(&g_deInitMutex);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoGetFormat(td_u32 &type)
|
|
|
{
|
|
|
if (m_formatType != -1) {
|
|
|
type = static_cast<td_u32>(m_formatType);
|
|
|
ALOGI("VoGetFormat has been invoked, Screen resolution type is %d", m_formatType);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int ret = TD_SUCCESS;
|
|
|
uapi_disp_timing data = {};
|
|
|
GetDisplayId();
|
|
|
ret = uapi_disp_init();
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | uapi_disp_init Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
ret = uapi_disp_get_custom_timing(m_displayId, &data);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("uapi_disp_get_custom_timing fail(disp:%d, ret=0x%x)", m_displayId, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
int width = static_cast<int>(data.hact);
|
|
|
int height = static_cast<int>(data.vact);
|
|
|
if (data.vert_freq != 0) {
|
|
|
m_frameRate = static_cast<int>(data.vert_freq);
|
|
|
}
|
|
|
ALOGI("GetDisplayMode display Info: width(%d), height(%d), frameRate(%d)", width, height, m_frameRate);
|
|
|
|
|
|
type = DEFAULT_VO_FORMAT_TYPE;
|
|
|
const size_t row = sizeof(WidthHeightTypeArr) / sizeof(WidthHeightTypeArr[0]);
|
|
|
for (size_t i = 0; i < row; i = i + 1) {
|
|
|
if (width == WidthHeightTypeArr[i][0] && height == WidthHeightTypeArr[i][1]) {
|
|
|
type = WidthHeightTypeArr[i][ARR_COLUMN - 1];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_formatType = static_cast<int>(type);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::VoGetWindowHandle(td_u32 &windowHandle)
|
|
|
{
|
|
|
windowHandle = m_socWindow;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::VoDoDequeue()
|
|
|
{
|
|
|
int ret = 0;
|
|
|
uapi_video_frame_info stDqueframe;
|
|
|
do {
|
|
|
if (!m_isInitialized) {
|
|
|
ALOGW("[%s: %d], vo has not been initialized", __FUNCTION__, __LINE__);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
struct timespec tm;
|
|
|
tm.tv_sec = 0;
|
|
|
// 10 ms
|
|
|
tm.tv_nsec = SLEEP_DEQUEUE * MILLLISECONDS_TO_NANOSECONDS;
|
|
|
nanosleep(&tm, nullptr);
|
|
|
if (memset_s(&stDqueframe, sizeof(uapi_video_frame_info), 0, sizeof(uapi_video_frame_info)) != EOK) {
|
|
|
ALOGE("stDqueframe memset failed");
|
|
|
}
|
|
|
|
|
|
ret = uapi_win_dequeue_frame(m_socWindow, &stDqueframe, DEQUEUE_TIMEOUT_MS);
|
|
|
if (ret == TD_SUCCESS) {
|
|
|
ALOGI("uapi_win_dequeue_frame success: fd = %llx\n", stDqueframe.frame_addr[0].start_addr);
|
|
|
} else {
|
|
|
ALOGE("uapi_win_dequeue_frame failed, Ret = %d\n", ret);
|
|
|
}
|
|
|
} while (ret != TD_SUCCESS);
|
|
|
pthread_mutex_lock(&g_frameCountMutex);
|
|
|
m_frameCount--;
|
|
|
ALOGI("uapi_win_dequeue_frame success, m_frameCount = %d", m_frameCount);
|
|
|
pthread_mutex_unlock(&g_frameCountMutex);
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoDoFramexSync(void)
|
|
|
{
|
|
|
// wait for dequeue in worker thread
|
|
|
while (m_frameCount >= NUMOUTPUTBUFFER) {
|
|
|
struct timespec tm;
|
|
|
tm.tv_sec = 0;
|
|
|
tm.tv_nsec = 1 * MILLLISECONDS_TO_NANOSECONDS;
|
|
|
nanosleep(&tm, nullptr);
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::VoDoFramex(const private_handle_t& handle, const ExtendFrameInfo &extendInfo)
|
|
|
{
|
|
|
int ret;
|
|
|
#ifndef SUPPORT_ARGB
|
|
|
ret = ConvertARGBToYUV420SP(handle, m_videoBuffers[m_bufCount]);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("convert ARGB8888 to yuv420sp failed");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
#else
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
ret = ConvertARGBToYUV420SP(handle, m_videoBuffers[m_bufCount]);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("convert ARGB8888 to yuv422sp failed");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
uapi_video_frame_info stFrame;
|
|
|
if (memset_s(&stFrame, sizeof(uapi_video_frame_info), 0x0, sizeof(uapi_video_frame_info)) != EOK) {
|
|
|
ALOGE("vo_do_dramex stFrame memset failed");
|
|
|
}
|
|
|
|
|
|
VoSetFrameInfo(handle, stFrame, extendInfo);
|
|
|
|
|
|
ret = uapi_win_queue_frame(m_socWindow, &stFrame, nullptr);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("uapi_win_queue_frame(0x%llx) failed, ret = 0x%x", stFrame.frame_addr[0].start_addr, ret);
|
|
|
ALOGE("ERR :%s LINE %d | __EER__ vo_do_frame Failed ret(0x%x)", __FUNCTION__, __LINE__, ret);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
pthread_mutex_lock(&g_frameCountMutex);
|
|
|
m_frameCount++;
|
|
|
ALOGI("uapi_win_queue_frame(0x%llx) success, m_frameCount = %d", stFrame.frame_addr[0].start_addr, m_frameCount);
|
|
|
if (m_frameCount >= FRAME_DEQUEUE_VALVE) {
|
|
|
ALOGI("[%s:%d] call WorkQueue to DeQueueFrame, m_frameCount = %d", __FUNCTION__, __LINE__, m_frameCount);
|
|
|
SendDequeueMessage();
|
|
|
}
|
|
|
m_bufCount++;
|
|
|
m_bufCount %= NUMOUTPUTBUFFER;
|
|
|
pthread_mutex_unlock(&g_frameCountMutex);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::VoSetFrameInfo(const private_handle_t &handle, uapi_video_frame_info &stFrame,
|
|
|
const ExtendFrameInfo &extendInfo)
|
|
|
{
|
|
|
stFrame.frame_index = m_frameIndex++;
|
|
|
ALOGD("Debug :%s LINE %d | m_frameIndex is %d", __FUNCTION__, __LINE__, stFrame.frame_index);
|
|
|
stFrame.bit_depth = UAPI_PIXEL_BIT_DEPTH_8BIT;
|
|
|
stFrame.hdr_type = UAPI_HDR_TYPE_SDR;
|
|
|
|
|
|
// frame color description
|
|
|
stFrame.color_description.color_space = UAPI_COLOR_CS_YUV;
|
|
|
stFrame.color_description.quantify_range = UAPI_COLOR_FULL_RANGE;
|
|
|
if (!static_cast<bool>(property_get_bool("ro.prop.gallery.wcg.disable", false)) &&
|
|
|
m_colorSpaceMap.find(extendInfo.colorSpace) != m_colorSpaceMap.end()) {
|
|
|
ALOGD("[%s:%d], colorSpace = %d", __FUNCTION__, __LINE__, extendInfo.colorSpace);
|
|
|
stFrame.color_description.color_primary = m_colorSpaceMap[extendInfo.colorSpace];
|
|
|
} else {
|
|
|
ALOGW("[%s:%d], unknow colorSpace, use default SRGB", __FUNCTION__, __LINE__);
|
|
|
stFrame.color_description.color_primary = UAPI_COLOR_PRIMARY_BT709;
|
|
|
}
|
|
|
stFrame.color_description.transfer_type = UAPI_COLOR_TRANSFER_TYPE_GAMMA_SDR;
|
|
|
stFrame.color_description.matrix_coef = UAPI_COLOR_MATRIX_COEFFS_BT709;
|
|
|
stFrame.video_format = UAPI_FORMAT_YUV_SEMIPLANAR_420_VU;
|
|
|
stFrame.scan_type = UAPI_VIDEO_SCAN_TYPE_PROGRESSIVE;
|
|
|
stFrame.field_mode = UAPI_VIDEO_FIELD_ALL;
|
|
|
stFrame.frame_packing_type = UAPI_FRAME_PACKING_TYPE_2D;
|
|
|
stFrame.source_type = UAPI_VIDEO_SOURCE_GRAPHIC;
|
|
|
|
|
|
#ifndef SUPPORT_ARGB
|
|
|
stFrame.frame_addr[0].start_addr = m_videoBuffers[m_bufCount].handle;
|
|
|
stFrame.frame_addr[0].y_offset = 0;
|
|
|
stFrame.frame_addr[0].stride_y = m_videoBuffers[m_bufCount].stride;
|
|
|
stFrame.frame_addr[0].c_offset = m_videoBuffers[m_bufCount].width * m_videoBuffers[m_bufCount].height;
|
|
|
stFrame.frame_addr[0].stride_c = m_videoBuffers[m_bufCount].stride;
|
|
|
#else
|
|
|
if (Is8KFormat() || (m_displayId == UAPI_DISPLAY1)) {
|
|
|
stFrame.video_format = UAPI_FORMAT_YUV_PACKAGE_UYVY;
|
|
|
stFrame.frame_addr[0].start_addr = m_videoBuffers[m_bufCount].handle;
|
|
|
stFrame.frame_addr[0].y_offset = 0;
|
|
|
stFrame.frame_addr[0].stride_y = m_videoBuffers[m_bufCount].stride * HALF;
|
|
|
stFrame.frame_addr[0].c_offset = 0;
|
|
|
stFrame.frame_addr[0].stride_c = m_videoBuffers[m_bufCount].stride * HALF;
|
|
|
} else {
|
|
|
stFrame.color_description.color_space = UAPI_COLOR_CS_RGB;
|
|
|
stFrame.video_format = UAPI_FORMAT_ARGB8888;
|
|
|
stFrame.frame_addr[0].start_addr = handle.fd;
|
|
|
stFrame.frame_addr[0].y_offset = 0;
|
|
|
stFrame.frame_addr[0].stride_y = handle.bytes_stride;
|
|
|
}
|
|
|
#endif
|
|
|
DealVideoFrameInfo(handle, stFrame);
|
|
|
}
|
|
|
void HwGalleryIapiComImpl::DealVideoFrameInfo(const private_handle_t &handle, uapi_video_frame_info &stFrame) const
|
|
|
{
|
|
|
stFrame.top_field_first = TD_TRUE;
|
|
|
stFrame.frame_rate = static_cast<td_u32>(m_frameRate);
|
|
|
stFrame.aspect_width = FRAME_ASPECT_WIDTH;
|
|
|
stFrame.aspect_height = FRAME_ASPECT_HEIGHT;
|
|
|
stFrame.decode_width = handle.width;
|
|
|
stFrame.decode_height = handle.height;
|
|
|
stFrame.display_width = handle.width;
|
|
|
stFrame.display_height = handle.height;
|
|
|
stFrame.display_center_x = handle.width / HALF;
|
|
|
stFrame.display_center_y = handle.height / HALF;
|
|
|
|
|
|
#ifdef SUPPORT_HDR_POLICY
|
|
|
ext_drv_hdr_policy_param info;
|
|
|
info.valid = TD_TRUE;
|
|
|
info.hdr_type = (ext_drv_hdr_type)UAPI_HDR_TYPE_SDR;
|
|
|
info.color_desc.color_primary = (ext_drv_color_primary)stFrame.color_description.color_primary;
|
|
|
info.color_desc.color_space = (ext_drv_color_space)stFrame.color_description.color_space;
|
|
|
info.color_desc.quantify_range = (ext_drv_color_quantify_range)stFrame.color_description.quantify_range;
|
|
|
info.color_desc.transfer_type = (ext_drv_color_transfer_curve)stFrame.color_description.transfer_type;
|
|
|
info.color_desc.matrix_coef = (ext_drv_color_matrix_coeffs)stFrame.color_description.matrix_coef;
|
|
|
soc_mod_id mod_id = SOC_ID_WIN;
|
|
|
td_s32 ret = uapi_sys_init();
|
|
|
ALOGI("INFO :%s LINE %d |call uapi_sys_init. ret is 0x%x!\n", __FUNCTION__, __LINE__, ret);
|
|
|
if (ret == TD_SUCCESS && m_socWindow != TD_INVALID_HANDLE) {
|
|
|
ret = ext_mpi_sys_policy_set_hdr_param(mod_id, m_socWindow, &info);
|
|
|
ALOGI("INFO :%s LINE %d | call ext_mpi_sys_policy_set_hdr_param ret is 0x%x!\n", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
uapi_sys_deinit();
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
td_s32 SmpRmEventCallback(const td_void* pClient, uapi_rm_event enEvent, td_u32 u32EventPara __unused)
|
|
|
{
|
|
|
(void)pClient;
|
|
|
if (enEvent == UAPI_RM_EVENT_WIN_LACK) {
|
|
|
ALOGI("INFO :%s LINE %d | UAPI_RM_EVENT_WIN_LACK!\n", __FUNCTION__, __LINE__);
|
|
|
HwGalleryIapiAdapter::GetInstance()->VoDeinit();
|
|
|
} else if (enEvent == UAPI_RM_EVENT_WIN_CREATED) {
|
|
|
ALOGI("INFO :%s LINE %d | UAPI_RM_EVENT_WIN_CREATED!\n", __FUNCTION__, __LINE__);
|
|
|
} else if (enEvent == UAPI_RM_EVENT_WIN_DESTROYED) {
|
|
|
ALOGI("INFO :%s LINE %d | UAPI_RM_EVENT_WIN_DESTROYED!\n", __FUNCTION__, __LINE__);
|
|
|
} else {
|
|
|
ALOGI("INFO :%s LINE %d | UAPI_RM_EVENT_WIN_BUTT!\n", __FUNCTION__, __LINE__);
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::RMRegister(void)
|
|
|
{
|
|
|
if (m_isRmRegister) {
|
|
|
ALOGI("RM has been registered, return");
|
|
|
return EXT_OK;
|
|
|
}
|
|
|
|
|
|
td_s32 ret = uapi_rm_init();
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | UAPI_RM_Init Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = uapi_rm_register_callback(&m_rmService, (uapi_rm_event_cb_fn)SmpRmEventCallback,
|
|
|
static_cast<td_u32>(UAPI_RM_EVENT_WIN_LACK) |
|
|
|
static_cast<td_u32>(UAPI_RM_EVENT_WIN_CREATED) |
|
|
|
static_cast<td_u32>(UAPI_RM_EVENT_WIN_DESTROYED));
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | UAPI_RM_RegisterCallback Failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
uapi_rm_deinit();
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ALOGI("INFO :%s LINE %d | UAPI_RM_RegisterCallback ok\n", __FUNCTION__, __LINE__);
|
|
|
m_isRmRegister = true;
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::RMUnRegister(void)
|
|
|
{
|
|
|
if (!m_isRmRegister) {
|
|
|
ALOGI("RM has been unregister, return");
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ret = uapi_rm_unregister_callback(&m_rmService, (uapi_rm_event_cb_fn)SmpRmEventCallback);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("ERR :%s LINE %d | UAPI_RM_unRegisterCallback failed ret(%x)", __FUNCTION__, __LINE__, ret);
|
|
|
}
|
|
|
|
|
|
uapi_rm_deinit();
|
|
|
|
|
|
m_isRmRegister = false;
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::RMAcquireResource(void)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
if (!m_isRmRegister) {
|
|
|
ALOGW("RM has not been register before, register now");
|
|
|
ret = RMRegister();
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
ALOGE("RM register failed, ret = 0x%x", ret);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ret = uapi_rm_request_resource(UAPI_RM_RESOURCE_TYPE_ALL);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return ret;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
|
|
|
void HwGalleryIapiComImpl::DequeueThreadFun()
|
|
|
{
|
|
|
m_looper = new android::Looper(true);
|
|
|
if (m_looper == nullptr) {
|
|
|
ALOGE("ERR :%s LINE %d | m_looper is nullptr", __FUNCTION__, __LINE__);
|
|
|
return;
|
|
|
}
|
|
|
int result;
|
|
|
while (true) {
|
|
|
result = m_looper->pollOnce(SECONDS_TO_MILLLISECONDS);
|
|
|
if (result == android::Looper::POLL_ERROR) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int HwGalleryIapiComImpl::CreateDequeueThread()
|
|
|
{
|
|
|
if (m_looper.get() != nullptr) {
|
|
|
ALOGE("ERR :%s LINE %d | CreateDequeueThread is failed", __FUNCTION__, __LINE__);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
std::thread thread(&HwGalleryIapiComImpl::DequeueThreadFun, this);
|
|
|
thread.detach();
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::DequeueMessageHandler::handleMessage(const android::Message& message)
|
|
|
{
|
|
|
if (message.what == MSG_VO_DEQUEUE) {
|
|
|
HwGalleryIapiComImpl* iapiComImpl =
|
|
|
static_cast<HwGalleryIapiComImpl*>(HwGalleryIapiComImpl::GetInstance());
|
|
|
iapiComImpl->VoDoDequeue();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void HwGalleryIapiComImpl::SendDequeueMessage() const
|
|
|
{
|
|
|
android::Message msg;
|
|
|
msg.what = MSG_VO_DEQUEUE;
|
|
|
android::sp<HwGalleryIapiComImpl::DequeueMessageHandler> handler = new DequeueMessageHandler();
|
|
|
|
|
|
if (m_looper != nullptr) {
|
|
|
m_looper->sendMessage(handler, msg);
|
|
|
}
|
|
|
}
|
|
|
}
|