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