From ca365f2fc90821f5f5ddfd3ce46e8eddab906859 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 9 Sep 2020 13:49:10 -0700 Subject: [PATCH] Support shared av memory handle in Tuner JNI In the MediaEvent of AV filters, the AV memory handle is mapped/unmapped on each event. If the vendor allocates a persistent memory block, and use MediaEvent.offset to access the data, the mapping change is unnecessary. To improve this, a new API to get shared AV Memory is introduced in Tuner HAL 1.1. Tuner JNI queries the sharedAvMemory Handle when the media filter is opened. It builds up linear block through either shared or independent memory block by checking the memory handle fd number. Test: make Bug: 162013047 Bug: 157143515 Bug: 156664393 Change-Id: I5bfe3a8f4c26b5789212f56709b70c512ed15a0c --- media/jni/android_media_tv_Tuner.cpp | 103 +++++++++++++++++++++------ media/jni/android_media_tv_Tuner.h | 50 ++++++------- 2 files changed, 106 insertions(+), 47 deletions(-) diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index e0afe29de7e69..04dba36a8417c 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -309,9 +309,9 @@ C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, /////////////// MediaEvent /////////////////////// -MediaEvent::MediaEvent(sp iFilter, hidl_handle avHandle, - uint64_t dataId, uint64_t dataLength, jobject obj) : mIFilter(iFilter), - mDataId(dataId), mDataLength(dataLength), mBuffer(nullptr), +MediaEvent::MediaEvent(sp filter, hidl_handle avHandle, + uint64_t dataId, uint64_t dataSize, jobject obj) : mFilter(filter), + mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr), mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) { JNIEnv *env = AndroidRuntime::getJNIEnv(); mMediaEventObj = env->NewWeakGlobalRef(obj); @@ -335,7 +335,8 @@ MediaEvent::~MediaEvent() { void MediaEvent::finalize() { if (mAvHandleRefCnt == 0) { - mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0); + mFilter->mFilterSp->releaseAvHandle( + hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0); native_handle_close(mAvHandle); } } @@ -348,7 +349,47 @@ jobject MediaEvent::getLinearBlock() { if (mLinearBlockObj != NULL) { return mLinearBlockObj; } - mIonHandle = new C2HandleIon(dup(mAvHandle->data[0]), mDataLength); + + int fd; + int numInts = 0; + int memIndex; + int dataSize; + if (mAvHandle->numFds == 0) { + if (mFilter->mAvSharedHandle == NULL) { + ALOGE("Shared AV memory handle is not initialized."); + return NULL; + } + if (mFilter->mAvSharedHandle->numFds == 0) { + ALOGE("Shared AV memory handle is empty."); + return NULL; + } + fd = mFilter->mAvSharedHandle->data[0]; + dataSize = mFilter->mAvSharedMemSize; + numInts = mFilter->mAvSharedHandle->numInts; + if (numInts > 0) { + // If the first int in the shared native handle has value, use it as the index + memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds]; + } + } else { + fd = mAvHandle->data[0]; + dataSize = mDataSize; + numInts = mAvHandle->numInts; + if (numInts > 0) { + // Otherwise if the first int in the av native handle returned from the filter + // event has value, use it as the index + memIndex = mAvHandle->data[mAvHandle->numFds]; + } else { + if (mFilter->mAvSharedHandle != NULL) { + numInts = mFilter->mAvSharedHandle->numInts; + if (numInts > 0) { + // If the first int in the shared native handle has value, use it as the index + memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds]; + } + } + } + } + + mIonHandle = new C2HandleIon(dup(fd), dataSize); std::shared_ptr block = _C2BlockFactory::CreateLinearBlock(mIonHandle); if (block != nullptr) { // CreateLinearBlock delete mIonHandle after it create block successfully. @@ -357,13 +398,11 @@ jobject MediaEvent::getLinearBlock() { JNIEnv *env = AndroidRuntime::getJNIEnv(); std::unique_ptr context{new JMediaCodecLinearBlock}; context->mBlock = block; - std::shared_ptr pC2Buffer = context->toC2Buffer(0, mDataLength); + std::shared_ptr pC2Buffer = context->toC2Buffer(0, dataSize); context->mBuffer = pC2Buffer; mC2Buffer = pC2Buffer; - if (mAvHandle->numInts > 0) { - // use first int in the native_handle as the index - int index = mAvHandle->data[mAvHandle->numFds]; - std::shared_ptr c2param = std::make_shared(index, mDataId); + if (numInts > 0) { + std::shared_ptr c2param = std::make_shared(memIndex, mDataId); std::shared_ptr info(std::static_pointer_cast(c2param)); pC2Buffer->setInfo(info); } @@ -470,7 +509,7 @@ jobjectArray FilterCallback::getMediaEvent( if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) { sp mediaEventSp = - new MediaEvent(mIFilter, mediaEvent.avMemory, + new MediaEvent(mFilter, mediaEvent.avMemory, mediaEvent.avDataId, dataLength + offset, obj); mediaEventSp->mAvHandleRefCnt++; env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get()); @@ -690,7 +729,7 @@ Return FilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEve } } env->CallVoidMethod( - mFilter, + mFilter->mFilterObj, gFields.onFilterEventID, array); return Void(); @@ -709,7 +748,7 @@ Return FilterCallback::onFilterStatus(const DemuxFilterStatus status) { ALOGD("FilterCallback::onFilterStatus"); JNIEnv *env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod( - mFilter, + mFilter->mFilterObj, gFields.onFilterStatusID, (jint)status); return Void(); @@ -717,17 +756,11 @@ Return FilterCallback::onFilterStatus(const DemuxFilterStatus status) { void FilterCallback::setFilter(const sp filter) { ALOGD("FilterCallback::setFilter"); - mFilter = filter->mFilterObj; - mIFilter = filter->mFilterSp; + // JNI Object + mFilter = filter; } -FilterCallback::~FilterCallback() { - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (mFilter != NULL) { - env->DeleteWeakGlobalRef(mFilter); - mFilter = NULL; - } -} +FilterCallback::~FilterCallback() {} /////////////// Filter /////////////////////// @@ -1575,9 +1608,33 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) { sp filterSp = new Filter(iFilterSp, filterObj); filterSp->incStrong(filterObj); env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get()); - + filterSp->mIsMediaFilter = false; + filterSp->mAvSharedHandle = NULL; callback->setFilter(filterSp); + if (type.mainType == DemuxFilterMainType::MMTP) { + if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO || + type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) { + filterSp->mIsMediaFilter = true; + } + } + + if (type.mainType == DemuxFilterMainType::TS) { + if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO || + type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) { + filterSp->mIsMediaFilter = true; + } + } + + if (iFilterSp_1_1 != NULL && filterSp->mIsMediaFilter) { + iFilterSp_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) { + if (r == Result::SUCCESS) { + filterSp->mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle()); + filterSp->mAvSharedMemSize = avMemSize; + } + }); + } + return filterObj; } diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index d7dc600a166b1..7a633f8db21a4 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -117,28 +117,6 @@ struct Dvr : public RefBase { int mFd; }; -struct MediaEvent : public RefBase { - MediaEvent(sp iFilter, hidl_handle avHandle, uint64_t dataId, - uint64_t dataLength, jobject obj); - ~MediaEvent(); - jobject getLinearBlock(); - uint64_t getAudioHandle(); - void finalize(); - - sp mIFilter; - native_handle_t* mAvHandle; - uint64_t mDataId; - uint64_t mDataLength; - uint8_t* mBuffer; - android::Mutex mLock; - int mDataIdRefCnt; - int mAvHandleRefCnt; - jweak mMediaEventObj; - jweak mLinearBlockObj; - C2HandleIon* mIonHandle; - std::weak_ptr mC2Buffer; -}; - struct Filter : public RefBase { Filter(sp sp, jobject obj); ~Filter(); @@ -148,6 +126,31 @@ struct Filter : public RefBase { std::unique_ptr mFilterMQ; EventFlag* mFilterMQEventFlag; jweak mFilterObj; + native_handle_t* mAvSharedHandle; + uint64_t mAvSharedMemSize; + bool mIsMediaFilter; +}; + +struct MediaEvent : public RefBase { + MediaEvent(sp filter, hidl_handle avHandle, uint64_t dataId, + uint64_t dataSize, jobject obj); + ~MediaEvent(); + jobject getLinearBlock(); + uint64_t getAudioHandle(); + void finalize(); + + sp mFilter; + native_handle_t* mAvHandle; + uint64_t mDataId; + uint64_t mDataSize; + uint8_t* mBuffer; + android::Mutex mLock; + int mDataIdRefCnt; + int mAvHandleRefCnt; + jweak mMediaEventObj; + jweak mLinearBlockObj; + C2HandleIon* mIonHandle; + std::weak_ptr mC2Buffer; }; struct FilterCallback : public IFilterCallback { @@ -159,8 +162,7 @@ struct FilterCallback : public IFilterCallback { void setFilter(const sp filter); private: - jweak mFilter; - sp mIFilter; + sp mFilter; jobjectArray getSectionEvent( jobjectArray& arr, const std::vector& events); jobjectArray getMediaEvent(