/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2019-2019. All rights reserved. * Description: support private media overlay solution * Author: Hisilicon * Created: 2019.12.30 */ #include "TvGraphics.h" #include #include #include namespace V1_0= vendor::huanglong::hardware::hwgraphics::V1_0; namespace V1_2= vendor::huanglong::hardware::hwgraphics::V1_2; using V1_0::CaptureType; using V1_0::HwRect; using V1_0::HwLayer; using namespace android; namespace { const int SUCCESS = 0; const int ERROR = -1; const int INVALID_FENCE_FD = -1; const int CAPTURE_MODE_VIDEO = 0; const int CAPTURE_MODE_VIDEO_GRAPHIC = 2; const int SET_OVERLAY_FAIL = -1; android::sp g_tvGraphics = nullptr; android::sp g_tvGraphics_1_2 = nullptr; android::sp g_hwListener = nullptr; } int Init() { g_tvGraphics = V1_0::IGraphics::getService(); if (g_tvGraphics == nullptr) { ALOGE("Can't find TVGraphics Service"); return ERROR; } else { // hwgraphic will close all overlay CloseOverlay(-1); auto castResult = V1_2::IGraphics::castFrom(g_tvGraphics); if (castResult.isOk()) { g_tvGraphics_1_2 = castResult; if (g_tvGraphics_1_2 != nullptr) { ALOGI("tvGraphics_1_2 will been used"); } } } return SUCCESS; } int PresentOverlay(uint64_t display, int32_t seq, buffer_handle_t handle, bool visible) { if (g_tvGraphics == nullptr) { ALOGE("PresentOverlay failed: Can't find TVGraphics Service"); return ERROR; } HwLayer layer = {display, seq, handle}; int releaseFenceFd = INVALID_FENCE_FD; // present overlay auto ret = g_tvGraphics->PresentOverlay(layer, visible, [&releaseFenceFd](const auto& ret, const auto& fenceHandle) mutable { if (ret != android::NO_ERROR || !fenceHandle) { return; } auto fenceNativeHandle = fenceHandle.getNativeHandle(); if (!fenceNativeHandle || fenceNativeHandle->numFds != 1) { ALOGE("invalid fence handle"); return; } int fenceFd = fenceNativeHandle->data[0]; if (fenceFd >= 0) { releaseFenceFd = dup(fenceFd); if (releaseFenceFd < 0) { ALOGE("No resource during dup fenceFd"); releaseFenceFd = INVALID_FENCE_FD; return; } } }); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); return INVALID_FENCE_FD; } return releaseFenceFd; } int SetOverlayPosition(int32_t seq, int32_t left, int32_t top, int32_t right, int32_t bottom) { if (g_tvGraphics == nullptr) { ALOGE("SetOverlayPosition failed: Can't find TVGraphics Service"); return SET_OVERLAY_FAIL; } HwRect displayFrame = { left, top, right, bottom }; auto ret = g_tvGraphics->SetOverlayPosition(seq, displayFrame); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } return ret; } int SetOverlayCrop(int32_t seq, int32_t left, int32_t top, int32_t right, int32_t bottom) { if (g_tvGraphics == nullptr) { ALOGE("SetOverlayCrop failed: Can't find TVGraphics Service"); return SET_OVERLAY_FAIL; } HwRect sourceCrop = { left, top, right, bottom }; auto ret = g_tvGraphics->SetOverlayCrop(seq, sourceCrop); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } return ret; } int SetOverlayTransform(int32_t seq, int32_t transform) { if (g_tvGraphics == nullptr) { ALOGE("SetOverlayTransform failed: Can't find TVGraphics Service"); return SET_OVERLAY_FAIL; } auto ret = g_tvGraphics->SetOverlayTransform(seq, transform); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } return ret; } int SetOverlayZOrder(int32_t seq, int32_t zOrder) { if (g_tvGraphics_1_2 == nullptr) { ALOGE("SetOverlayZOrder failed: Can't find TVGraphics Service"); return SET_OVERLAY_FAIL; } auto ret = g_tvGraphics_1_2->SetOverlayZOrder(seq, zOrder); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } return ret; } void SetOverlayDataSpace(int32_t seq, int32_t dataSpace) { if (g_tvGraphics_1_2 != nullptr) { auto ret = g_tvGraphics_1_2->SetOverlayDataSpace(seq, dataSpace); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); return; } } else { ALOGE("only Graphics_1_2 can support set overlay layer dataSpace"); } } void CloseOverlay(int32_t seq) { if (g_tvGraphics == nullptr) { ALOGE("CloseOverlay failed: Can't find TVGraphics Service"); return; } auto ret = g_tvGraphics->CloseOverlay(seq); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } } int InitCast(uint64_t display, uint32_t format, uint32_t width, uint32_t height) { if (g_tvGraphics_1_2 == nullptr) { ALOGE("InitCast failed: Can't find TVGraphics Service"); return ERROR; } return g_tvGraphics_1_2->InitCast(display, format, width, height); } int CastFrame(int32_t castHandle, const buffer_handle_t& rawHandle, const buffer_handle_t& fence, int& acqurieFence) { if (g_tvGraphics_1_2 == nullptr) { ALOGE("CastFrame failed: Can't find TVGraphics Service"); return ERROR; } int result = -1; auto ret = g_tvGraphics_1_2->CastFrame(castHandle, rawHandle, fence, [&result, &acqurieFence](const auto& ret, const auto& fenceHandle) mutable { result = ret; if (ret != SUCCESS || !fenceHandle) { return; } auto handle = fenceHandle.getNativeHandle(); if (!handle || handle->numFds != 1) { ALOGE("invalid fence handle"); return; } int fenceFd = handle->data[0]; if (fenceFd >= 0) { acqurieFence = dup(fenceFd); if (acqurieFence < 0) { ALOGE("No resource during dup fenceFd"); acqurieFence = -1; return; } } }); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } return result; } int CloseCast(int32_t castHandle) { if (g_tvGraphics_1_2 == nullptr) { ALOGE("CloseCast failed: Can't find TVGraphics Service"); return ERROR; } return g_tvGraphics_1_2->CloseCast(castHandle); } void SetBlackCastFrame(bool isBlack) { if (g_tvGraphics_1_2 == nullptr) { ALOGE("SetBlackCastFrame failed: Can't find TVGraphics Service"); return; } auto ret = g_tvGraphics_1_2->SetBlackCastFrame(isBlack); if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); } } int CaptureScreenByVDP(int32_t mode, buffer_handle_t buffer, ARect cropRect) { if (g_tvGraphics == nullptr) { ALOGE("CaptureScreenByVDP failed: Can't find TVGraphics Service"); return ERROR; } CaptureType captureType; if (mode == CAPTURE_MODE_VIDEO) { captureType = CaptureType::CAPTURE_TYPE_VIDEO; } else if (mode == CAPTURE_MODE_VIDEO_GRAPHIC) { captureType = CaptureType::CAPTURE_TYPE_VIDEO_GRAPHIC; } else { ALOGI("captureMode:%d, should use aosp solution", mode); return ERROR; } ALOGI("CaptureScreenByVDP mode:%d", mode); android::hardware::Return ret = 0; auto castResult = V1_2::IGraphics::castFrom(g_tvGraphics); if (castResult.isOk()) { android::sp tvGraphics_1_2 = castResult; if (tvGraphics_1_2 != nullptr) { HwRect rect = {cropRect.left, cropRect.top, cropRect.right, cropRect.bottom}; ALOGI("CaptureScreenByVDP_1_2 crop:[%d, %d, %d, %d]", rect.left, rect.top, rect.right, rect.bottom); ret = tvGraphics_1_2->CaptureScreenByVDP_1_2(captureType, buffer, rect); } else { ret = g_tvGraphics->CaptureScreenByVDP(captureType, buffer); } if (!ret.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); return ERROR; } } if (!castResult.isOk()) { ALOGE("%s failed: HIDL call failed description: %s", __FUNCTION__, ret.description().c_str()); return ERROR; } ALOGI("Capture mode:%d success,ret = %s", mode, ret.description().c_str()); return ret; } void SfDeathRecipient() { if (g_tvGraphics_1_2 == nullptr) { ALOGE("sfDeathRecipient failed: Can't find TVGraphics Service"); return; } if (g_hwListener == nullptr) { g_hwListener = new HwGraphicsListener(); } auto ret = g_tvGraphics_1_2->SfDeathRecipient(g_hwListener); if (!ret.isOk()) { ALOGE("sfDeathRecipient failed: %s", ret.description().c_str()); } }