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.
357 lines
13 KiB
357 lines
13 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
|
|
* Description: NxMetadataRetriever class implement
|
|
* Author: NxPlayer software group
|
|
* Create: 2019-11-21
|
|
*/
|
|
|
|
#define LOG_NDEBUG 0
|
|
#define LOG_TAG "HR_RET"
|
|
|
|
#include "NxMetadataRetriever.h"
|
|
#include "NxMediaDefine.h"
|
|
|
|
#include <log/log.h>
|
|
#include <cstring>
|
|
#include <cinttypes>
|
|
#include <utils/Errors.h>
|
|
|
|
using ::android::hardware::hidl_handle;
|
|
|
|
namespace android {
|
|
NxMetadataRetriever::NxMetadataRetriever(int idx)
|
|
:m_deathRecipient(nullptr), m_instIdx(idx)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
m_nxMetadataStore = INxPlayerMetadataStore::getService();
|
|
if (m_nxMetadataStore.get() == nullptr) {
|
|
HLOGE("getService metadataStore failed");
|
|
}
|
|
sp<INxPlayerMetadata> p;
|
|
Return<void> transCreate = m_nxMetadataStore->createNxPlayerMetadata(
|
|
[&p, this](int32_t status, const sp<INxPlayerMetadata> &comp) {
|
|
if (status != 0) {
|
|
HLOGE("createNxMediaPlayerMetadata failed");
|
|
return;
|
|
}
|
|
p = comp;
|
|
});
|
|
m_nxMetadata = p;
|
|
InitDeathRecipient();
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
}
|
|
|
|
void NxMetadataRetriever::InitDeathRecipient()
|
|
{
|
|
m_deathRecipient = new(std::nothrow) DeathRecipient(this, m_instIdx);
|
|
if (m_deathRecipient.get() == nullptr) {
|
|
HLOGE("new DeathRecipient failed");
|
|
}
|
|
|
|
if (m_deathRecipient.get() != nullptr && m_nxMetadata != nullptr) {
|
|
uint64_t cookie = reinterpret_cast<uintptr_t>(m_nxMetadata.get());
|
|
if (!m_nxMetadata->linkToDeath(m_deathRecipient, cookie)) {
|
|
HLOGE("register death notification failed");
|
|
} else {
|
|
HLOGD("register death notification success");
|
|
}
|
|
}
|
|
}
|
|
|
|
void NxMetadataRetriever::DeInitDeathRecipient()
|
|
{
|
|
if (m_deathRecipient.get() != nullptr && m_nxMetadata != nullptr) {
|
|
m_nxMetadata->unlinkToDeath(m_deathRecipient);
|
|
}
|
|
}
|
|
|
|
NxMetadataRetriever::~NxMetadataRetriever()
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
DeInitDeathRecipient();
|
|
m_nxMetadata.clear();
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
}
|
|
|
|
status_t NxMetadataRetriever::setDataSource(const char *url,
|
|
const KeyedVector<String8, String8> *headers)
|
|
{
|
|
HLOGI("call %s in, uri=*", __FUNCTION__);
|
|
hidl_string urlHidl(url);
|
|
std::vector<Header> headersTemp;
|
|
if (headers != nullptr) {
|
|
for (size_t i = 0; i < headers->size(); i++) {
|
|
Header header{headers->keyAt(i).c_str(), headers->valueAt(i).c_str()};
|
|
headersTemp.push_back(header);
|
|
}
|
|
}
|
|
|
|
hidl_vec<Header> headersHidl = headersTemp;
|
|
Return<int32_t> transSetDataSourceNetwork = m_nxMetadata->setDataSourceUrl(urlHidl, headersHidl);
|
|
if (!transSetDataSourceNetwork.isOk() || static_cast<int32_t>(transSetDataSourceNetwork) != 0) {
|
|
HLOGE("SetDataSourceNetwork failed");
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t NxMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
native_handle_t * const nativeHdl = native_handle_create(1, 0);
|
|
if (nativeHdl == nullptr) {
|
|
HLOGE("nativeHdl is null");
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
nativeHdl->data[0] = fd;
|
|
hidl_handle fdHandle;
|
|
fdHandle.setTo(nativeHdl, false);
|
|
Return<int32_t> transSetDataSourceLocal = m_nxMetadata->setDataSourceFd(fdHandle, offset, length);
|
|
if (!transSetDataSourceLocal.isOk() || static_cast<int32_t>(transSetDataSourceLocal) != 0) {
|
|
HLOGE("transSetDataSourceLocal failed");
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
void NxMetadataRetriever::InitPicInfo(PIC_INFO &picInfo, const MediaBuffer &pic) const
|
|
{
|
|
HLOGD("%s", __FUNCTION__);
|
|
picInfo.picWidth = pic.width;
|
|
picInfo.picHeight = pic.height;
|
|
picInfo.picRotation = pic.rotation;
|
|
picInfo.picSize = pic.size;
|
|
picInfo.picData = pic.data;
|
|
}
|
|
|
|
void NxMetadataRetriever::CopyFrameInfo(ThumbnailInfo &outInfo, const PIC_INFO &picInfo) const
|
|
{
|
|
HLOGD("%s, rotation=%d", __FUNCTION__, picInfo.picRotation);
|
|
outInfo.width = picInfo.picWidth;
|
|
outInfo.height = picInfo.picHeight;
|
|
outInfo.rotation = picInfo.picRotation;
|
|
outInfo.picSize = picInfo.picSize;
|
|
}
|
|
|
|
sp<IMemory> NxMetadataRetriever::getFrameAtTime(int64_t timeUs, ThumbnailParam &inParam, ThumbnailInfo &outInfo)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
PIC_INFO picInfo = {};
|
|
Return<void> transGetFrameAtTime = m_nxMetadata->getFrameAtTime(
|
|
timeUs, inParam.option, inParam.colorFormat, inParam.metaOnly,
|
|
[&picInfo, this](int32_t ret, const MediaBuffer &pic) {
|
|
if (ret != 0) {
|
|
HLOGE("getFrameAtTime failed");
|
|
return;
|
|
}
|
|
InitPicInfo(picInfo, pic);
|
|
});
|
|
if (!transGetFrameAtTime.isOk() || (picInfo.picSize == 0)) {
|
|
HLOGE("transGetFrameAtTime failed");
|
|
return nullptr;
|
|
}
|
|
uint8_t *frameCopy = nullptr;
|
|
size_t size = inParam.extraSize + picInfo.picSize;
|
|
sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "NxMetadataRetriever");
|
|
if (heap.get() == nullptr) {
|
|
HLOGE("new MemoryHeapBase with size=%zu failed", size);
|
|
return nullptr;
|
|
}
|
|
sp<IMemory> thumbnail = new MemoryBase(heap, 0, size);
|
|
if (thumbnail.get() == nullptr) {
|
|
HLOGE("new MemoryBase failed, not enough memory for VideoFrame size=%zu", size);
|
|
return nullptr;
|
|
}
|
|
/* For the RGB picture, only one block (block 0) is used. In this case, pay attention only to frameData[0] */
|
|
#if (PLATFORM_SDK_VERSION >= 31)
|
|
frameCopy = static_cast<uint8_t *>(thumbnail->unsecurePointer());
|
|
#else
|
|
frameCopy = static_cast<uint8_t *>(thumbnail->pointer());
|
|
#endif
|
|
if (frameCopy == nullptr) {
|
|
HLOGE("frameCopy is null");
|
|
return nullptr;
|
|
}
|
|
|
|
sp<HMemory> memory = mapMemory(picInfo.picData);
|
|
if (memory.get() == nullptr || memory->getPointer() == nullptr) {
|
|
HLOGE("mapMemory failed");
|
|
return nullptr;
|
|
}
|
|
if (memcpy_s(frameCopy + inParam.extraSize, picInfo.picSize, memory->getPointer(), picInfo.picSize) != EOK) {
|
|
HLOGE("memcpy_s failed");
|
|
return nullptr;
|
|
}
|
|
CopyFrameInfo(outInfo, picInfo);
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return thumbnail;
|
|
}
|
|
|
|
sp<IMemory> NxMetadataRetriever::getImageAtIndex(int index, ThumbnailParam &inParam, ThumbnailInfo &outInfo)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
(void)outInfo;
|
|
uint32_t picWidth;
|
|
uint32_t picHeight;
|
|
uint32_t picSize;
|
|
hidl_memory picData;
|
|
Return<void> transGetImageAtIndex = m_nxMetadata->getImageAtIndex(
|
|
index, inParam.colorFormat, inParam.metaOnly, inParam.thumbnail,
|
|
[&picWidth, &picHeight, &picSize, &picData, this](int32_t ret, const MediaBuffer &pic) {
|
|
if (ret != 0) {
|
|
HLOGE("transGetImageAtIndex failed");
|
|
return;
|
|
}
|
|
picWidth = pic.width;
|
|
picHeight = pic.height;
|
|
picSize = pic.size;
|
|
picData = pic.data;
|
|
});
|
|
if (!transGetImageAtIndex.isOk()) {
|
|
HLOGE("transGetImageAtIndex failed");
|
|
return nullptr;
|
|
}
|
|
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return nullptr;
|
|
}
|
|
|
|
sp<IMemory> NxMetadataRetriever::getImageRectAtIndex(int index, ThumbnailParam &inParam,
|
|
ThumbnailRect &rectInfo, ThumbnailInfo &outInfo)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
(void)outInfo;
|
|
uint32_t picWidth;
|
|
uint32_t picHeight;
|
|
uint32_t picSize;
|
|
hidl_memory picData;
|
|
Return<void> transGetImageRectAtIndex = m_nxMetadata->getImageRectAtIndex(
|
|
index, inParam.colorFormat, rectInfo.left, rectInfo.top, rectInfo.right, rectInfo.bottom,
|
|
[&picWidth, &picHeight, &picSize, &picData, this](int32_t ret, const MediaBuffer &pic) {
|
|
if (ret != 0) {
|
|
HLOGE("getImageRectAtIndex failed");
|
|
return;
|
|
}
|
|
picWidth = pic.width;
|
|
picHeight = pic.height;
|
|
picSize = pic.size;
|
|
picData = pic.data;
|
|
});
|
|
if (!transGetImageRectAtIndex.isOk()) {
|
|
HLOGE("transGetImageAtIndex failed");
|
|
return nullptr;
|
|
}
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return nullptr;
|
|
}
|
|
|
|
status_t NxMetadataRetriever::getFrameAtIndex(std::vector<sp<IMemory>> *frames, int frameIndex, int numFrames,
|
|
ThumbnailParam &inParam, std::vector<ThumbnailInfo> &outInfo)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
(void)outInfo;
|
|
Return<void> transGetFrameAtIndex = m_nxMetadata->getFrameAtIndex(
|
|
frameIndex, numFrames, inParam.colorFormat, inParam.metaOnly,
|
|
[this](int32_t ret, const hidl_vec<MediaBuffer> &pic) {
|
|
if (ret != 0) {
|
|
HLOGE("getFrameAtIndex failed");
|
|
return;
|
|
}
|
|
(void)pic;
|
|
});
|
|
if (!transGetFrameAtIndex.isOk()) {
|
|
HLOGE("transGetImageAtIndex failed");
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
HLOGE("call %s out, not support getFrameAtIndex", __FUNCTION__);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
sp<IMemory> NxMetadataRetriever::getFrameAtIndex(int frameIndex, ThumbnailParam &inParam,
|
|
ThumbnailInfo &outInfo)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
(void)outInfo;
|
|
HLOGE("call %s out, not support getFrameAtIndex! frameIndex:%d, colorFormat:%d,metaOnly:%d", __FUNCTION__,
|
|
frameIndex, inParam.colorFormat, inParam.metaOnly);
|
|
return nullptr;
|
|
}
|
|
|
|
const char *NxMetadataRetriever::extractMetadata(int keyCode)
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
hidl_string metaData;
|
|
Return<void> transExtractMetadata = m_nxMetadata->extractMetadata(
|
|
keyCode,
|
|
[&metaData, this](int32_t ret, const hidl_string &metadata) {
|
|
if (ret != 0) {
|
|
HLOGE("extractMetadata failed");
|
|
return;
|
|
}
|
|
metaData = metadata;
|
|
});
|
|
if (!transExtractMetadata.isOk()) {
|
|
HLOGE("transExtractMetadata failed");
|
|
return nullptr;
|
|
}
|
|
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
if (!metaData.empty()) {
|
|
return strdup(metaData.c_str());
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
std::string NxMetadataRetriever::extractAlbumArt()
|
|
{
|
|
HLOGI("call %s in", __FUNCTION__);
|
|
std::string albumArtStr;
|
|
Return<void> transExtractAlbumArt = m_nxMetadata->extractAlbumArt(
|
|
[&albumArtStr, this](int32_t ret, const hidl_string &albumArtString) {
|
|
if (ret != 0) {
|
|
HLOGE("extractAlbumArt failed");
|
|
return;
|
|
}
|
|
albumArtStr = albumArtString;
|
|
});
|
|
if (!transExtractAlbumArt.isOk()) {
|
|
HLOGE("transExtractMetadata failed");
|
|
return albumArtStr;
|
|
}
|
|
HLOGI("call %s out", __FUNCTION__);
|
|
return albumArtStr;
|
|
}
|
|
|
|
void NxMetadataRetriever::DeathRecipient::serviceDied(uint64_t cookie,
|
|
const wp< ::android::hidl::base::V1_0::IBase > &) /* who */
|
|
{
|
|
/* handle death notify */
|
|
HLOGE("call %s, player cookie=%" PRIu64 "", __FUNCTION__, cookie);
|
|
if (m_nxMetadataRetriever != nullptr) {
|
|
m_nxMetadataRetriever->m_nxMetadata.clear();
|
|
}
|
|
}
|
|
|
|
NxMetadataRetriever::DeathRecipient::~DeathRecipient()
|
|
{
|
|
HLOGD("release %s", __FUNCTION__);
|
|
}
|
|
|
|
extern "C" android::NxMetadataRetrieverInterface *CreateNxMetadataRetrieverInterfaceInstance(int idx)
|
|
{
|
|
ALOGI("[%d][%s:%d]: create %s", idx, __FUNCTION__, __LINE__, __FUNCTION__);
|
|
return new ::android::NxMetadataRetriever(idx);
|
|
}
|
|
|
|
extern "C" void DestroyNxMetadataRetrieverInterfaceInstance(
|
|
android::NxMetadataRetrieverInterface *metadataRetriever, int idx)
|
|
{
|
|
ALOGI("[%d][%s:%d]: delete %s", idx, __FUNCTION__, __LINE__, __FUNCTION__);
|
|
delete metadataRetriever;
|
|
}
|
|
};
|