/* * 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 #include #include #include #include #include #include #include #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(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(data.hact); int height = static_cast(data.vact); if (data.vert_freq != 0) { m_frameRate = static_cast(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(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(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(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(UAPI_RM_EVENT_WIN_LACK) | static_cast(UAPI_RM_EVENT_WIN_CREATED) | static_cast(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::GetInstance()); iapiComImpl->VoDoDequeue(); } } void HwGalleryIapiComImpl::SendDequeueMessage() const { android::Message msg; msg.what = MSG_VO_DEQUEUE; android::sp handler = new DequeueMessageHandler(); if (m_looper != nullptr) { m_looper->sendMessage(handler, msg); } } }