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.

825 lines
30 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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);
}
}
}