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.

290 lines
9.4 KiB

/*
* 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 <utils/RefBase.h>
#include <log/log.h>
#include <vendor/huanglong/hardware/hwgraphics/1.2/IGraphics.h>
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<V1_0::IGraphics> g_tvGraphics = nullptr;
android::sp<V1_2::IGraphics> g_tvGraphics_1_2 = nullptr;
android::sp<HwGraphicsListener> 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<uint32_t> ret = 0;
auto castResult = V1_2::IGraphics::castFrom(g_tvGraphics);
if (castResult.isOk()) {
android::sp<V1_2::IGraphics> 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 successret = %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());
}
}