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