Loading media/java/android/media/tv/tuner/filter/MediaEvent.java +24 −3 Original line number Diff line number Diff line Loading @@ -28,14 +28,19 @@ import android.media.MediaCodec.LinearBlock; */ @SystemApi public class MediaEvent extends FilterEvent { private native int nativeGetAudioHandle(); private long mNativeContext; private final Object mLock = new Object(); private native Long nativeGetAudioHandle(); private native LinearBlock nativeGetLinearBlock(); private native void nativeFinalize(); private final int mStreamId; private final boolean mIsPtsPresent; private final long mPts; private final long mDataLength; private final long mOffset; private final LinearBlock mLinearBlock; private LinearBlock mLinearBlock; private final boolean mIsSecureMemory; private final long mDataId; private final int mMpuSequenceNumber; Loading Loading @@ -103,8 +108,13 @@ public class MediaEvent extends FilterEvent { */ @Nullable public LinearBlock getLinearBlock() { synchronized (mLock) { if (mLinearBlock == null) { mLinearBlock = nativeGetLinearBlock(); } return mLinearBlock; } } /** * Returns whether the data is secure. Loading Loading @@ -163,4 +173,15 @@ public class MediaEvent extends FilterEvent { public AudioDescriptor getExtraMetaData() { return mExtraMetaData; } /** * Finalize the MediaEvent object. * @hide */ @Override protected void finalize() { nativeFinalize(); mNativeContext = 0; } } media/jni/android_media_tv_Tuner.cpp +158 −21 Original line number Diff line number Diff line Loading @@ -21,8 +21,7 @@ #include "android_media_tv_Tuner.h" #include "android_runtime/AndroidRuntime.h" #include <C2BlockInternal.h> #include <C2HandleIonInternal.h> #include <android-base/logging.h> #include <android/hardware/tv/tuner/1.0/ITuner.h> #include <media/stagefright/foundation/ADebug.h> #include <nativehelper/JNIHelp.h> Loading Loading @@ -145,6 +144,7 @@ struct fields_t { jfieldID descramblerContext; jfieldID dvrRecorderContext; jfieldID dvrPlaybackContext; jfieldID mediaEventContext; jmethodID frontendInitID; jmethodID filterInitID; jmethodID timeFilterInitID; Loading @@ -169,6 +169,12 @@ static fields_t gFields; static int IP_V4_LENGTH = 4; static int IP_V6_LENGTH = 16; void DestroyCallback(const C2Buffer * /* buf */, void *arg) { android::sp<android::MediaEvent> event = (android::MediaEvent *)arg; event->mAvHandleRefCnt--; event->finalize(); } namespace android { /////////////// LnbCallback /////////////////////// LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) { Loading Loading @@ -280,17 +286,69 @@ MQ& Dvr::getDvrMQ() { return *mDvrMQ; } /////////////// FilterCallback /////////////////////// //TODO: implement filter callback jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint32_t size) { ALOGD("FilterCallback::handleToLinearBlock"); C2HandleIon* ion = new C2HandleIon(handle->data[0], size); std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(ion); /////////////// C2DataIdInfo /////////////////////// C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) { CHECK(isGlobal()); CHECK_EQ(C2Param::INFO, kind()); DummyInfo info{value}; memcpy(this + 1, static_cast<C2Param *>(&info) + 1, kParamSize - sizeof(C2Param)); } /////////////// 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), mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) { JNIEnv *env = AndroidRuntime::getJNIEnv(); mMediaEventObj = env->NewWeakGlobalRef(obj); mAvHandle = native_handle_clone(avHandle.getNativeHandle()); } MediaEvent::~MediaEvent() { JNIEnv *env = AndroidRuntime::getJNIEnv(); env->DeleteWeakGlobalRef(mMediaEventObj); mMediaEventObj = NULL; native_handle_delete(mAvHandle); if (mIonHandle != NULL) { delete mIonHandle; } if (mC2Buffer != NULL) { mC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this); } } void MediaEvent::finalize() { if (mAvHandleRefCnt == 0) { mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0); native_handle_close(mAvHandle); } } jobject MediaEvent::getLinearBlock() { ALOGD("MediaEvent::getLinearBlock"); if (mAvHandle == NULL) { return NULL; } if (mLinearBlockObj != NULL) { return mLinearBlockObj; } mIonHandle = new C2HandleIon(mAvHandle->data[0], mDataLength); std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle); JNIEnv *env = AndroidRuntime::getJNIEnv(); std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock}; context->mBlock = block; mC2Buffer = context->toC2Buffer(0, mDataLength); 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); std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param)); mC2Buffer->setInfo(info); } mC2Buffer->registerOnDestroyNotify(&DestroyCallback, this); jobject linearBlock = env->NewObject( env->FindClass("android/media/MediaCodec$LinearBlock"), Loading @@ -300,9 +358,18 @@ jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint3 gFields.linearBlockSetInternalStateID, (jlong)context.release(), true); return linearBlock; mLinearBlockObj = env->NewWeakGlobalRef(linearBlock); mAvHandleRefCnt++; return mLinearBlockObj; } uint64_t MediaEvent::getAudioHandle() { mDataIdRefCnt++; return mDataId; } /////////////// FilterCallback /////////////////////// jobjectArray FilterCallback::getSectionEvent( jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { JNIEnv *env = AndroidRuntime::getJNIEnv(); Loading Loading @@ -333,6 +400,7 @@ jobjectArray FilterCallback::getMediaEvent( "<init>", "(IZJJJLandroid/media/MediaCodec$LinearBlock;" "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V"); jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J"); for (int i = 0; i < events.size(); i++) { auto event = events[i]; Loading @@ -358,12 +426,6 @@ jobjectArray FilterCallback::getMediaEvent( } jlong dataLength = static_cast<jlong>(mediaEvent.dataLength); const native_handle_t* h = NULL; jobject block = NULL; if (mediaEvent.avMemory != NULL) { h = mediaEvent.avMemory.getNativeHandle(); block = handleToLinearBlock(h, dataLength); } jint streamId = static_cast<jint>(mediaEvent.streamId); jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent); Loading @@ -376,8 +438,18 @@ jobjectArray FilterCallback::getMediaEvent( jobject obj = env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength, offset, block, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, offset, NULL, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, audioDescriptor); if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) { sp<MediaEvent> mediaEventSp = new MediaEvent(mIFilter, mediaEvent.avMemory, mediaEvent.avDataId, dataLength, obj); mediaEventSp->mAvHandleRefCnt++; env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get()); mediaEventSp->incStrong(obj); } env->SetObjectArrayElement(arr, i, obj); } return arr; Loading Loading @@ -594,10 +666,10 @@ Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) { return Void(); } void FilterCallback::setFilter(const jobject filter) { void FilterCallback::setFilter(const sp<Filter> filter) { ALOGD("FilterCallback::setFilter"); JNIEnv *env = AndroidRuntime::getJNIEnv(); mFilter = env->NewWeakGlobalRef(filter); mFilter = filter->mFilterObj; mIFilter = filter->mFilterSp; } FilterCallback::~FilterCallback() { Loading Loading @@ -1431,7 +1503,7 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) { filterSp->incStrong(filterObj); env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get()); callback->setFilter(filterObj); callback->setFilter(filterSp); return filterObj; } Loading Loading @@ -2390,6 +2462,9 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) { gFields.onDvrPlaybackStatusID = env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V"); jclass mediaEventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); gFields.mediaEventContext = env->GetFieldID(mediaEventClazz, "mNativeContext", "J"); jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock"); gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V"); gFields.linearBlockSetInternalStateID = Loading Loading @@ -3507,6 +3582,52 @@ static jlong android_media_tv_Tuner_write_dvr_to_array( return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size); } static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) { return (MediaEvent *)env->GetLongField(mediaEventObj, gFields.mediaEventContext); } static jobject android_media_tv_Tuner_media_event_get_linear_block( JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return NULL; } return mediaEventSp->getLinearBlock(); } static jobject android_media_tv_Tuner_media_event_get_audio_handle( JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return NULL; } android::Mutex::Autolock autoLock(mediaEventSp->mLock); uint64_t audioHandle = mediaEventSp->getAudioHandle(); jclass longClazz = env->FindClass("java/lang/Long"); jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(audioHandle)); return longObj; } static void android_media_tv_Tuner_media_event_finalize(JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return; } android::Mutex::Autolock autoLock(mediaEventSp->mLock); mediaEventSp->mAvHandleRefCnt--; mediaEventSp->finalize(); mediaEventSp->decStrong(mediaEventObj); } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init }, { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup }, Loading Loading @@ -3629,6 +3750,15 @@ static const JNINativeMethod gLnbMethods[] = { { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb }, }; static const JNINativeMethod gMediaEventMethods[] = { { "nativeGetLinearBlock", "()Landroid/media/MediaCodec$LinearBlock;", (void *)android_media_tv_Tuner_media_event_get_linear_block }, { "nativeGetAudioHandle", "()Ljava/lang/Long;", (void *)android_media_tv_Tuner_media_event_get_audio_handle }, { "nativeFinalize", "()V", (void *)android_media_tv_Tuner_media_event_finalize }, }; static bool register_android_media_tv_Tuner(JNIEnv *env) { if (AndroidRuntime::registerNativeMethods( env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) { Loading Loading @@ -3677,6 +3807,13 @@ static bool register_android_media_tv_Tuner(JNIEnv *env) { ALOGE("Failed to register lnb native methods"); return false; } if (AndroidRuntime::registerNativeMethods( env, "android/media/tv/tuner/filter/MediaEvent", gMediaEventMethods, NELEM(gMediaEventMethods)) != JNI_OK) { ALOGE("Failed to register MediaEvent native methods"); return false; } return true; } Loading media/jni/android_media_tv_Tuner.h +48 −13 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ #define _ANDROID_MEDIA_TV_TUNER_H_ #include <android/hardware/tv/tuner/1.0/ITuner.h> #include <C2BlockInternal.h> #include <C2HandleIonInternal.h> #include <C2ParamDef.h> #include <fmq/MessageQueue.h> #include <fstream> #include <string> #include <unordered_map> #include <utils/Mutex.h> #include <utils/RefBase.h> #include "jni.h" Loading @@ -30,6 +34,7 @@ using ::android::hardware::EventFlag; using ::android::hardware::MQDescriptorSync; using ::android::hardware::MessageQueue; using ::android::hardware::Return; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_vec; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent; Loading Loading @@ -106,15 +111,48 @@ 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::shared_ptr<C2Buffer> mC2Buffer; }; struct Filter : public RefBase { Filter(sp<IFilter> sp, jobject obj); ~Filter(); int close(); sp<IFilter> getIFilter(); sp<IFilter> mFilterSp; std::unique_ptr<MQ> mFilterMQ; EventFlag* mFilterMQEventFlag; jweak mFilterObj; }; struct FilterCallback : public IFilterCallback { ~FilterCallback(); virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent); virtual Return<void> onFilterStatus(const DemuxFilterStatus status); void setFilter(const jobject filter); jobject handleToLinearBlock(const native_handle_t* handle, uint32_t size); void setFilter(const sp<Filter> filter); private: jweak mFilter; sp<IFilter> mIFilter; jobjectArray getSectionEvent( jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events); jobjectArray getMediaEvent( Loading Loading @@ -144,17 +182,6 @@ struct FrontendCallback : public IFrontendCallback { FrontendId mId; }; struct Filter : public RefBase { Filter(sp<IFilter> sp, jobject obj); ~Filter(); int close(); sp<IFilter> getIFilter(); sp<IFilter> mFilterSp; std::unique_ptr<MQ> mFilterMQ; EventFlag* mFilterMQEventFlag; jweak mFilterObj; }; struct TimeFilter : public RefBase { TimeFilter(sp<ITimeFilter> sp, jweak obj); ~TimeFilter(); Loading Loading @@ -219,6 +246,14 @@ private: static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps); }; class C2DataIdInfo : public C2Param { public: C2DataIdInfo(uint32_t index, uint64_t value); private: typedef C2GlobalParam<C2Info, C2Int64Value, 0> DummyInfo; static const size_t kParamSize = sizeof(DummyInfo); }; } // namespace android #endif // _ANDROID_MEDIA_TV_TUNER_H_ Loading
media/java/android/media/tv/tuner/filter/MediaEvent.java +24 −3 Original line number Diff line number Diff line Loading @@ -28,14 +28,19 @@ import android.media.MediaCodec.LinearBlock; */ @SystemApi public class MediaEvent extends FilterEvent { private native int nativeGetAudioHandle(); private long mNativeContext; private final Object mLock = new Object(); private native Long nativeGetAudioHandle(); private native LinearBlock nativeGetLinearBlock(); private native void nativeFinalize(); private final int mStreamId; private final boolean mIsPtsPresent; private final long mPts; private final long mDataLength; private final long mOffset; private final LinearBlock mLinearBlock; private LinearBlock mLinearBlock; private final boolean mIsSecureMemory; private final long mDataId; private final int mMpuSequenceNumber; Loading Loading @@ -103,8 +108,13 @@ public class MediaEvent extends FilterEvent { */ @Nullable public LinearBlock getLinearBlock() { synchronized (mLock) { if (mLinearBlock == null) { mLinearBlock = nativeGetLinearBlock(); } return mLinearBlock; } } /** * Returns whether the data is secure. Loading Loading @@ -163,4 +173,15 @@ public class MediaEvent extends FilterEvent { public AudioDescriptor getExtraMetaData() { return mExtraMetaData; } /** * Finalize the MediaEvent object. * @hide */ @Override protected void finalize() { nativeFinalize(); mNativeContext = 0; } }
media/jni/android_media_tv_Tuner.cpp +158 −21 Original line number Diff line number Diff line Loading @@ -21,8 +21,7 @@ #include "android_media_tv_Tuner.h" #include "android_runtime/AndroidRuntime.h" #include <C2BlockInternal.h> #include <C2HandleIonInternal.h> #include <android-base/logging.h> #include <android/hardware/tv/tuner/1.0/ITuner.h> #include <media/stagefright/foundation/ADebug.h> #include <nativehelper/JNIHelp.h> Loading Loading @@ -145,6 +144,7 @@ struct fields_t { jfieldID descramblerContext; jfieldID dvrRecorderContext; jfieldID dvrPlaybackContext; jfieldID mediaEventContext; jmethodID frontendInitID; jmethodID filterInitID; jmethodID timeFilterInitID; Loading @@ -169,6 +169,12 @@ static fields_t gFields; static int IP_V4_LENGTH = 4; static int IP_V6_LENGTH = 16; void DestroyCallback(const C2Buffer * /* buf */, void *arg) { android::sp<android::MediaEvent> event = (android::MediaEvent *)arg; event->mAvHandleRefCnt--; event->finalize(); } namespace android { /////////////// LnbCallback /////////////////////// LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) { Loading Loading @@ -280,17 +286,69 @@ MQ& Dvr::getDvrMQ() { return *mDvrMQ; } /////////////// FilterCallback /////////////////////// //TODO: implement filter callback jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint32_t size) { ALOGD("FilterCallback::handleToLinearBlock"); C2HandleIon* ion = new C2HandleIon(handle->data[0], size); std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(ion); /////////////// C2DataIdInfo /////////////////////// C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) { CHECK(isGlobal()); CHECK_EQ(C2Param::INFO, kind()); DummyInfo info{value}; memcpy(this + 1, static_cast<C2Param *>(&info) + 1, kParamSize - sizeof(C2Param)); } /////////////// 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), mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) { JNIEnv *env = AndroidRuntime::getJNIEnv(); mMediaEventObj = env->NewWeakGlobalRef(obj); mAvHandle = native_handle_clone(avHandle.getNativeHandle()); } MediaEvent::~MediaEvent() { JNIEnv *env = AndroidRuntime::getJNIEnv(); env->DeleteWeakGlobalRef(mMediaEventObj); mMediaEventObj = NULL; native_handle_delete(mAvHandle); if (mIonHandle != NULL) { delete mIonHandle; } if (mC2Buffer != NULL) { mC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this); } } void MediaEvent::finalize() { if (mAvHandleRefCnt == 0) { mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0); native_handle_close(mAvHandle); } } jobject MediaEvent::getLinearBlock() { ALOGD("MediaEvent::getLinearBlock"); if (mAvHandle == NULL) { return NULL; } if (mLinearBlockObj != NULL) { return mLinearBlockObj; } mIonHandle = new C2HandleIon(mAvHandle->data[0], mDataLength); std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle); JNIEnv *env = AndroidRuntime::getJNIEnv(); std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock}; context->mBlock = block; mC2Buffer = context->toC2Buffer(0, mDataLength); 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); std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param)); mC2Buffer->setInfo(info); } mC2Buffer->registerOnDestroyNotify(&DestroyCallback, this); jobject linearBlock = env->NewObject( env->FindClass("android/media/MediaCodec$LinearBlock"), Loading @@ -300,9 +358,18 @@ jobject FilterCallback::handleToLinearBlock(const native_handle_t* handle, uint3 gFields.linearBlockSetInternalStateID, (jlong)context.release(), true); return linearBlock; mLinearBlockObj = env->NewWeakGlobalRef(linearBlock); mAvHandleRefCnt++; return mLinearBlockObj; } uint64_t MediaEvent::getAudioHandle() { mDataIdRefCnt++; return mDataId; } /////////////// FilterCallback /////////////////////// jobjectArray FilterCallback::getSectionEvent( jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) { JNIEnv *env = AndroidRuntime::getJNIEnv(); Loading Loading @@ -333,6 +400,7 @@ jobjectArray FilterCallback::getMediaEvent( "<init>", "(IZJJJLandroid/media/MediaCodec$LinearBlock;" "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V"); jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J"); for (int i = 0; i < events.size(); i++) { auto event = events[i]; Loading @@ -358,12 +426,6 @@ jobjectArray FilterCallback::getMediaEvent( } jlong dataLength = static_cast<jlong>(mediaEvent.dataLength); const native_handle_t* h = NULL; jobject block = NULL; if (mediaEvent.avMemory != NULL) { h = mediaEvent.avMemory.getNativeHandle(); block = handleToLinearBlock(h, dataLength); } jint streamId = static_cast<jint>(mediaEvent.streamId); jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent); Loading @@ -376,8 +438,18 @@ jobjectArray FilterCallback::getMediaEvent( jobject obj = env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength, offset, block, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, offset, NULL, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, audioDescriptor); if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) { sp<MediaEvent> mediaEventSp = new MediaEvent(mIFilter, mediaEvent.avMemory, mediaEvent.avDataId, dataLength, obj); mediaEventSp->mAvHandleRefCnt++; env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get()); mediaEventSp->incStrong(obj); } env->SetObjectArrayElement(arr, i, obj); } return arr; Loading Loading @@ -594,10 +666,10 @@ Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) { return Void(); } void FilterCallback::setFilter(const jobject filter) { void FilterCallback::setFilter(const sp<Filter> filter) { ALOGD("FilterCallback::setFilter"); JNIEnv *env = AndroidRuntime::getJNIEnv(); mFilter = env->NewWeakGlobalRef(filter); mFilter = filter->mFilterObj; mIFilter = filter->mFilterSp; } FilterCallback::~FilterCallback() { Loading Loading @@ -1431,7 +1503,7 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) { filterSp->incStrong(filterObj); env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get()); callback->setFilter(filterObj); callback->setFilter(filterSp); return filterObj; } Loading Loading @@ -2390,6 +2462,9 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) { gFields.onDvrPlaybackStatusID = env->GetMethodID(dvrPlaybackClazz, "onPlaybackStatusChanged", "(I)V"); jclass mediaEventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent"); gFields.mediaEventContext = env->GetFieldID(mediaEventClazz, "mNativeContext", "J"); jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock"); gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V"); gFields.linearBlockSetInternalStateID = Loading Loading @@ -3507,6 +3582,52 @@ static jlong android_media_tv_Tuner_write_dvr_to_array( return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size); } static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) { return (MediaEvent *)env->GetLongField(mediaEventObj, gFields.mediaEventContext); } static jobject android_media_tv_Tuner_media_event_get_linear_block( JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return NULL; } return mediaEventSp->getLinearBlock(); } static jobject android_media_tv_Tuner_media_event_get_audio_handle( JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return NULL; } android::Mutex::Autolock autoLock(mediaEventSp->mLock); uint64_t audioHandle = mediaEventSp->getAudioHandle(); jclass longClazz = env->FindClass("java/lang/Long"); jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V"); jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(audioHandle)); return longObj; } static void android_media_tv_Tuner_media_event_finalize(JNIEnv* env, jobject mediaEventObj) { sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj); if (mediaEventSp == NULL) { ALOGD("Failed get MediaEvent"); return; } android::Mutex::Autolock autoLock(mediaEventSp->mLock); mediaEventSp->mAvHandleRefCnt--; mediaEventSp->finalize(); mediaEventSp->decStrong(mediaEventObj); } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init }, { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup }, Loading Loading @@ -3629,6 +3750,15 @@ static const JNINativeMethod gLnbMethods[] = { { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb }, }; static const JNINativeMethod gMediaEventMethods[] = { { "nativeGetLinearBlock", "()Landroid/media/MediaCodec$LinearBlock;", (void *)android_media_tv_Tuner_media_event_get_linear_block }, { "nativeGetAudioHandle", "()Ljava/lang/Long;", (void *)android_media_tv_Tuner_media_event_get_audio_handle }, { "nativeFinalize", "()V", (void *)android_media_tv_Tuner_media_event_finalize }, }; static bool register_android_media_tv_Tuner(JNIEnv *env) { if (AndroidRuntime::registerNativeMethods( env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) { Loading Loading @@ -3677,6 +3807,13 @@ static bool register_android_media_tv_Tuner(JNIEnv *env) { ALOGE("Failed to register lnb native methods"); return false; } if (AndroidRuntime::registerNativeMethods( env, "android/media/tv/tuner/filter/MediaEvent", gMediaEventMethods, NELEM(gMediaEventMethods)) != JNI_OK) { ALOGE("Failed to register MediaEvent native methods"); return false; } return true; } Loading
media/jni/android_media_tv_Tuner.h +48 −13 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ #define _ANDROID_MEDIA_TV_TUNER_H_ #include <android/hardware/tv/tuner/1.0/ITuner.h> #include <C2BlockInternal.h> #include <C2HandleIonInternal.h> #include <C2ParamDef.h> #include <fmq/MessageQueue.h> #include <fstream> #include <string> #include <unordered_map> #include <utils/Mutex.h> #include <utils/RefBase.h> #include "jni.h" Loading @@ -30,6 +34,7 @@ using ::android::hardware::EventFlag; using ::android::hardware::MQDescriptorSync; using ::android::hardware::MessageQueue; using ::android::hardware::Return; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_vec; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent; Loading Loading @@ -106,15 +111,48 @@ 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::shared_ptr<C2Buffer> mC2Buffer; }; struct Filter : public RefBase { Filter(sp<IFilter> sp, jobject obj); ~Filter(); int close(); sp<IFilter> getIFilter(); sp<IFilter> mFilterSp; std::unique_ptr<MQ> mFilterMQ; EventFlag* mFilterMQEventFlag; jweak mFilterObj; }; struct FilterCallback : public IFilterCallback { ~FilterCallback(); virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent); virtual Return<void> onFilterStatus(const DemuxFilterStatus status); void setFilter(const jobject filter); jobject handleToLinearBlock(const native_handle_t* handle, uint32_t size); void setFilter(const sp<Filter> filter); private: jweak mFilter; sp<IFilter> mIFilter; jobjectArray getSectionEvent( jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events); jobjectArray getMediaEvent( Loading Loading @@ -144,17 +182,6 @@ struct FrontendCallback : public IFrontendCallback { FrontendId mId; }; struct Filter : public RefBase { Filter(sp<IFilter> sp, jobject obj); ~Filter(); int close(); sp<IFilter> getIFilter(); sp<IFilter> mFilterSp; std::unique_ptr<MQ> mFilterMQ; EventFlag* mFilterMQEventFlag; jweak mFilterObj; }; struct TimeFilter : public RefBase { TimeFilter(sp<ITimeFilter> sp, jweak obj); ~TimeFilter(); Loading Loading @@ -219,6 +246,14 @@ private: static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps); }; class C2DataIdInfo : public C2Param { public: C2DataIdInfo(uint32_t index, uint64_t value); private: typedef C2GlobalParam<C2Info, C2Int64Value, 0> DummyInfo; static const size_t kParamSize = sizeof(DummyInfo); }; } // namespace android #endif // _ANDROID_MEDIA_TV_TUNER_H_