am 2c2ce8e5: Merge "Added support for audio sessions in MediaPlayer and AudioTrack." into gingerbread

Merge commit '2c2ce8e53f5eb94916a5d0f40b2877cc7551870d' into gingerbread-plus-aosp

* commit '2c2ce8e53f5eb94916a5d0f40b2877cc7551870d':
  Added support for audio sessions in MediaPlayer and AudioTrack.
This commit is contained in:
Eric Laurent
2010-06-22 18:32:17 -07:00
committed by Android Git Automerger
11 changed files with 252 additions and 38 deletions

View File

@ -166,7 +166,7 @@ static void audioCallback(int event, void* user, void *info) {
static int
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint streamType, jint sampleRateInHertz, jint channels,
jint audioFormat, jint buffSizeInBytes, jint memoryMode)
jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession)
{
LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
@ -253,6 +253,20 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
lpJniStorage->mStreamType = atStreamType;
jint* nSession = NULL;
if (jSession) {
nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
if (nSession == NULL) {
LOGE("Error creating AudioTrack: Error retrieving session id pointer");
delete lpJniStorage;
return AUDIOTRACK_ERROR;
}
} else {
LOGE("Error creating AudioTrack: invalid session ID pointer");
delete lpJniStorage;
return AUDIOTRACK_ERROR;
}
// create the native AudioTrack object
AudioTrack* lpTrack = new AudioTrack();
if (lpTrack == NULL) {
@ -273,7 +287,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
0,// shared mem
true);// thread can call Java
true,// thread can call Java
nSession[0]);// audio session ID
} else if (memoryMode == javaAudioTrackFields.MODE_STATIC) {
// AudioTrack is using shared memory
@ -293,7 +308,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
lpJniStorage->mMemBase,// shared mem
true);// thread can call Java
true,// thread can call Java
nSession[0]);// audio session ID
}
if (lpTrack->initCheck() != NO_ERROR) {
@ -301,6 +317,12 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
goto native_init_failure;
}
// read the audio session ID back from AudioTrack in case we create a new session
nSession[0] = lpTrack->getSessionId();
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
// save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field
// of the Java object (in mNativeTrackInJavaObj)
env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (int)lpTrack);
@ -317,6 +339,9 @@ native_init_failure:
env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, 0);
native_track_failure:
if (nSession != NULL) {
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
}
env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
delete lpJniStorage;
@ -785,7 +810,7 @@ static JNINativeMethod gMethods[] = {
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
{"native_setup", "(Ljava/lang/Object;IIIIII)I",
{"native_setup", "(Ljava/lang/Object;IIIIII[I)I",
(void *)android_media_AudioTrack_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_native_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_native_release},

View File

@ -40,8 +40,11 @@ public:
virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, const KeyedVector<String8, String8> *headers = NULL) = 0;
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
const char* url, const KeyedVector<String8, String8> *headers = NULL,
int audioSessionId = 0) = 0;
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IOMX> getOMX() = 0;

View File

@ -172,6 +172,8 @@ public:
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
status_t suspend();
status_t resume();
status_t setAudioSessionId(int sessionId);
int getAudioSessionId();
private:
void clear_l();
status_t seekTo_l(int msec);
@ -198,6 +200,7 @@ private:
float mRightVolume;
int mVideoWidth;
int mVideoHeight;
int mAudioSessionId;
};
}; // namespace android

View File

@ -210,6 +210,10 @@ public class AudioTrack
* @see AudioFormat#ENCODING_PCM_16BIT
*/
private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
/**
* Audio session ID
*/
private int mSessionId = 0;
//--------------------------------
@ -257,6 +261,48 @@ public class AudioTrack
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
this(streamType, sampleRateInHz, channelConfig, audioFormat,
bufferSizeInBytes, mode, 0);
}
/**
* Class constructor with audio session. Use this constructor when the AudioTrack must be
* attached to a particular audio session. The primary use of the audio session ID is to
* associate audio effects to a particular instance of AudioTrack: if an audio session ID
* is provided when creating an AudioEffect, this effect will be applied only to audio tracks
* and media players in the same session and not to the output mix.
* When an AudioTrack is created without specifying a session, it will create its own session
* which can be retreived by calling the {@link #getAudioSessionId()} method.
* If a session ID is provided, this AudioTrack will share effects attached to this session
* with all other media players or audio tracks in the same session.
* @param streamType the type of the audio stream. See
* {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
* {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
* {@link AudioManager#STREAM_ALARM}
* @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
* not limited to) 44100, 22050 and 11025.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
* @param audioFormat the format in which the audio data is represented.
* See {@link AudioFormat#ENCODING_PCM_16BIT} and
* {@link AudioFormat#ENCODING_PCM_8BIT}
* @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
* from for playback. If using the AudioTrack in streaming mode, you can write data into
* this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
* this is the maximum size of the sound that will be played for this instance.
* See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
* for the successful creation of an AudioTrack instance in streaming mode. Using values
* smaller than getMinBufferSize() will result in an initialization failure.
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @param sessionId Id of audio session the AudioTrack must be attached to
* @throws java.lang.IllegalArgumentException
// FIXME: unhide.
* @hide
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode, int sessionId)
throws IllegalArgumentException {
mState = STATE_UNINITIALIZED;
@ -269,15 +315,23 @@ public class AudioTrack
audioBuffSizeCheck(bufferSizeInBytes);
if (sessionId < 0) {
throw (new IllegalArgumentException("Invalid audio session ID: "+sessionId));
}
int[] session = new int[1];
session[0] = sessionId;
// native initialization
int initResult = native_setup(new WeakReference<AudioTrack>(this),
mStreamType, mSampleRate, mChannels, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode);
mNativeBufferSizeInBytes, mDataLoadMode, session);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
}
mSessionId = session[0];
if (mDataLoadMode == MODE_STATIC) {
mState = STATE_NO_STATIC_DATA;
} else {
@ -590,6 +644,17 @@ public class AudioTrack
}
}
/**
* Returns the audio session ID.
*
* @return the ID of the audio session this AudioTrack belongs to.
// FIXME: unhide.
// FIXME: link to AudioEffect class when public.
* @hide
*/
public int getAudioSessionId() {
return mSessionId;
}
//--------------------------------------------------------------------------
// Initialization / configuration
@ -1012,7 +1077,7 @@ public class AudioTrack
private native final int native_setup(Object audiotrack_this,
int streamType, int sampleRate, int nbChannels, int audioFormat,
int buffSizeInBytes, int mode);
int buffSizeInBytes, int mode, int[] sessionId);
private native final void native_finalize();
@ -1056,6 +1121,7 @@ public class AudioTrack
static private native final int native_get_min_buff_size(
int sampleRateInHz, int channelConfig, int audioFormat);
private native final int native_get_session_id();
//---------------------------------------------------------
// Utility methods

View File

@ -423,6 +423,18 @@ import java.lang.ref.WeakReference;
* <td>Successful invoke of this method in a valid state transfers the
* object to the <em>Stopped</em> state. Calling this method in an
* invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
* <tr><td>setAudioSessionId </p></td>
* <td>{Idle} </p></td>
* <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
* Error} </p></td>
* <td>This method must be called in idle state as the audio session ID must be known before
* calling setDataSource. Calling it does not change the object state. </p></td></tr>
* <tr><td>getAudioSessionId </p></td>
* <td>any </p></td>
* <td>{} </p></td>
* <td>This method can be called in any state and calling it does not change
* the object state. </p></td></tr>
*
* </table>
*
* <a name="Permissions"></a>
@ -1158,6 +1170,38 @@ public class MediaPlayer
*/
public native Bitmap getFrameAt(int msec) throws IllegalStateException;
/**
* Sets the audio session ID.
*
* @param sessionId: the audio session ID.
* The audio session ID is a system wide unique identifier for the audio stream played by
* this MediaPlayer instance.
* The primary use of the audio session ID is to associate audio effects to a particular
* instance of MediaPlayer: if an audio session ID is provided when creating an audio effect,
* this effect will be applied only to the audio content of media players within the same
* audio session and not to the output mix.
* When created, a MediaPlayer instance automatically generates its own audio session ID.
* However, it is possible to force this player to be part of an already existing audio session
* by calling this method.
* This method must be called before one of the overloaded <code> setDataSource </code> methods.
* @throws IllegalStateException if it is called in an invalid state
*
// FIXME: unhide.
// FIXME: link to AudioEffect class when public.
* @hide
*/
public native void setAudioSessionId(int sessionId) throws IllegalArgumentException, IllegalStateException;
/**
* Returns the audio session ID.
*
* @return the audio session ID. {@see #setAudioSessionId(int)}.
* Note that the audio session ID is 0 only if a problem occured when the MediaPlayer was contructed.
// FIXME: unhide.
* @hide
*/
public native int getAudioSessionId();
/**
* @param request Parcel destinated to the media player. The
* Interface token must be set to the IMediaPlayer

View File

@ -292,7 +292,7 @@ static void setVideoSurface(const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz
if (surface != NULL) {
const sp<Surface> native_surface = get_surface(env, surface);
LOGV("prepare: surface=%p (id=%d)",
native_surface.get(), native_surface->ID());
native_surface.get(), native_surface->getIdentity());
mp->setVideoSurface(native_surface);
}
}
@ -332,7 +332,7 @@ android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
if (surface != NULL) {
const sp<Surface> native_surface = get_surface(env, surface);
LOGV("prepareAsync: surface=%p (id=%d)",
native_surface.get(), native_surface->ID());
native_surface.get(), native_surface->getIdentity());
mp->setVideoSurface(native_surface);
}
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
@ -705,6 +705,27 @@ android_media_MediaPlayer_native_suspend_resume(
return isSuspend ? mp->suspend() : mp->resume();
}
static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) {
LOGV("set_session_id(): %d", sessionId);
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL );
}
static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) {
LOGV("get_session_id()");
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return 0;
}
return mp->getAudioSessionId();
}
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@ -738,6 +759,8 @@ static JNINativeMethod gMethods[] = {
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"snoop", "([SI)I", (void *)android_media_MediaPlayer_snoop},
{"native_suspend_resume", "(Z)I", (void *)android_media_MediaPlayer_native_suspend_resume},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
};
static const char* const kClassPathName = "android/media/MediaPlayer";

View File

@ -92,7 +92,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
frameCount, flags, cbf, user, notificationFrames, 0);
frameCount, flags, cbf, user, notificationFrames,
0, false, sessionId);
}
AudioTrack::AudioTrack(
@ -109,7 +110,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
0, flags, cbf, user, notificationFrames, sharedBuffer);
0, flags, cbf, user, notificationFrames,
sharedBuffer, false, sessionId);
}
AudioTrack::~AudioTrack()

View File

@ -58,7 +58,7 @@ public:
virtual sp<IMediaPlayer> create(
pid_t pid, const sp<IMediaPlayerClient>& client,
const char* url, const KeyedVector<String8, String8> *headers) {
const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
@ -75,8 +75,10 @@ public:
data.writeString8(headers->valueAt(i));
}
}
data.writeInt32(audioSessionId);
remote()->transact(CREATE_URL, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
@ -89,7 +91,8 @@ public:
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length)
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
int64_t offset, int64_t length, int audioSessionId)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@ -98,8 +101,11 @@ public:
data.writeFileDescriptor(fd);
data.writeInt64(offset);
data.writeInt64(length);
data.writeInt32(audioSessionId);
remote()->transact(CREATE_FD, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
}
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
@ -166,9 +172,10 @@ status_t BnMediaPlayerService::onTransact(
String8 value = data.readString8();
headers.add(key, value);
}
int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(
pid, client, url, numHeaders > 0 ? &headers : NULL);
pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
@ -180,7 +187,9 @@ status_t BnMediaPlayerService::onTransact(
int fd = dup(data.readFileDescriptor());
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
sp<IMediaPlayer> player = create(pid, client, fd, offset, length);
int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;

View File

@ -55,6 +55,7 @@ MediaPlayer::MediaPlayer()
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
mAudioSessionId = AudioSystem::newAudioSessionId();
}
MediaPlayer::~MediaPlayer()
@ -137,7 +138,7 @@ status_t MediaPlayer::setDataSource(
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(
service->create(getpid(), this, url, headers));
service->create(getpid(), this, url, headers, mAudioSessionId));
err = setDataSource(player);
}
}
@ -150,7 +151,7 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
err = setDataSource(player);
}
return err;
@ -501,6 +502,27 @@ status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
return OK;
}
status_t MediaPlayer::setAudioSessionId(int sessionId)
{
LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
Mutex::Autolock _l(mLock);
if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
LOGE("setAudioSessionId called in state %d", mCurrentState);
return INVALID_OPERATION;
}
if (sessionId < 0) {
return BAD_VALUE;
}
mAudioSessionId = sessionId;
return NO_ERROR;
}
int MediaPlayer::getAudioSessionId()
{
Mutex::Autolock _l(mLock);
return mAudioSessionId;
}
void MediaPlayer::notify(int msg, int ext1, int ext2)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);

View File

@ -252,11 +252,12 @@ sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pi
sp<IMediaPlayer> MediaPlayerService::create(
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
const KeyedVector<String8, String8> *headers)
const KeyedVector<String8, String8> *headers, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(this, pid, connId, client);
LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
connId, pid, url, connId, audioSessionId);
if (NO_ERROR != c->setDataSource(url, headers))
{
c.clear();
@ -269,12 +270,12 @@ sp<IMediaPlayer> MediaPlayerService::create(
}
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
int fd, int64_t offset, int64_t length)
int fd, int64_t offset, int64_t length, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(this, pid, connId, client);
LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
connId, pid, fd, offset, length);
sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
connId, pid, fd, offset, length, audioSessionId);
if (NO_ERROR != c->setDataSource(fd, offset, length)) {
c.clear();
} else {
@ -609,7 +610,7 @@ void MediaPlayerService::removeClient(wp<Client> client)
}
MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
int32_t connId, const sp<IMediaPlayerClient>& client)
int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId)
{
LOGV("Client(%d) constructor", connId);
mPid = pid;
@ -618,6 +619,8 @@ MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t
mClient = client;
mLoop = false;
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
#if CALLBACK_ANTAGONIZER
LOGD("create Antagonizer");
mAntagonizer = new Antagonizer(notify, this);
@ -871,7 +874,7 @@ status_t MediaPlayerService::Client::setDataSource(
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput();
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@ -921,7 +924,7 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput();
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@ -1412,9 +1415,11 @@ sp<IMemory> MediaPlayerService::snoop()
#undef LOG_TAG
#define LOG_TAG "AudioSink"
MediaPlayerService::AudioOutput::AudioOutput()
MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
: mCallback(NULL),
mCallbackCookie(NULL) {
mCallbackCookie(NULL),
mSessionId(sessionId) {
LOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
mStreamType = AudioSystem::MUSIC;
mLeftVolume = 1.0;
@ -1504,7 +1509,7 @@ status_t MediaPlayerService::AudioOutput::open(
bufferCount = mMinBufferCount;
}
LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
LOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId);
if (mTrack) close();
int afSampleRate;
int afFrameCount;
@ -1529,14 +1534,21 @@ status_t MediaPlayerService::AudioOutput::open(
frameCount,
0 /* flags */,
CallbackWrapper,
this);
this,
0,
mSessionId);
} else {
t = new AudioTrack(
mStreamType,
sampleRate,
format,
(channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
frameCount);
frameCount,
0,
NULL,
NULL,
0,
mSessionId);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {

View File

@ -65,7 +65,7 @@ class MediaPlayerService : public BnMediaPlayerService
class AudioOutput : public MediaPlayerBase::AudioSink
{
public:
AudioOutput();
AudioOutput(int sessionId);
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != NULL; }
@ -108,6 +108,7 @@ class MediaPlayerService : public BnMediaPlayerService
float mRightVolume;
float mMsecsPerFrame;
uint32_t mLatency;
int mSessionId;
static bool mIsOnEmulator;
static int mMinBufferCount; // 12 for emulator; otherwise 4
@ -185,9 +186,9 @@ public:
// House keeping for media player clients
virtual sp<IMediaPlayer> create(
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
const KeyedVector<String8, String8> *headers);
const KeyedVector<String8, String8> *headers, int audioSessionId);
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
virtual sp<IMemory> snoop();
@ -237,12 +238,15 @@ private:
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args) const;
int getAudioSessionId() { return mAudioSessionId; }
private:
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
int32_t connId,
const sp<IMediaPlayerClient>& client);
const sp<IMediaPlayerClient>& client,
int audioSessionId);
Client();
virtual ~Client();
@ -271,6 +275,7 @@ private:
status_t mStatus;
bool mLoop;
int32_t mConnId;
int mAudioSessionId;
// Metadata filters.
media::Metadata::Filter mMetadataAllow; // protected by mLock