/* * 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 #include #include #include 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 p; Return transCreate = m_nxMetadataStore->createNxPlayerMetadata( [&p, this](int32_t status, const sp &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(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 *headers) { HLOGI("call %s in, uri=*", __FUNCTION__); hidl_string urlHidl(url); std::vector
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
headersHidl = headersTemp; Return transSetDataSourceNetwork = m_nxMetadata->setDataSourceUrl(urlHidl, headersHidl); if (!transSetDataSourceNetwork.isOk() || static_cast(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 transSetDataSourceLocal = m_nxMetadata->setDataSourceFd(fdHandle, offset, length); if (!transSetDataSourceLocal.isOk() || static_cast(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 NxMetadataRetriever::getFrameAtTime(int64_t timeUs, ThumbnailParam &inParam, ThumbnailInfo &outInfo) { HLOGI("call %s in", __FUNCTION__); PIC_INFO picInfo = {}; Return 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 heap = new MemoryHeapBase(size, 0, "NxMetadataRetriever"); if (heap.get() == nullptr) { HLOGE("new MemoryHeapBase with size=%zu failed", size); return nullptr; } sp 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(thumbnail->unsecurePointer()); #else frameCopy = static_cast(thumbnail->pointer()); #endif if (frameCopy == nullptr) { HLOGE("frameCopy is null"); return nullptr; } sp 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 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 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 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 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> *frames, int frameIndex, int numFrames, ThumbnailParam &inParam, std::vector &outInfo) { HLOGI("call %s in", __FUNCTION__); (void)outInfo; Return transGetFrameAtIndex = m_nxMetadata->getFrameAtIndex( frameIndex, numFrames, inParam.colorFormat, inParam.metaOnly, [this](int32_t ret, const hidl_vec &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 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 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 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; } };