Loading media/libmedia/include/media/JAudioAttributes.h +1 −7 Original line number Diff line number Diff line Loading @@ -26,8 +26,7 @@ class JAudioAttributes { public: /* Creates a Java AudioAttributes object. */ static jobject createAudioAttributesObj(JNIEnv *env, const audio_attributes_t* pAttributes, audio_stream_type_t streamType) { const audio_attributes_t* pAttributes) { jclass jBuilderCls = env->FindClass("android/media/AudioAttributes$Builder"); jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V"); Loading Loading @@ -58,11 +57,6 @@ public: // TODO: Handle the 'tags' (char[] to HashSet<String>). // How to parse the char[]? Is there any example of it? // Also, the addTags() method is hidden. } else { // Call AudioAttributes.Builder.setLegacyStreamType().build() jmethodID jSetLegacyStreamType = env->GetMethodID(jBuilderCls, "setLegacyStreamType", "(I)Landroid/media/AudioAttributes$Builder;"); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetLegacyStreamType, streamType); } jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", Loading media/libmediaplayer2/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ cc_library_static { "libstagefright_player2", "libstagefright_rtsp", "libstagefright_timedtext2", "libmedia2_jni_core", ], export_include_dirs: [ Loading media/libmediaplayer2/JAudioTrack.cpp +132 −23 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ namespace android { // TODO: Store Java class/methodID as a member variable in the class. // TODO: Add NULL && Exception checks after every JNI call. JAudioTrack::JAudioTrack( // < Usages of the arguments are below > audio_stream_type_t streamType, // AudioAudioAttributes uint32_t sampleRate, // AudioFormat && bufferSizeInBytes audio_format_t format, // AudioFormat && bufferSizeInBytes audio_channel_mask_t channelMask, // AudioFormat && bufferSizeInBytes Loading @@ -40,8 +39,10 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen float maxRequiredSpeed) { // bufferSizeInBytes JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack"); mAudioTrackCls = (jclass) env->NewGlobalRef(jAudioTrackCls); mAudioTrackCls = reinterpret_cast<jclass>(env->NewGlobalRef(jAudioTrackCls)); env->DeleteLocalRef(jAudioTrackCls); maxRequiredSpeed = std::min(std::max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX); Loading @@ -64,10 +65,13 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V"); jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor); jobject jAudioAttributesObj = JAudioAttributes::createAudioAttributesObj(env, pAttributes); mAudioAttributesObj = reinterpret_cast<jobject>(env->NewGlobalRef(jAudioAttributesObj)); env->DeleteLocalRef(jAudioAttributesObj); jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes", "(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;"); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes, JAudioAttributes::createAudioAttributesObj(env, pAttributes, streamType)); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes, mAudioAttributesObj); jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat", "(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;"); Loading Loading @@ -100,7 +104,9 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen } jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioTrack;"); mAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild); jobject jAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild); mAudioTrackObj = reinterpret_cast<jobject>(env->NewGlobalRef(jAudioTrackObj)); env->DeleteLocalRef(jBuilderObj); if (cbf != NULL) { // Set offload mode callback Loading @@ -118,6 +124,8 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen JAudioTrack::~JAudioTrack() { JNIEnv *env = JavaVMHelper::getJNIEnv(); env->DeleteGlobalRef(mAudioTrackCls); env->DeleteGlobalRef(mAudioTrackObj); env->DeleteGlobalRef(mAudioAttributesObj); } size_t JAudioTrack::frameCount() { Loading Loading @@ -151,21 +159,21 @@ status_t JAudioTrack::getPosition(uint32_t *position) { return NO_ERROR; } bool JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { status_t JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioTimeStampCls = env->FindClass("android/media/AudioTimestamp"); jobject jAudioTimeStampObj = env->AllocObject(jAudioTimeStampCls); jfieldID jFramePosition = env->GetFieldID(jAudioTimeStampCls, "framePosition", "L"); jfieldID jNanoTime = env->GetFieldID(jAudioTimeStampCls, "nanoTime", "L"); jfieldID jFramePosition = env->GetFieldID(jAudioTimeStampCls, "framePosition", "J"); jfieldID jNanoTime = env->GetFieldID(jAudioTimeStampCls, "nanoTime", "J"); jmethodID jGetTimestamp = env->GetMethodID(mAudioTrackCls, "getTimestamp", "(Landroid/media/AudioTimestamp)B"); "getTimestamp", "(Landroid/media/AudioTimestamp;)Z"); bool success = env->CallBooleanMethod(mAudioTrackObj, jGetTimestamp, jAudioTimeStampObj); if (!success) { return false; return NO_INIT; } long long framePosition = env->GetLongField(jAudioTimeStampObj, jFramePosition); Loading @@ -178,7 +186,7 @@ bool JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { timestamp.mTime = ts; timestamp.mPosition = (uint32_t) framePosition; return true; return NO_ERROR; } status_t JAudioTrack::getTimestamp(ExtendedTimestamp *timestamp __unused) { Loading Loading @@ -423,6 +431,35 @@ audio_format_t JAudioTrack::format() { return audioFormatToNative(javaFormat); } size_t JAudioTrack::frameSize() { JNIEnv *env = JavaVMHelper::getJNIEnv(); // TODO: Calculated here implementing the logic in AudioTrack.java // wait for AudioTrack.java exposing this parameter (i.e. getFrameSizeInBtytes()) jmethodID jGetAudioFormat = env->GetMethodID(mAudioTrackCls, "getAudioFormat", "()I"); int javaFormat = env->CallIntMethod(mAudioTrackObj, jGetAudioFormat); jclass jAudioFormatCls = env->FindClass("android/media/AudioFormat"); jmethodID jIsEncodingLinearFrames = env->GetStaticMethodID( jAudioFormatCls, "isEncodingLinearFrames", "(I)Z"); jboolean javaIsEncodingLinearFrames = env->CallStaticBooleanMethod( jAudioFormatCls, jIsEncodingLinearFrames, javaFormat); if (javaIsEncodingLinearFrames == false) { return 1; } jmethodID jGetBytesPerSample = env->GetStaticMethodID(jAudioFormatCls, "getBytesPerSample", "(I)I"); int javaBytesPerSample = env->CallStaticIntMethod(jAudioFormatCls, jGetBytesPerSample, javaFormat); jmethodID jGetChannelCount = env->GetMethodID(mAudioTrackCls, "getChannelCount", "()I"); int javaChannelCount = env->CallIntMethod(mAudioTrackObj, jGetChannelCount); return javaChannelCount * javaBytesPerSample; } status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const { String8 result; Loading @@ -432,10 +469,6 @@ status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const // TODO: Remove logs that includes unavailable information from below. // result.appendFormat(" status(%d), state(%d), session Id(%d), flags(%#x)\n", // mStatus, mState, mSessionId, mFlags); // result.appendFormat(" stream type(%d), left - right volume(%f, %f)\n", // (mStreamType == AUDIO_STREAM_DEFAULT) ? // audio_attributes_to_stream_type(&mAttributes) : mStreamType, // mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]); // result.appendFormat(" format(%#x), channel mask(%#x), channel count(%u)\n", // format(), mChannelMask, channelCount()); // result.appendFormat(" sample rate(%u), original sample rate(%u), speed(%f)\n", Loading @@ -462,7 +495,7 @@ audio_port_handle_t JAudioTrack::getRoutedDeviceId() { return AUDIO_PORT_HANDLE_NONE; } jclass jAudioDeviceInfoCls = env->FindClass("Landroid/media/AudioDeviceInfo"); jclass jAudioDeviceInfoCls = env->FindClass("android/media/AudioDeviceInfo"); jmethodID jGetId = env->GetMethodID(jAudioDeviceInfoCls, "getId", "()I"); jint routedDeviceId = env->CallIntMethod(jAudioDeviceInfoObj, jGetId); return routedDeviceId; Loading @@ -478,13 +511,22 @@ audio_session_t JAudioTrack::getAudioSessionId() { status_t JAudioTrack::setOutputDevice(audio_port_handle_t deviceId) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jMP2ImplCls = env->FindClass("android/media/MediaPlayer2Impl"); jmethodID jSetAudioOutputDeviceById = env->GetMethodID( jmethodID jSetAudioOutputDeviceById = env->GetStaticMethodID( jMP2ImplCls, "setAudioOutputDeviceById", "(Landroid/media/AudioTrack;I)Z"); jboolean result = env->CallStaticBooleanMethod( jMP2ImplCls, jSetAudioOutputDeviceById, mAudioTrackObj, deviceId); return result == true ? NO_ERROR : BAD_VALUE; } audio_stream_type_t JAudioTrack::getAudioStreamType() { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioAttributesCls = env->FindClass("android/media/AudioAttributes"); jmethodID jGetVolumeControlStream = env->GetMethodID(jAudioAttributesCls, "getVolumeControlStream", "()I"); int javaAudioStreamType = env->CallIntMethod(mAudioAttributesObj, jGetVolumeControlStream); return (audio_stream_type_t)javaAudioStreamType; } status_t JAudioTrack::pendingDuration(int32_t *msec) { if (msec == nullptr) { return BAD_VALUE; Loading Loading @@ -526,18 +568,85 @@ status_t JAudioTrack::pendingDuration(int32_t *msec) { return NO_ERROR; } status_t JAudioTrack::addAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback __unused) { // TODO: Implement this after appropriate Java AudioTrack method is available. status_t JAudioTrack::addAudioDeviceCallback(jobject listener, jobject handler) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jmethodID jAddOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls, "addOnRoutingChangedListener", "(Landroid/media/AudioRouting$OnRoutingChangedListener;Landroid/os/Handler;)V"); env->CallVoidMethod(mAudioTrackObj, jAddOnRoutingChangedListener, listener, handler); return NO_ERROR; } status_t JAudioTrack::removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback __unused) { // TODO: Implement this after appropriate Java AudioTrack method is available. status_t JAudioTrack::removeAudioDeviceCallback(jobject listener) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jmethodID jRemoveOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls, "removeOnRoutingChangedListener", "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V"); env->CallVoidMethod(mAudioTrackObj, jRemoveOnRoutingChangedListener, listener); return NO_ERROR; } void JAudioTrack::registerRoutingDelegates( std::vector<std::pair<jobject, jobject>>& routingDelegates) { for (std::vector<std::pair<jobject, jobject>>::iterator it = routingDelegates.begin(); it != routingDelegates.end(); it++) { addAudioDeviceCallback(it->second, getHandler(it->second)); } } ///////////////////////////////////////////////////////////// /// Static methods begin /// ///////////////////////////////////////////////////////////// jobject JAudioTrack::getListener(const jobject routingDelegateObj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate"); jmethodID jGetListener = env->GetMethodID(jRoutingDelegateCls, "getListener", "()Landroid/media/AudioRouting$OnRoutingChangedListener;"); return env->CallObjectMethod(routingDelegateObj, jGetListener); } jobject JAudioTrack::getHandler(const jobject routingDelegateObj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate"); jmethodID jGetHandler = env->GetMethodID(jRoutingDelegateCls, "getHandler", "()Landroid/os/Handler;"); return env->CallObjectMethod(routingDelegateObj, jGetHandler); } jobject JAudioTrack::addGlobalRef(const jobject obj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); return reinterpret_cast<jobject>(env->NewGlobalRef(obj)); } status_t JAudioTrack::removeGlobalRef(const jobject obj) { if (obj == NULL) { return BAD_VALUE; } JNIEnv *env = JavaVMHelper::getJNIEnv(); env->DeleteGlobalRef(obj); return NO_ERROR; } jobject JAudioTrack::findByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key) { JNIEnv *env = JavaVMHelper::getJNIEnv(); for (std::vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) { if (env->IsSameObject(it->first, key)) { return it->second; } } return nullptr; } void JAudioTrack::eraseByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key) { JNIEnv *env = JavaVMHelper::getJNIEnv(); for (std::vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) { if (env->IsSameObject(it->first, key)) { mp.erase(it); return; } } } ///////////////////////////////////////////////////////////// /// Private method begins /// ///////////////////////////////////////////////////////////// Loading media/libmediaplayer2/MediaPlayer2AudioOutput.cpp +174 −195 File changed.Preview size limit exceeded, changes collapsed. Show changes media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h +69 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_JAUDIOTRACK_H #define ANDROID_JAUDIOTRACK_H #include <vector> #include <utility> #include <jni.h> #include <media/AudioResamplerPublic.h> #include <media/AudioSystem.h> Loading @@ -29,7 +31,7 @@ namespace android { class JAudioTrack { class JAudioTrack : public RefBase { public: /* Events used by AudioTrack callback function (callback_t). Loading @@ -37,6 +39,8 @@ public: */ enum event_type { EVENT_MORE_DATA = 0, // Request to write more data to buffer. EVENT_UNDERRUN = 1, // Buffer underrun occurred. This will not occur for // static tracks. EVENT_NEW_IAUDIOTRACK = 6, // IAudioTrack was re-created, either due to re-routing and // voluntary invalidation by mediaserver, or mediaserver crash. EVENT_STREAM_END = 7, // Sent after all the buffers queued in AF and HW are played Loading Loading @@ -104,8 +108,7 @@ public: * * TODO: Revive removed arguments after offload mode is supported. */ JAudioTrack(audio_stream_type_t streamType, uint32_t sampleRate, JAudioTrack(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, callback_t cbf, Loading Loading @@ -158,10 +161,10 @@ public: * Caution: calling this method too often may be inefficient; * if you need a high resolution mapping between frame position and presentation time, * consider implementing that at application level, based on the low resolution timestamps. * Returns true if timestamp is valid. * The timestamp parameter is undefined on return, if false is returned. * Returns NO_ERROR if timestamp is valid. * NO_INIT if finds error, and timestamp parameter will be undefined on return. */ bool getTimestamp(AudioTimestamp& timestamp); status_t getTimestamp(AudioTimestamp& timestamp); // TODO: This doc is just copied from AudioTrack.h. Revise it after implemenation. /* Return the extended timestamp, with additional timebase info and improved drain behavior. Loading Loading @@ -324,6 +327,8 @@ public: audio_format_t format(); size_t frameSize(); /* * Dumps the state of an audio track. * Not a general-purpose API; intended only for use by media player service to dump its tracks. Loading Loading @@ -355,6 +360,11 @@ public: /* Returns the flags */ audio_output_flags_t getFlags() const { return mFlags; } /* We don't keep stream type here, * instead, we keep attributes and call getVolumeControlStream() to get stream type */ audio_stream_type_t getAudioStreamType(); /* Obtain the pending duration in milliseconds for playback of pure PCM data remaining in * AudioTrack. * Loading @@ -369,33 +379,75 @@ public: * Replaces any previously installed callback. * * Parameters: * * callback: The callback interface * Listener: the listener to receive notification of rerouting events. * Handler: the handler to handler the rerouting events. * * Returns NO_ERROR if successful. * INVALID_OPERATION if the same callback is already installed. * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable * BAD_VALUE if the callback is NULL * (TODO) INVALID_OPERATION if the same callback is already installed. * (TODO) NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable * (TODO) BAD_VALUE if the callback is NULL */ status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback); status_t addAudioDeviceCallback(jobject listener, jobject rd); /* Removes an AudioDeviceCallback. * * Parameters: * * callback: The callback interface * Listener: the listener to receive notification of rerouting events. * * Returns NO_ERROR if successful. * INVALID_OPERATION if the callback is not installed * BAD_VALUE if the callback is NULL * (TODO) INVALID_OPERATION if the callback is not installed * (TODO) BAD_VALUE if the callback is NULL */ status_t removeAudioDeviceCallback(jobject listener); /* Register all backed-up routing delegates. * * Parameters: * routingDelegates: backed-up routing delegates * */ void registerRoutingDelegates(std::vector<std::pair<jobject, jobject>>& routingDelegates); /* get listener from RoutingDelegate object */ static jobject getListener(const jobject routingDelegateObj); /* get handler from RoutingDelegate object */ static jobject getHandler(const jobject routingDelegateObj); /* convert local reference to global reference. */ static jobject addGlobalRef(const jobject obj); /* erase global reference. * * Returns NO_ERROR if succeeds * BAD_VALUE if obj is NULL */ static status_t removeGlobalRef(const jobject obj); /* * Parameters: * map and key * * Returns value if key is in the map * nullptr if key is not in the map */ static jobject findByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key); /* * Parameters: * map and key */ status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback); static void eraseByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key); private: audio_output_flags_t mFlags; jclass mAudioTrackCls; jobject mAudioTrackObj; jobject mAudioAttributesObj; /* Creates a Java VolumeShaper.Configuration object from VolumeShaper::Configuration */ jobject createVolumeShaperConfigurationObj( Loading Loading
media/libmedia/include/media/JAudioAttributes.h +1 −7 Original line number Diff line number Diff line Loading @@ -26,8 +26,7 @@ class JAudioAttributes { public: /* Creates a Java AudioAttributes object. */ static jobject createAudioAttributesObj(JNIEnv *env, const audio_attributes_t* pAttributes, audio_stream_type_t streamType) { const audio_attributes_t* pAttributes) { jclass jBuilderCls = env->FindClass("android/media/AudioAttributes$Builder"); jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V"); Loading Loading @@ -58,11 +57,6 @@ public: // TODO: Handle the 'tags' (char[] to HashSet<String>). // How to parse the char[]? Is there any example of it? // Also, the addTags() method is hidden. } else { // Call AudioAttributes.Builder.setLegacyStreamType().build() jmethodID jSetLegacyStreamType = env->GetMethodID(jBuilderCls, "setLegacyStreamType", "(I)Landroid/media/AudioAttributes$Builder;"); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetLegacyStreamType, streamType); } jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", Loading
media/libmediaplayer2/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ cc_library_static { "libstagefright_player2", "libstagefright_rtsp", "libstagefright_timedtext2", "libmedia2_jni_core", ], export_include_dirs: [ Loading
media/libmediaplayer2/JAudioTrack.cpp +132 −23 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ namespace android { // TODO: Store Java class/methodID as a member variable in the class. // TODO: Add NULL && Exception checks after every JNI call. JAudioTrack::JAudioTrack( // < Usages of the arguments are below > audio_stream_type_t streamType, // AudioAudioAttributes uint32_t sampleRate, // AudioFormat && bufferSizeInBytes audio_format_t format, // AudioFormat && bufferSizeInBytes audio_channel_mask_t channelMask, // AudioFormat && bufferSizeInBytes Loading @@ -40,8 +39,10 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen float maxRequiredSpeed) { // bufferSizeInBytes JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack"); mAudioTrackCls = (jclass) env->NewGlobalRef(jAudioTrackCls); mAudioTrackCls = reinterpret_cast<jclass>(env->NewGlobalRef(jAudioTrackCls)); env->DeleteLocalRef(jAudioTrackCls); maxRequiredSpeed = std::min(std::max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX); Loading @@ -64,10 +65,13 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V"); jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor); jobject jAudioAttributesObj = JAudioAttributes::createAudioAttributesObj(env, pAttributes); mAudioAttributesObj = reinterpret_cast<jobject>(env->NewGlobalRef(jAudioAttributesObj)); env->DeleteLocalRef(jAudioAttributesObj); jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes", "(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;"); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes, JAudioAttributes::createAudioAttributesObj(env, pAttributes, streamType)); jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes, mAudioAttributesObj); jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat", "(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;"); Loading Loading @@ -100,7 +104,9 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen } jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioTrack;"); mAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild); jobject jAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild); mAudioTrackObj = reinterpret_cast<jobject>(env->NewGlobalRef(jAudioTrackObj)); env->DeleteLocalRef(jBuilderObj); if (cbf != NULL) { // Set offload mode callback Loading @@ -118,6 +124,8 @@ JAudioTrack::JAudioTrack( // < Usages of the argumen JAudioTrack::~JAudioTrack() { JNIEnv *env = JavaVMHelper::getJNIEnv(); env->DeleteGlobalRef(mAudioTrackCls); env->DeleteGlobalRef(mAudioTrackObj); env->DeleteGlobalRef(mAudioAttributesObj); } size_t JAudioTrack::frameCount() { Loading Loading @@ -151,21 +159,21 @@ status_t JAudioTrack::getPosition(uint32_t *position) { return NO_ERROR; } bool JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { status_t JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioTimeStampCls = env->FindClass("android/media/AudioTimestamp"); jobject jAudioTimeStampObj = env->AllocObject(jAudioTimeStampCls); jfieldID jFramePosition = env->GetFieldID(jAudioTimeStampCls, "framePosition", "L"); jfieldID jNanoTime = env->GetFieldID(jAudioTimeStampCls, "nanoTime", "L"); jfieldID jFramePosition = env->GetFieldID(jAudioTimeStampCls, "framePosition", "J"); jfieldID jNanoTime = env->GetFieldID(jAudioTimeStampCls, "nanoTime", "J"); jmethodID jGetTimestamp = env->GetMethodID(mAudioTrackCls, "getTimestamp", "(Landroid/media/AudioTimestamp)B"); "getTimestamp", "(Landroid/media/AudioTimestamp;)Z"); bool success = env->CallBooleanMethod(mAudioTrackObj, jGetTimestamp, jAudioTimeStampObj); if (!success) { return false; return NO_INIT; } long long framePosition = env->GetLongField(jAudioTimeStampObj, jFramePosition); Loading @@ -178,7 +186,7 @@ bool JAudioTrack::getTimestamp(AudioTimestamp& timestamp) { timestamp.mTime = ts; timestamp.mPosition = (uint32_t) framePosition; return true; return NO_ERROR; } status_t JAudioTrack::getTimestamp(ExtendedTimestamp *timestamp __unused) { Loading Loading @@ -423,6 +431,35 @@ audio_format_t JAudioTrack::format() { return audioFormatToNative(javaFormat); } size_t JAudioTrack::frameSize() { JNIEnv *env = JavaVMHelper::getJNIEnv(); // TODO: Calculated here implementing the logic in AudioTrack.java // wait for AudioTrack.java exposing this parameter (i.e. getFrameSizeInBtytes()) jmethodID jGetAudioFormat = env->GetMethodID(mAudioTrackCls, "getAudioFormat", "()I"); int javaFormat = env->CallIntMethod(mAudioTrackObj, jGetAudioFormat); jclass jAudioFormatCls = env->FindClass("android/media/AudioFormat"); jmethodID jIsEncodingLinearFrames = env->GetStaticMethodID( jAudioFormatCls, "isEncodingLinearFrames", "(I)Z"); jboolean javaIsEncodingLinearFrames = env->CallStaticBooleanMethod( jAudioFormatCls, jIsEncodingLinearFrames, javaFormat); if (javaIsEncodingLinearFrames == false) { return 1; } jmethodID jGetBytesPerSample = env->GetStaticMethodID(jAudioFormatCls, "getBytesPerSample", "(I)I"); int javaBytesPerSample = env->CallStaticIntMethod(jAudioFormatCls, jGetBytesPerSample, javaFormat); jmethodID jGetChannelCount = env->GetMethodID(mAudioTrackCls, "getChannelCount", "()I"); int javaChannelCount = env->CallIntMethod(mAudioTrackObj, jGetChannelCount); return javaChannelCount * javaBytesPerSample; } status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const { String8 result; Loading @@ -432,10 +469,6 @@ status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const // TODO: Remove logs that includes unavailable information from below. // result.appendFormat(" status(%d), state(%d), session Id(%d), flags(%#x)\n", // mStatus, mState, mSessionId, mFlags); // result.appendFormat(" stream type(%d), left - right volume(%f, %f)\n", // (mStreamType == AUDIO_STREAM_DEFAULT) ? // audio_attributes_to_stream_type(&mAttributes) : mStreamType, // mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]); // result.appendFormat(" format(%#x), channel mask(%#x), channel count(%u)\n", // format(), mChannelMask, channelCount()); // result.appendFormat(" sample rate(%u), original sample rate(%u), speed(%f)\n", Loading @@ -462,7 +495,7 @@ audio_port_handle_t JAudioTrack::getRoutedDeviceId() { return AUDIO_PORT_HANDLE_NONE; } jclass jAudioDeviceInfoCls = env->FindClass("Landroid/media/AudioDeviceInfo"); jclass jAudioDeviceInfoCls = env->FindClass("android/media/AudioDeviceInfo"); jmethodID jGetId = env->GetMethodID(jAudioDeviceInfoCls, "getId", "()I"); jint routedDeviceId = env->CallIntMethod(jAudioDeviceInfoObj, jGetId); return routedDeviceId; Loading @@ -478,13 +511,22 @@ audio_session_t JAudioTrack::getAudioSessionId() { status_t JAudioTrack::setOutputDevice(audio_port_handle_t deviceId) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jMP2ImplCls = env->FindClass("android/media/MediaPlayer2Impl"); jmethodID jSetAudioOutputDeviceById = env->GetMethodID( jmethodID jSetAudioOutputDeviceById = env->GetStaticMethodID( jMP2ImplCls, "setAudioOutputDeviceById", "(Landroid/media/AudioTrack;I)Z"); jboolean result = env->CallStaticBooleanMethod( jMP2ImplCls, jSetAudioOutputDeviceById, mAudioTrackObj, deviceId); return result == true ? NO_ERROR : BAD_VALUE; } audio_stream_type_t JAudioTrack::getAudioStreamType() { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jAudioAttributesCls = env->FindClass("android/media/AudioAttributes"); jmethodID jGetVolumeControlStream = env->GetMethodID(jAudioAttributesCls, "getVolumeControlStream", "()I"); int javaAudioStreamType = env->CallIntMethod(mAudioAttributesObj, jGetVolumeControlStream); return (audio_stream_type_t)javaAudioStreamType; } status_t JAudioTrack::pendingDuration(int32_t *msec) { if (msec == nullptr) { return BAD_VALUE; Loading Loading @@ -526,18 +568,85 @@ status_t JAudioTrack::pendingDuration(int32_t *msec) { return NO_ERROR; } status_t JAudioTrack::addAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback __unused) { // TODO: Implement this after appropriate Java AudioTrack method is available. status_t JAudioTrack::addAudioDeviceCallback(jobject listener, jobject handler) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jmethodID jAddOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls, "addOnRoutingChangedListener", "(Landroid/media/AudioRouting$OnRoutingChangedListener;Landroid/os/Handler;)V"); env->CallVoidMethod(mAudioTrackObj, jAddOnRoutingChangedListener, listener, handler); return NO_ERROR; } status_t JAudioTrack::removeAudioDeviceCallback( const sp<AudioSystem::AudioDeviceCallback>& callback __unused) { // TODO: Implement this after appropriate Java AudioTrack method is available. status_t JAudioTrack::removeAudioDeviceCallback(jobject listener) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jmethodID jRemoveOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls, "removeOnRoutingChangedListener", "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V"); env->CallVoidMethod(mAudioTrackObj, jRemoveOnRoutingChangedListener, listener); return NO_ERROR; } void JAudioTrack::registerRoutingDelegates( std::vector<std::pair<jobject, jobject>>& routingDelegates) { for (std::vector<std::pair<jobject, jobject>>::iterator it = routingDelegates.begin(); it != routingDelegates.end(); it++) { addAudioDeviceCallback(it->second, getHandler(it->second)); } } ///////////////////////////////////////////////////////////// /// Static methods begin /// ///////////////////////////////////////////////////////////// jobject JAudioTrack::getListener(const jobject routingDelegateObj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate"); jmethodID jGetListener = env->GetMethodID(jRoutingDelegateCls, "getListener", "()Landroid/media/AudioRouting$OnRoutingChangedListener;"); return env->CallObjectMethod(routingDelegateObj, jGetListener); } jobject JAudioTrack::getHandler(const jobject routingDelegateObj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate"); jmethodID jGetHandler = env->GetMethodID(jRoutingDelegateCls, "getHandler", "()Landroid/os/Handler;"); return env->CallObjectMethod(routingDelegateObj, jGetHandler); } jobject JAudioTrack::addGlobalRef(const jobject obj) { JNIEnv *env = JavaVMHelper::getJNIEnv(); return reinterpret_cast<jobject>(env->NewGlobalRef(obj)); } status_t JAudioTrack::removeGlobalRef(const jobject obj) { if (obj == NULL) { return BAD_VALUE; } JNIEnv *env = JavaVMHelper::getJNIEnv(); env->DeleteGlobalRef(obj); return NO_ERROR; } jobject JAudioTrack::findByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key) { JNIEnv *env = JavaVMHelper::getJNIEnv(); for (std::vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) { if (env->IsSameObject(it->first, key)) { return it->second; } } return nullptr; } void JAudioTrack::eraseByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key) { JNIEnv *env = JavaVMHelper::getJNIEnv(); for (std::vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) { if (env->IsSameObject(it->first, key)) { mp.erase(it); return; } } } ///////////////////////////////////////////////////////////// /// Private method begins /// ///////////////////////////////////////////////////////////// Loading
media/libmediaplayer2/MediaPlayer2AudioOutput.cpp +174 −195 File changed.Preview size limit exceeded, changes collapsed. Show changes
media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h +69 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_JAUDIOTRACK_H #define ANDROID_JAUDIOTRACK_H #include <vector> #include <utility> #include <jni.h> #include <media/AudioResamplerPublic.h> #include <media/AudioSystem.h> Loading @@ -29,7 +31,7 @@ namespace android { class JAudioTrack { class JAudioTrack : public RefBase { public: /* Events used by AudioTrack callback function (callback_t). Loading @@ -37,6 +39,8 @@ public: */ enum event_type { EVENT_MORE_DATA = 0, // Request to write more data to buffer. EVENT_UNDERRUN = 1, // Buffer underrun occurred. This will not occur for // static tracks. EVENT_NEW_IAUDIOTRACK = 6, // IAudioTrack was re-created, either due to re-routing and // voluntary invalidation by mediaserver, or mediaserver crash. EVENT_STREAM_END = 7, // Sent after all the buffers queued in AF and HW are played Loading Loading @@ -104,8 +108,7 @@ public: * * TODO: Revive removed arguments after offload mode is supported. */ JAudioTrack(audio_stream_type_t streamType, uint32_t sampleRate, JAudioTrack(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, callback_t cbf, Loading Loading @@ -158,10 +161,10 @@ public: * Caution: calling this method too often may be inefficient; * if you need a high resolution mapping between frame position and presentation time, * consider implementing that at application level, based on the low resolution timestamps. * Returns true if timestamp is valid. * The timestamp parameter is undefined on return, if false is returned. * Returns NO_ERROR if timestamp is valid. * NO_INIT if finds error, and timestamp parameter will be undefined on return. */ bool getTimestamp(AudioTimestamp& timestamp); status_t getTimestamp(AudioTimestamp& timestamp); // TODO: This doc is just copied from AudioTrack.h. Revise it after implemenation. /* Return the extended timestamp, with additional timebase info and improved drain behavior. Loading Loading @@ -324,6 +327,8 @@ public: audio_format_t format(); size_t frameSize(); /* * Dumps the state of an audio track. * Not a general-purpose API; intended only for use by media player service to dump its tracks. Loading Loading @@ -355,6 +360,11 @@ public: /* Returns the flags */ audio_output_flags_t getFlags() const { return mFlags; } /* We don't keep stream type here, * instead, we keep attributes and call getVolumeControlStream() to get stream type */ audio_stream_type_t getAudioStreamType(); /* Obtain the pending duration in milliseconds for playback of pure PCM data remaining in * AudioTrack. * Loading @@ -369,33 +379,75 @@ public: * Replaces any previously installed callback. * * Parameters: * * callback: The callback interface * Listener: the listener to receive notification of rerouting events. * Handler: the handler to handler the rerouting events. * * Returns NO_ERROR if successful. * INVALID_OPERATION if the same callback is already installed. * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable * BAD_VALUE if the callback is NULL * (TODO) INVALID_OPERATION if the same callback is already installed. * (TODO) NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable * (TODO) BAD_VALUE if the callback is NULL */ status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback); status_t addAudioDeviceCallback(jobject listener, jobject rd); /* Removes an AudioDeviceCallback. * * Parameters: * * callback: The callback interface * Listener: the listener to receive notification of rerouting events. * * Returns NO_ERROR if successful. * INVALID_OPERATION if the callback is not installed * BAD_VALUE if the callback is NULL * (TODO) INVALID_OPERATION if the callback is not installed * (TODO) BAD_VALUE if the callback is NULL */ status_t removeAudioDeviceCallback(jobject listener); /* Register all backed-up routing delegates. * * Parameters: * routingDelegates: backed-up routing delegates * */ void registerRoutingDelegates(std::vector<std::pair<jobject, jobject>>& routingDelegates); /* get listener from RoutingDelegate object */ static jobject getListener(const jobject routingDelegateObj); /* get handler from RoutingDelegate object */ static jobject getHandler(const jobject routingDelegateObj); /* convert local reference to global reference. */ static jobject addGlobalRef(const jobject obj); /* erase global reference. * * Returns NO_ERROR if succeeds * BAD_VALUE if obj is NULL */ static status_t removeGlobalRef(const jobject obj); /* * Parameters: * map and key * * Returns value if key is in the map * nullptr if key is not in the map */ static jobject findByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key); /* * Parameters: * map and key */ status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback); static void eraseByKey(std::vector<std::pair<jobject, jobject>>& mp, const jobject key); private: audio_output_flags_t mFlags; jclass mAudioTrackCls; jobject mAudioTrackObj; jobject mAudioAttributesObj; /* Creates a Java VolumeShaper.Configuration object from VolumeShaper::Configuration */ jobject createVolumeShaperConfigurationObj( Loading