MediaPlayer2: create MP2AudioOutput in constructor
Move MP2AudioOutput creator from setDataSource() to constructor.
Test: MediaPlayer2Test, RoutingTest
Change-Id: Ibe19c8a259c735ea2b5822f769babaf4d7f2bed0
diff --git a/media/libmediaplayer2/JAudioTrack.cpp b/media/libmediaplayer2/JAudioTrack.cpp
index 543f700..cb139c9 100644
--- a/media/libmediaplayer2/JAudioTrack.cpp
+++ b/media/libmediaplayer2/JAudioTrack.cpp
@@ -35,7 +35,7 @@
void* user, // Offload
size_t frameCount, // bufferSizeInBytes
audio_session_t sessionId, // AudioTrack
- const audio_attributes_t* pAttributes, // AudioAttributes
+ const jobject attributes, // AudioAttributes
float maxRequiredSpeed) { // bufferSizeInBytes
JNIEnv *env = JavaVMHelper::getJNIEnv();
@@ -65,13 +65,17 @@
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);
+ if (attributes != NULL) {
+ mAudioAttributesObj = new JObjectHolder(attributes);
+ } else {
+ mAudioAttributesObj = new JObjectHolder(
+ JAudioAttributes::createAudioAttributesObj(env, NULL));
+ }
jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes",
"(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;");
- jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioAttributes, mAudioAttributesObj);
+ jBuilderObj = env->CallObjectMethod(jBuilderObj,
+ jSetAudioAttributes, mAudioAttributesObj->getJObject());
jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat",
"(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;");
@@ -125,7 +129,6 @@
JNIEnv *env = JavaVMHelper::getJNIEnv();
env->DeleteGlobalRef(mAudioTrackCls);
env->DeleteGlobalRef(mAudioTrackObj);
- env->DeleteGlobalRef(mAudioAttributesObj);
}
size_t JAudioTrack::frameCount() {
@@ -509,11 +512,15 @@
}
audio_stream_type_t JAudioTrack::getAudioStreamType() {
+ if (mAudioAttributesObj == NULL) {
+ return AUDIO_STREAM_DEFAULT;
+ }
JNIEnv *env = JavaVMHelper::getJNIEnv();
jclass jAudioAttributesCls = env->FindClass("android/media/AudioAttributes");
jmethodID jGetVolumeControlStream = env->GetMethodID(jAudioAttributesCls,
"getVolumeControlStream", "()I");
- int javaAudioStreamType = env->CallIntMethod(mAudioAttributesObj, jGetVolumeControlStream);
+ int javaAudioStreamType = env->CallIntMethod(
+ mAudioAttributesObj->getJObject(), jGetVolumeControlStream);
return (audio_stream_type_t)javaAudioStreamType;
}
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
index 149f243..3040c2d 100644
--- a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
+++ b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
@@ -60,7 +60,7 @@
}
MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
- const audio_attributes_t* attr, std::vector<jobject>& routingDelegatesBackup)
+ const jobject attributes)
: mCallback(nullptr),
mCallbackCookie(nullptr),
mCallbackData(nullptr),
@@ -76,22 +76,13 @@
mAuxEffectId(0),
mFlags(AUDIO_OUTPUT_FLAG_NONE) {
ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
- if (attr != nullptr) {
- mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- if (mAttributes != nullptr) {
- memcpy(mAttributes, attr, sizeof(audio_attributes_t));
- }
- } else {
- mAttributes = nullptr;
+
+ if (attributes != nullptr) {
+ mAttributes = new JObjectHolder(attributes);
}
setMinBufferCount();
mRoutingDelegates.clear();
- for (auto routingDelegate : routingDelegatesBackup) {
- mRoutingDelegates.push_back(std::pair<jobject, jobject>(
- JAudioTrack::getListener(routingDelegate), routingDelegate));
- }
- routingDelegatesBackup.clear();
}
MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
@@ -99,7 +90,6 @@
JAudioTrack::removeGlobalRef(routingDelegate.second);
}
close();
- free(mAttributes);
delete mCallbackData;
}
@@ -251,16 +241,10 @@
return status;
}
-void MediaPlayer2AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
+void MediaPlayer2AudioOutput::setAudioAttributes(const jobject attributes) {
Mutex::Autolock lock(mLock);
- if (attributes == nullptr) {
- free(mAttributes);
- mAttributes = nullptr;
- } else {
- if (mAttributes == nullptr) {
- mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- }
- memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
+ if (attributes != nullptr) {
+ sp<JObjectHolder> x = new JObjectHolder(attributes);
}
}
@@ -325,7 +309,7 @@
newcbd,
frameCount,
mSessionId,
- mAttributes,
+ mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
1.0f); // default value for maxRequiredSpeed
} else {
// TODO: Due to buffer memory concerns, we use a max target playback speed
@@ -344,7 +328,7 @@
nullptr,
frameCount,
mSessionId,
- mAttributes,
+ mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
targetSpeed);
}
@@ -569,15 +553,6 @@
return NO_ERROR;
}
-void MediaPlayer2AudioOutput::copyAudioDeviceCallback(
- std::vector<jobject>& routingDelegateTarget) {
- ALOGV("copyAudioDeviceCallback");
- for (std::vector<std::pair<jobject, jobject>>::iterator it = mRoutingDelegates.begin();
- it != mRoutingDelegates.end(); it++) {
- routingDelegateTarget.push_back(it->second);
- }
-}
-
// static
void MediaPlayer2AudioOutput::CallbackWrapper(
int event, void *cookie, void *info) {
@@ -655,6 +630,11 @@
return mSessionId;
}
+void MediaPlayer2AudioOutput::setSessionId(const audio_session_t id) {
+ Mutex::Autolock lock(mLock);
+ mSessionId = id;
+}
+
uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
Mutex::Autolock lock(mLock);
if (mJAudioTrack == 0) {
diff --git a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h b/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
index 6122687..13cf85a 100644
--- a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
+++ b/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
@@ -25,7 +25,7 @@
#include <media/VolumeShaper.h>
#include <system/audio.h>
#include <utils/Errors.h>
-
+#include <mediaplayer2/JObjectHolder.h>
#include <media/AudioTimestamp.h> // It has dependency on audio.h/Errors.h, but doesn't
// include them in it. Therefore it is included here at last.
@@ -115,7 +115,7 @@
void* user,
size_t frameCount = 0,
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- const audio_attributes_t* pAttributes = NULL,
+ const jobject pAttributes = NULL,
float maxRequiredSpeed = 1.0f);
/*
@@ -446,7 +446,7 @@
jclass mAudioTrackCls;
jobject mAudioTrackObj;
- jobject mAudioAttributesObj;
+ sp<JObjectHolder> mAudioAttributesObj;
/* Creates a Java VolumeShaper.Configuration object from VolumeShaper::Configuration */
jobject createVolumeShaperConfigurationObj(
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
index d13c54c..fc020ca 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
@@ -41,8 +41,7 @@
MediaPlayer2AudioOutput(audio_session_t sessionId,
uid_t uid,
int pid,
- const audio_attributes_t * attr,
- std::vector<jobject>& routingDelegatesBackup);
+ const jobject attributes);
virtual ~MediaPlayer2AudioOutput();
virtual bool ready() const {
@@ -59,6 +58,7 @@
virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
virtual status_t getFramesWritten(uint32_t *frameswritten) const;
virtual audio_session_t getSessionId() const;
+ virtual void setSessionId(const audio_session_t id);
virtual uint32_t getSampleRate() const;
virtual int64_t getBufferDurationInUs() const;
@@ -76,7 +76,7 @@
virtual void flush();
virtual void pause();
virtual void close();
- void setAudioAttributes(const audio_attributes_t * attributes);
+ void setAudioAttributes(const jobject attributes);
virtual audio_stream_type_t getAudioStreamType() const;
void setVolume(float volume);
@@ -99,7 +99,6 @@
virtual jobject getRoutedDevice();
virtual status_t addAudioDeviceCallback(jobject routingDelegate);
virtual status_t removeAudioDeviceCallback(jobject listener);
- virtual void copyAudioDeviceCallback(std::vector<jobject>& routingDelegateTarget);
private:
static void setMinBufferCount();
@@ -112,7 +111,7 @@
AudioCallback mCallback;
void * mCallbackCookie;
CallbackData * mCallbackData;
- audio_attributes_t * mAttributes;
+ sp<JObjectHolder> mAttributes;
float mVolume;
AudioPlaybackRate mPlaybackRate;
uint32_t mSampleRateHz; // sample rate of the content, as set in open()
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index a646399..d881813 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -24,8 +24,8 @@
#include <media/mediaplayer_common.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
#include <mediaplayer2/MediaPlayer2Types.h>
+#include <mediaplayer2/JObjectHolder.h>
-#include <vector>
#include <jni.h>
#include <utils/Errors.h>
#include <utils/Mutex.h>
@@ -100,7 +100,8 @@
audio_session_t getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
status_t attachAuxEffect(int effectId);
- status_t setParameter(int key, const Parcel& request);
+ status_t setAudioAttributes(const jobject attributes);
+ jobject getAudioAttributes();
status_t getParameter(int key, Parcel* reply);
// Modular DRM
@@ -121,14 +122,14 @@
// Disconnect from the currently connected ANativeWindow.
void disconnectNativeWindow_l();
- status_t setAudioAttributes_l(const Parcel &request);
+ status_t setAudioAttributes_l(const jobject attributes);
void clear_l();
status_t seekTo_l(int64_t msec, MediaPlayer2SeekMode mode);
status_t prepareAsync_l();
status_t getDuration_l(int64_t *msec);
status_t reset_l();
- status_t checkStateForKeySet_l(int key);
+ status_t checkState_l();
pid_t mPid;
uid_t mUid;
@@ -145,15 +146,13 @@
int64_t mSeekPosition;
MediaPlayer2SeekMode mSeekMode;
audio_stream_type_t mStreamType;
- Parcel* mAudioAttributesParcel;
bool mLoop;
float mVolume;
int mVideoWidth;
int mVideoHeight;
audio_session_t mAudioSessionId;
- audio_attributes_t * mAudioAttributes;
+ sp<JObjectHolder> mAudioAttributes;
float mSendLevel;
- std::vector<jobject> mRoutingDelegates;
sp<ANativeWindowWrapper> mConnectedWindow;
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index 617da47..04a6f68 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -53,57 +53,6 @@
const int kDumpLockRetries = 50;
const int kDumpLockSleepUs = 20000;
-// marshalling tag indicating flattened utf16 tags
-// keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
-const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
-
-// Audio attributes format in a parcel:
-//
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | usage |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | content_type |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | source |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | flags |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | kAudioAttributesMarshallTagFlattenTags | // ignore tags if not found
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | flattened tags in UTF16 |
-// | ... |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//
-// @param p Parcel that contains audio attributes.
-// @param[out] attributes On exit points to an initialized audio_attributes_t structure
-// @param[out] status On exit contains the status code to be returned.
-void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes) {
- attributes->usage = (audio_usage_t) parcel.readInt32();
- attributes->content_type = (audio_content_type_t) parcel.readInt32();
- attributes->source = (audio_source_t) parcel.readInt32();
- attributes->flags = (audio_flags_mask_t) parcel.readInt32();
- const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
- if (hasFlattenedTag) {
- // the tags are UTF16, convert to UTF8
- String16 tags = parcel.readString16();
- ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
- if (realTagSize <= 0) {
- strcpy(attributes->tags, "");
- } else {
- // copy the flattened string into the attributes as the destination for the conversion:
- // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
- size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
- utf16_to_utf8(tags.string(), tagSize, attributes->tags,
- sizeof(attributes->tags) / sizeof(attributes->tags[0]));
- }
- } else {
- ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
- strcpy(attributes->tags, "");
- }
-}
-
class proxyListener : public MediaPlayer2InterfaceListener {
public:
proxyListener(const wp<MediaPlayer2> &player)
@@ -293,7 +242,7 @@
mLockThreadId = 0;
mListener = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
- mAudioAttributesParcel = NULL;
+ mAudioAttributes = NULL;
mCurrentPosition = -1;
mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
@@ -310,21 +259,14 @@
mPid = IPCThreadState::self()->getCallingPid();
mUid = IPCThreadState::self()->getCallingUid();
- mAudioAttributes = NULL;
+ mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid, mPid, NULL /*attributes*/);
}
MediaPlayer2::~MediaPlayer2() {
ALOGV("destructor");
- if (mAudioAttributesParcel != NULL) {
- delete mAudioAttributesParcel;
- mAudioAttributesParcel = NULL;
- }
AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
disconnect();
removePlayer(this);
- if (mAudioAttributes != NULL) {
- free(mAudioAttributes);
- }
}
bool MediaPlayer2::init() {
@@ -412,13 +354,7 @@
clear_l();
- if (mAudioOutput != NULL) {
- mAudioOutput->copyAudioDeviceCallback(mRoutingDelegates);
- }
-
player->setListener(new proxyListener(this));
- mAudioOutput = new MediaPlayer2AudioOutput(mAudioSessionId, mUid,
- mPid, mAudioAttributes, mRoutingDelegates);
player->setAudioSink(mAudioOutput);
err = player->setDataSource(dsd);
@@ -568,22 +504,9 @@
return mPlayer->setBufferingSettings(buffering);
}
-status_t MediaPlayer2::setAudioAttributes_l(const Parcel &parcel) {
- if (mAudioAttributes != NULL) {
- free(mAudioAttributes);
- }
- mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- if (mAudioAttributes == NULL) {
- return NO_MEMORY;
- }
- unmarshallAudioAttributes(parcel, mAudioAttributes);
-
- ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
- mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
- mAudioAttributes->tags);
-
- if (mAudioOutput != 0) {
- mAudioOutput->setAudioAttributes(mAudioAttributes);
+status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
+ if (mAudioOutput != NULL) {
+ mAudioOutput->setAudioAttributes(attributes);
}
return NO_ERROR;
}
@@ -592,8 +515,8 @@
ALOGV("prepareAsync");
Mutex::Autolock _l(mLock);
if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
- if (mAudioAttributesParcel != NULL) {
- status_t err = setAudioAttributes_l(*mAudioAttributesParcel);
+ if (mAudioAttributes != NULL) {
+ status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
if (err != OK) {
return err;
}
@@ -983,6 +906,9 @@
AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
mAudioSessionId = sessionId;
}
+ if (mAudioOutput != NULL && mAudioSessionId != mAudioOutput->getSessionId()) {
+ mAudioOutput->setSessionId(sessionId);
+ }
return NO_ERROR;
}
@@ -1015,67 +941,37 @@
}
// always call with lock held
-status_t MediaPlayer2::checkStateForKeySet_l(int key) {
- switch(key) {
- case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
- if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
- MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
- // Can't change the audio attributes after prepare
- ALOGE("trying to set audio attributes called in state %d", mCurrentState);
- return INVALID_OPERATION;
- }
- break;
- default:
- // parameter doesn't require player state check
- break;
+status_t MediaPlayer2::checkState_l() {
+ if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
+ MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
+ // Can't change the audio attributes after prepare
+ ALOGE("trying to set audio attributes called in state %d", mCurrentState);
+ return INVALID_OPERATION;
}
return OK;
}
-status_t MediaPlayer2::setParameter(int key, const Parcel& request) {
- ALOGV("MediaPlayer2::setParameter(%d)", key);
+status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
+ ALOGV("MediaPlayer2::setAudioAttributes");
status_t status = INVALID_OPERATION;
Mutex::Autolock _l(mLock);
- if (checkStateForKeySet_l(key) != OK) {
+ if (checkState_l() != OK) {
return status;
}
- switch (key) {
- case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
- // save the marshalled audio attributes
- if (mAudioAttributesParcel != NULL) {
- delete mAudioAttributesParcel;
- }
- mAudioAttributesParcel = new Parcel();
- mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
- status = setAudioAttributes_l(request);
- if (status != OK) {
- return status;
- }
- break;
- default:
- ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
- break;
- }
-
- if (mPlayer != NULL) {
- status = mPlayer->setParameter(key, request);
- }
+ mAudioAttributes = new JObjectHolder(attributes);
+ status = setAudioAttributes_l(attributes);
return status;
}
+jobject MediaPlayer2::getAudioAttributes() {
+ ALOGV("MediaPlayer2::getAudioAttributes)");
+ Mutex::Autolock _l(mLock);
+ return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
+}
+
status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
ALOGV("MediaPlayer2::getParameter(%d)", key);
Mutex::Autolock _l(mLock);
- if (key == MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES) {
- if (reply == NULL) {
- return BAD_VALUE;
- }
- if (mAudioAttributesParcel != NULL) {
- reply->appendFrom(mAudioAttributesParcel, 0, mAudioAttributesParcel->dataSize());
- }
- return OK;
- }
-
if (mPlayer == NULL) {
ALOGV("getParameter: no active player");
return INVALID_OPERATION;
@@ -1286,7 +1182,6 @@
Mutex::Autolock _l(mLock);
if (mAudioOutput == NULL) {
ALOGV("addAudioDeviceCallback: player not init");
- mRoutingDelegates.push_back(routingDelegate);
return NO_INIT;
}
return mAudioOutput->addAudioDeviceCallback(routingDelegate);