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
This commit is contained in:
Amy Zhang
2020-09-09 13:49:10 -07:00
parent 4a11c4408f
commit ca365f2fc9
2 changed files with 106 additions and 47 deletions

View File

@@ -309,9 +309,9 @@ C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize,
/////////////// MediaEvent ///////////////////////
MediaEvent::MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle,
uint64_t dataId, uint64_t dataLength, jobject obj) : mIFilter(iFilter),
mDataId(dataId), mDataLength(dataLength), mBuffer(nullptr),
MediaEvent::MediaEvent(sp<Filter> 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<C2LinearBlock> 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<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
context->mBlock = block;
std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, mDataLength);
std::shared_ptr<C2Buffer> 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> c2param = std::make_shared<C2DataIdInfo>(index, mDataId);
if (numInts > 0) {
std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(memIndex, mDataId);
std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param));
pC2Buffer->setInfo(info);
}
@@ -470,7 +509,7 @@ jobjectArray FilterCallback::getMediaEvent(
if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
sp<MediaEvent> 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<void> FilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEve
}
}
env->CallVoidMethod(
mFilter,
mFilter->mFilterObj,
gFields.onFilterEventID,
array);
return Void();
@@ -709,7 +748,7 @@ Return<void> 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<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
void FilterCallback::setFilter(const sp<Filter> 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<Filter> 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;
}

View File

@@ -117,28 +117,6 @@ struct Dvr : public RefBase {
int mFd;
};
struct MediaEvent : public RefBase {
MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle, uint64_t dataId,
uint64_t dataLength, jobject obj);
~MediaEvent();
jobject getLinearBlock();
uint64_t getAudioHandle();
void finalize();
sp<IFilter> 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<C2Buffer> mC2Buffer;
};
struct Filter : public RefBase {
Filter(sp<IFilter> sp, jobject obj);
~Filter();
@@ -148,6 +126,31 @@ struct Filter : public RefBase {
std::unique_ptr<MQ> mFilterMQ;
EventFlag* mFilterMQEventFlag;
jweak mFilterObj;
native_handle_t* mAvSharedHandle;
uint64_t mAvSharedMemSize;
bool mIsMediaFilter;
};
struct MediaEvent : public RefBase {
MediaEvent(sp<Filter> filter, hidl_handle avHandle, uint64_t dataId,
uint64_t dataSize, jobject obj);
~MediaEvent();
jobject getLinearBlock();
uint64_t getAudioHandle();
void finalize();
sp<Filter> 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<C2Buffer> mC2Buffer;
};
struct FilterCallback : public IFilterCallback {
@@ -159,8 +162,7 @@ struct FilterCallback : public IFilterCallback {
void setFilter(const sp<Filter> filter);
private:
jweak mFilter;
sp<IFilter> mIFilter;
sp<Filter> mFilter;
jobjectArray getSectionEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
jobjectArray getMediaEvent(