summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorJean-Michel Trivi <jmtrivi@google.com>2014-06-24 08:01:46 -0700
committerJean-Michel Trivi <jmtrivi@google.com>2014-07-01 07:57:32 -0700
commitd9d7fa0873796ac661c44a7fcd6ad5ff697ff01f (patch)
tree237375ce1605b2d7bd896b23f0a2ba2f0235ae09 /media
parentf92f22becdf7fce1f55d5ebd80ac2caa2ad55602 (diff)
downloadframeworks_av-d9d7fa0873796ac661c44a7fcd6ad5ff697ff01f.zip
frameworks_av-d9d7fa0873796ac661c44a7fcd6ad5ff697ff01f.tar.gz
frameworks_av-d9d7fa0873796ac661c44a7fcd6ad5ff697ff01f.tar.bz2
Support for audio attributes on audio output of media player
Change-Id: Iae4995c98e64add1ab9e6c8ae6501515032755f5
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/AudioTrack.cpp12
-rw-r--r--media/libmedia/mediaplayer.cpp22
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp108
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h8
4 files changed, 137 insertions, 13 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 898d58d..b5c9125 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -124,7 +124,8 @@ AudioTrack::AudioTrack(
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
- pid_t pid)
+ pid_t pid,
+ const audio_attributes_t* pAttributes)
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -134,7 +135,7 @@ AudioTrack::AudioTrack(
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
- offloadInfo, uid, pid, NULL /*no audio attributes*/);
+ offloadInfo, uid, pid, pAttributes);
}
AudioTrack::AudioTrack(
@@ -151,7 +152,8 @@ AudioTrack::AudioTrack(
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
- pid_t pid)
+ pid_t pid,
+ const audio_attributes_t* pAttributes)
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -161,7 +163,7 @@ AudioTrack::AudioTrack(
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- uid, pid, NULL /*no audio attributes*/);
+ uid, pid, pAttributes);
}
AudioTrack::~AudioTrack()
@@ -205,7 +207,7 @@ status_t AudioTrack::set(
const audio_offload_info_t *offloadInfo,
int uid,
pid_t pid,
- audio_attributes_t* pAttributes)
+ const audio_attributes_t* pAttributes)
{
ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"flags #%x, notificationFrames %u, sessionId %d, transferType %d",
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 406f9f2..889bd7f 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -624,10 +624,32 @@ status_t MediaPlayer::attachAuxEffect(int effectId)
return mPlayer->attachAuxEffect(effectId);
}
+// always call with lock held
+status_t MediaPlayer::checkStateForKeySet_l(int key)
+{
+ switch(key) {
+ case KEY_PARAMETER_AUDIO_ATTRIBUTES:
+ if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
+ MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_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;
+ }
+ return OK;
+}
+
status_t MediaPlayer::setParameter(int key, const Parcel& request)
{
ALOGV("MediaPlayer::setParameter(%d)", key);
Mutex::Autolock _l(mLock);
+ if (checkStateForKeySet_l(key) != OK) {
+ return INVALID_OPERATION;
+ }
if (mPlayer != NULL) {
return mPlayer->setParameter(key, request);
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 76632a7..7218467 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -186,6 +186,60 @@ bool findMetadata(const Metadata::Filter& filter, const int32_t val)
} // anonymous namespace
+namespace {
+using android::Parcel;
+using android::String16;
+
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | 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->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);
+ }
+ } else {
+ ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
+ strcpy(attributes->tags, "");
+ }
+}
+} // anonymous namespace
+
+
namespace android {
static bool checkPermission(const char* permissionString) {
@@ -508,6 +562,7 @@ MediaPlayerService::Client::Client(
mAudioSessionId = audioSessionId;
mUID = uid;
mRetransmitEndpointValid = false;
+ mAudioAttributes = NULL;
#if CALLBACK_ANTAGONIZER
ALOGD("create Antagonizer");
@@ -522,6 +577,9 @@ MediaPlayerService::Client::~Client()
wp<Client> client(this);
disconnect();
mService->removeClient(client);
+ if (mAudioAttributes != NULL) {
+ free(mAudioAttributes);
+ }
}
void MediaPlayerService::Client::disconnect()
@@ -587,7 +645,7 @@ sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
- mPid);
+ mPid, mAudioAttributes);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -968,6 +1026,22 @@ status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type
return NO_ERROR;
}
+status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
+{
+ if (mAudioAttributes != NULL) { free(mAudioAttributes); }
+ mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+ 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);
+ }
+ return NO_ERROR;
+}
+
status_t MediaPlayerService::Client::setLooping(int loop)
{
ALOGV("[%d] setLooping(%d)", mConnId, loop);
@@ -1016,9 +1090,17 @@ status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
ALOGV("[%d] setParameter(%d)", mConnId, key);
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
- return p->setParameter(key, request);
+ switch (key) {
+ case KEY_PARAMETER_AUDIO_ATTRIBUTES:
+ {
+ Mutex::Autolock l(mLock);
+ return setAudioAttributes_l(request);
+ }
+ default:
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) { return UNKNOWN_ERROR; }
+ return p->setParameter(key, request);
+ }
}
status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
@@ -1300,7 +1382,8 @@ Exit:
#undef LOG_TAG
#define LOG_TAG "AudioSink"
-MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid)
+MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
+ const audio_attributes_t* attr)
: mCallback(NULL),
mCallbackCookie(NULL),
mCallbackData(NULL),
@@ -1319,6 +1402,7 @@ MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid)
mAuxEffectId = 0;
mSendLevel = 0.0;
setMinBufferCount();
+ mAttributes = attr;
}
MediaPlayerService::AudioOutput::~AudioOutput()
@@ -1408,6 +1492,10 @@ String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
return mTrack->getParameters(keys);
}
+void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
+ mAttributes = attributes;
+}
+
void MediaPlayerService::AudioOutput::deleteRecycledTrack()
{
ALOGV("deleteRecycledTrack");
@@ -1557,7 +1645,8 @@ status_t MediaPlayerService::AudioOutput::open(
AudioTrack::TRANSFER_CALLBACK,
offloadInfo,
mUid,
- mPid);
+ mPid,
+ mAttributes);
} else {
t = new AudioTrack(
mStreamType,
@@ -1573,13 +1662,18 @@ status_t MediaPlayerService::AudioOutput::open(
AudioTrack::TRANSFER_DEFAULT,
NULL, // offload info
mUid,
- mPid);
+ mPid,
+ mAttributes);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
ALOGE("Unable to create audio track");
delete newcbd;
return NO_INIT;
+ } else {
+ // successful AudioTrack initialization implies a legacy stream type was generated
+ // from the audio attributes
+ mStreamType = t->streamType();
}
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 448f27a..2eca6a0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -72,7 +72,8 @@ class MediaPlayerService : public BnMediaPlayerService
class CallbackData;
public:
- AudioOutput(int sessionId, int uid, int pid);
+ AudioOutput(int sessionId, int uid, int pid,
+ const audio_attributes_t * attr);
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != 0; }
@@ -104,6 +105,7 @@ class MediaPlayerService : public BnMediaPlayerService
void setAudioStreamType(audio_stream_type_t streamType) {
mStreamType = streamType; }
virtual audio_stream_type_t getAudioStreamType() const { return mStreamType; }
+ void setAudioAttributes(const audio_attributes_t * attributes);
void setVolume(float left, float right);
virtual status_t setPlaybackRatePermille(int32_t ratePermille);
@@ -133,6 +135,7 @@ class MediaPlayerService : public BnMediaPlayerService
CallbackData * mCallbackData;
uint64_t mBytesWritten;
audio_stream_type_t mStreamType;
+ const audio_attributes_t *mAttributes;
float mLeftVolume;
float mRightVolume;
int32_t mPlaybackRatePermille;
@@ -410,6 +413,8 @@ private:
// Disconnect from the currently connected ANativeWindow.
void disconnectNativeWindow();
+ status_t setAudioAttributes_l(const Parcel &request);
+
mutable Mutex mLock;
sp<MediaPlayerBase> mPlayer;
sp<MediaPlayerService> mService;
@@ -420,6 +425,7 @@ private:
bool mLoop;
int32_t mConnId;
int mAudioSessionId;
+ audio_attributes_t * mAudioAttributes;
uid_t mUID;
sp<ANativeWindow> mConnectedWindow;
sp<IBinder> mConnectedWindowBinder;