OSDN Git Service

Add a way to play file descriptor data sources using the A@H transmitter media player.
authorJason Simmons <jsimmons@google.com>
Mon, 30 Jan 2012 02:03:02 +0000 (18:03 -0800)
committerJason Simmons <jsimmons@google.com>
Mon, 30 Jan 2012 02:03:02 +0000 (18:03 -0800)
* Added a MediaPlayer.setMediaPlayerType API that be called to specify the
  desired media player implementation before calling setDataSource
* Implemented setDataSource(fd) in the AAH_TxPlayer

Change-Id: I359075d9c7d6fd699dda14eb85ec50da19307639

include/media/IMediaPlayer.h
include/media/mediaplayer.h
media/java/android/media/MediaPlayer.java
media/jni/android_media_MediaPlayer.cpp
media/libaah_rtp/aah_tx_player.cpp
media/libaah_rtp/aah_tx_player.h
media/libmedia/IMediaPlayer.cpp
media/libmedia/mediaplayer.cpp
media/libmediaplayerservice/MediaPlayerService.cpp
media/libmediaplayerservice/MediaPlayerService.h

index e905903..afd4f58 100644 (file)
@@ -58,6 +58,7 @@ public:
     virtual status_t        attachAuxEffect(int effectId) = 0;
     virtual status_t        setParameter(int key, const Parcel& request) = 0;
     virtual status_t        getParameter(int key, Parcel* reply) = 0;
+    virtual status_t        setMediaPlayerType(int playerType) = 0;
 
     // Invoke a generic method on the player by using opaque parcels
     // for the request and reply.
index e6a0cc5..ed42ee9 100644 (file)
@@ -201,6 +201,7 @@ public:
             status_t        attachAuxEffect(int effectId);
             status_t        setParameter(int key, const Parcel& request);
             status_t        getParameter(int key, Parcel* reply);
+            status_t        setMediaPlayerType(int playerType);
 
 private:
             void            clear_l();
@@ -231,6 +232,8 @@ private:
     int                         mVideoHeight;
     int                         mAudioSessionId;
     float                       mSendLevel;
+    bool                        mOverridePlayerType;
+    int                         mOverridePlayerTypeValue;
 };
 
 }; // namespace android
index 8d71dcf..04a12aa 100644 (file)
@@ -1486,6 +1486,18 @@ public class MediaPlayer
      */
     public native static int native_pullBatteryData(Parcel reply);
 
+    /**
+     * Override the choice of media player implementation the next time
+     * setDataSource is called.
+     *
+     * Only valid when the player is in the Idle state.
+     *
+     * @param playerType media player type (defined in MediaPlayerInterface.h)
+     * {@hide}
+     */
+    public native void setMediaPlayerType(int playerType)
+        throws IOException, IllegalStateException;
+
     @Override
     protected void finalize() { native_finalize(); }
 
index 63cbf5e..8f1aa98 100644 (file)
@@ -755,6 +755,20 @@ android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobj
     process_media_player_call(env, thiz, mp->getParameter(key, reply), NULL, NULL );
 }
 
+static void
+android_media_MediaPlayer_setMediaPlayerType(JNIEnv *env, jobject thiz, jint playerType)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    process_media_player_call(env, thiz, mp->setMediaPlayerType(playerType),
+                              "java/io/IOException",
+                              "setMediaPlayerType failed");
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -799,6 +813,7 @@ static JNINativeMethod gMethods[] = {
     {"native_pullBatteryData", "(Landroid/os/Parcel;)I",        (void *)android_media_MediaPlayer_pullBatteryData},
     {"setParameter",        "(ILandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_setParameter},
     {"getParameter",        "(ILandroid/os/Parcel;)V",          (void *)android_media_MediaPlayer_getParameter},
+    {"setMediaPlayerType", "(I)V",                              (void *)android_media_MediaPlayer_setMediaPlayerType},
 };
 
 static const char* const kClassPathName = "android/media/MediaPlayer";
index e7020c1..222cc4a 100644 (file)
@@ -25,6 +25,7 @@
 #include <aah_timesrv/cc_helper.h>
 #include <media/IMediaPlayer.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MetaData.h>
@@ -184,7 +185,27 @@ status_t AAH_TXPlayer::setDataSource_l(
 }
 
 status_t AAH_TXPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
-    return INVALID_OPERATION;
+    Mutex::Autolock autoLock(mLock);
+
+    reset_l();
+
+    sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
+
+    status_t err = dataSource->initCheck();
+
+    if (err != OK) {
+        return err;
+    }
+
+    mFileSource = dataSource;
+
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+    if (extractor == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    return setDataSource_l(extractor);
 }
 
 status_t AAH_TXPlayer::setVideoSurface(const sp<Surface>& surface) {
@@ -379,7 +400,12 @@ void AAH_TXPlayer::onPrepareAsyncEvent() {
 
     mAudioSource->getFormat()->findInt64(kKeyDuration, &mDurationUs);
 
-    mAudioSource->start();
+    status_t err = mAudioSource->start();
+    if (err != OK) {
+        LOGI("failed to start audio source, err=%d", err);
+        abortPrepare(err);
+        return;
+    }
 
     mFlags |= PREPARING_CONNECTED;
 
@@ -651,6 +677,8 @@ void AAH_TXPlayer::reset_l() {
     mUri.setTo("");
     mUriHeaders.clear();
 
+    mFileSource.clear();
+
     mBitrate = -1;
 
     {
index 8b1551f..c50c929 100644 (file)
@@ -136,6 +136,8 @@ class AAH_TXPlayer : public MediaPlayerHWInterface {
     String8 mUri;
     KeyedVector<String8, String8> mUriHeaders;
 
+    sp<DataSource> mFileSource;
+
     sp<TimedEventQueue::Event> mAsyncPrepareEvent;
     Condition mPreparedCondition;
     status_t mPrepareResult;
index 9c1e6b7..859c706 100644 (file)
@@ -55,6 +55,7 @@ enum {
     SET_VIDEO_SURFACETEXTURE,
     SET_PARAMETER,
     GET_PARAMETER,
+    SET_MEDIA_PLAYER_TYPE,
 };
 
 class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -291,6 +292,13 @@ public:
         return remote()->transact(GET_PARAMETER, data, reply);
     }
 
+    status_t setMediaPlayerType(int playerType) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeInt32(playerType);
+        remote()->transact(SET_MEDIA_PLAYER_TYPE, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -459,6 +467,11 @@ status_t BnMediaPlayer::onTransact(
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             return getParameter(data.readInt32(), reply);
         } break;
+        case SET_MEDIA_PLAYER_TYPE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(setMediaPlayerType(data.readInt32()));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
index c2e1ddf..325c788 100644 (file)
@@ -63,6 +63,8 @@ MediaPlayer::MediaPlayer()
     mAudioSessionId = AudioSystem::newAudioSessionId();
     AudioSystem::acquireAudioSessionId(mAudioSessionId);
     mSendLevel = 0;
+    mOverridePlayerType = false;
+    mOverridePlayerTypeValue = -1;
 }
 
 MediaPlayer::~MediaPlayer()
@@ -146,7 +148,14 @@ status_t MediaPlayer::setDataSource(
         const sp<IMediaPlayerService>& service(getMediaPlayerService());
         if (service != 0) {
             sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
-            if (NO_ERROR != player->setDataSource(url, headers)) {
+
+            if (mOverridePlayerType) {
+                if (NO_ERROR != player->setMediaPlayerType(mOverridePlayerTypeValue)) {
+                    player.clear();
+                }
+            }
+
+            if (player != 0 && NO_ERROR != player->setDataSource(url, headers)) {
                 player.clear();
             }
             err = attachNewPlayer(player);
@@ -162,7 +171,14 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
     const sp<IMediaPlayerService>& service(getMediaPlayerService());
     if (service != 0) {
         sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
-        if (NO_ERROR != player->setDataSource(fd, offset, length)) {
+
+        if (mOverridePlayerType) {
+            if (NO_ERROR != player->setMediaPlayerType(mOverridePlayerTypeValue)) {
+                player.clear();
+            }
+        }
+
+        if (player != 0 && NO_ERROR != player->setDataSource(fd, offset, length)) {
             player.clear();
         }
         err = attachNewPlayer(player);
@@ -599,6 +615,19 @@ status_t MediaPlayer::getParameter(int key, Parcel *reply)
     return INVALID_OPERATION;
 }
 
+status_t MediaPlayer::setMediaPlayerType(int playerType) {
+    if (!((mCurrentState & MEDIA_PLAYER_IDLE) ||
+          (mCurrentState == MEDIA_PLAYER_STATE_ERROR))) {
+        LOGE("attachNewPlayer called in state %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    mOverridePlayerType = true;
+    mOverridePlayerTypeValue = playerType;
+
+    return NO_ERROR;
+}
+
 void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
 {
     LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
index 5b1d6c7..45ffc7d 100644 (file)
@@ -497,6 +497,9 @@ MediaPlayerService::Client::Client(
     LOGD("create Antagonizer");
     mAntagonizer = new Antagonizer(notify, this);
 #endif
+
+    mOverridePlayerType = false;
+    mOverridePlayerTypeValue = static_cast<player_type>(-1);
 }
 
 MediaPlayerService::Client::~Client()
@@ -716,7 +719,8 @@ status_t MediaPlayerService::Client::setDataSource(
         close(fd);
         return mStatus;
     } else {
-        player_type playerType = getPlayerType(url);
+        player_type playerType = mOverridePlayerType ?
+                mOverridePlayerTypeValue : getPlayerType(url);
         LOGV("player type = %d", playerType);
 
         // create the right type of player
@@ -766,7 +770,8 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
         LOGV("calculated length = %lld", length);
     }
 
-    player_type playerType = getPlayerType(fd, offset, length);
+    player_type playerType = mOverridePlayerType ?
+            mOverridePlayerTypeValue : getPlayerType(fd, offset, length);
     LOGV("player type = %d", playerType);
 
     // create the right type of player
@@ -1100,6 +1105,13 @@ status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
     return p->getParameter(key, reply);
 }
 
+status_t MediaPlayerService::Client::setMediaPlayerType(int playerType) {
+    mOverridePlayerType = true;
+    mOverridePlayerTypeValue = static_cast<player_type>(playerType);
+
+    return NO_ERROR;
+}
+
 void MediaPlayerService::Client::notify(
         void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
 {
index 04d9e28..9ae1d50 100644 (file)
@@ -271,6 +271,7 @@ private:
         virtual status_t        attachAuxEffect(int effectId);
         virtual status_t        setParameter(int key, const Parcel &request);
         virtual status_t        getParameter(int key, Parcel *reply);
+        virtual status_t        setMediaPlayerType(int playerType);
 
         sp<MediaPlayerBase>     createPlayer(player_type playerType);
 
@@ -344,6 +345,9 @@ private:
         // getMetadata clears this set.
         media::Metadata::Filter mMetadataUpdated;  // protected by mLock
 
+        bool mOverridePlayerType;
+        player_type mOverridePlayerTypeValue;
+
 #if CALLBACK_ANTAGONIZER
                     Antagonizer*                mAntagonizer;
 #endif