OSDN Git Service

Bug 5198051 MediaPlayer prefetch status interface
authorGlenn Kasten <gkasten@google.com>
Mon, 22 Aug 2011 15:25:19 +0000 (08:25 -0700)
committerGlenn Kasten <gkasten@google.com>
Tue, 23 Aug 2011 21:21:40 +0000 (14:21 -0700)
Change-Id: I426c870f803df0a7052f17be955ba797a814b4cc

wilhelm/src/MPH_to.c
wilhelm/src/android/AudioPlayer_to_android.cpp
wilhelm/src/android/MediaPlayer_to_android.cpp
wilhelm/src/autogen/MPH_to_MediaPlayer.h
wilhelm/src/classes.c
wilhelm/src/classes.h
wilhelm/src/sles.c

index f119f38..e1fe6c9 100644 (file)
@@ -253,8 +253,9 @@ const signed char MPH_to_MediaPlayer[MPH_MAX] = {
     [MPH_XASTREAMINFORMATION] = 3,
     [MPH_XAVOLUME] = 4,
     [MPH_XASEEK] = 5,
+    [MPH_XAPREFETCHSTATUS] = 6,
 #ifdef ANDROID
-    [MPH_ANDROIDBUFFERQUEUE] = 6,
+    [MPH_ANDROIDBUFFERQUEUE] = 7,
 #endif
 #else
 #include "MPH_to_MediaPlayer.h"
index 9846ee5..adf405f 100644 (file)
@@ -706,6 +706,9 @@ AndroidObjectType audioPlayer_getAndroidObjectTypeForSourceSink(CAudioPlayer *ap
  * from a URI or FD, for prepare, prefetch, and play events
  */
 static void sfplayer_handlePrefetchEvent(int event, int data1, int data2, void* user) {
+
+    // FIXME see similar code and comment in player_handleMediaPlayerEventNotifications
+
     if (NULL == user) {
         return;
     }
index d01d6c6..3d300c2 100644 (file)
 //-----------------------------------------------------------------------------
 static void player_handleMediaPlayerEventNotifications(int event, int data1, int data2, void* user)
 {
+
+    // FIXME This code is derived from similar code in sfplayer_handlePrefetchEvent.  The two
+    // versions are quite similar, but still different enough that they need to be separate.
+    // At some point they should be re-factored and merged if feasible.
+    // As with other OpenMAX AL implementation code, this copy mostly uses SL_ symbols
+    // rather than XA_ unless the difference is significant.
+
     if (NULL == user) {
         return;
     }
 
     CMediaPlayer* mp = (CMediaPlayer*) user;
-    SL_LOGV("received event %d, data %d from AVPlayer", event, data1);
-
+    union {
+        char c[sizeof(int)];
+        int i;
+    } u;
+    u.i = event;
+    SL_LOGV("player_handleMediaPlayerEventNotifications(event='%c%c%c%c' (%d), data1=%d, data2=%d, "
+            "user=%p) from AVPlayer", u.c[3], u.c[2], u.c[1], u.c[0], event, data1, data2, user);
     switch(event) {
 
       case android::GenericPlayer::kEventPrepared: {
-        if (PLAYER_SUCCESS == data1) {
-            object_lock_exclusive(&mp->mObject);
-            SL_LOGV("Received AVPlayer::kEventPrepared from AVPlayer for CMediaPlayer %p", mp);
-            mp->mAndroidObjState = ANDROID_READY;
-            object_unlock_exclusive(&mp->mObject);
+
+        SL_LOGV("Received AVPlayer::kEventPrepared for CMediaPlayer %p", mp);
+
+        // assume no callback
+        slPrefetchCallback callback = NULL;
+        void* callbackPContext = NULL;
+
+        object_lock_exclusive(&mp->mObject);
+        // mark object as prepared; same state is used for successfully or unsuccessful prepare
+        mp->mAndroidObjState = ANDROID_READY;
+
+        // AVPlayer prepare() failed prefetching, there is no event in XAPrefetchStatus to
+        //  indicate a prefetch error, so we signal it by sending simulataneously two events:
+        //  - SL_PREFETCHEVENT_FILLLEVELCHANGE with a level of 0
+        //  - SL_PREFETCHEVENT_STATUSCHANGE with a status of SL_PREFETCHSTATUS_UNDERFLOW
+        if (PLAYER_SUCCESS != data1 && IsInterfaceInitialized(&mp->mObject, MPH_XAPREFETCHSTATUS)) {
+            mp->mPrefetchStatus.mLevel = 0;
+            mp->mPrefetchStatus.mStatus = SL_PREFETCHSTATUS_UNDERFLOW;
+            if (!(~mp->mPrefetchStatus.mCallbackEventsMask &
+                    (SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE))) {
+                callback = mp->mPrefetchStatus.mCallback;
+                callbackPContext = mp->mPrefetchStatus.mContext;
+            }
         }
+        object_unlock_exclusive(&mp->mObject);
+
+        // callback with no lock held
+        if (NULL != callback) {
+            (*callback)(&mp->mPrefetchStatus.mItf, callbackPContext,
+                    SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);
+        }
+
         break;
       }
 
@@ -110,13 +148,13 @@ static void player_handleMediaPlayerEventNotifications(int event, int data1, int
 
         // enqueue callback with no lock held
         if (NULL != playCallback) {
-#ifdef XA_SYNCHRONOUS_PLAYEVENT_HEADATEND
+#ifdef USE_SYNCHRONOUS_PLAY_CALLBACK
             (*playCallback)(&mp->mPlay.mItf, playContext, XA_PLAYEVENT_HEADATEND);
 #else
             SLresult res = EnqueueAsyncCallback_ppi(mp, playCallback, &mp->mPlay.mItf, playContext,
                     XA_PLAYEVENT_HEADATEND);
             LOGW_IF(SL_RESULT_SUCCESS != res,
-                    "Callback %p(%p, %p, XA_PLAYEVENT_HEADATEND) dropped", playCallback,
+                    "Callback %p(%p, %p, SL_PLAYEVENT_HEADATEND) dropped", playCallback,
                     &mp->mPlay.mItf, playContext);
 #endif
         }
@@ -136,11 +174,56 @@ static void player_handleMediaPlayerEventNotifications(int event, int data1, int
 
       case android::GenericPlayer::kEventPrefetchFillLevelUpdate: {
         SL_LOGV("kEventPrefetchFillLevelUpdate");
+        if (!IsInterfaceInitialized(&mp->mObject, MPH_XAPREFETCHSTATUS)) {
+            break;
+        }
+        slPrefetchCallback callback = NULL;
+        void* callbackPContext = NULL;
+
+        // SLPrefetchStatusItf callback or no callback?
+        interface_lock_exclusive(&mp->mPrefetchStatus);
+        if (mp->mPrefetchStatus.mCallbackEventsMask & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
+            callback = mp->mPrefetchStatus.mCallback;
+            callbackPContext = mp->mPrefetchStatus.mContext;
+        }
+        mp->mPrefetchStatus.mLevel = (SLpermille)data1;
+        interface_unlock_exclusive(&mp->mPrefetchStatus);
+
+        // callback with no lock held
+        if (NULL != callback) {
+            (*callback)(&mp->mPrefetchStatus.mItf, callbackPContext,
+                    SL_PREFETCHEVENT_FILLLEVELCHANGE);
+        }
       }
       break;
 
       case android::GenericPlayer::kEventPrefetchStatusChange: {
         SL_LOGV("kEventPrefetchStatusChange");
+        if (!IsInterfaceInitialized(&mp->mObject, MPH_XAPREFETCHSTATUS)) {
+            break;
+        }
+        slPrefetchCallback callback = NULL;
+        void* callbackPContext = NULL;
+
+        // SLPrefetchStatusItf callback or no callback?
+        object_lock_exclusive(&mp->mObject);
+        if (mp->mPrefetchStatus.mCallbackEventsMask & SL_PREFETCHEVENT_STATUSCHANGE) {
+            callback = mp->mPrefetchStatus.mCallback;
+            callbackPContext = mp->mPrefetchStatus.mContext;
+        }
+        if (data1 >= android::kStatusIntermediate) {
+            mp->mPrefetchStatus.mStatus = SL_PREFETCHSTATUS_SUFFICIENTDATA;
+            // FIXME copied from AudioPlayer, but probably wrong
+            mp->mAndroidObjState = ANDROID_READY;
+        } else if (data1 < android::kStatusIntermediate) {
+            mp->mPrefetchStatus.mStatus = SL_PREFETCHSTATUS_UNDERFLOW;
+        }
+        object_unlock_exclusive(&mp->mObject);
+
+        // callback with no lock held
+        if (NULL != callback) {
+            (*callback)(&mp->mPrefetchStatus.mItf, callbackPContext, SL_PREFETCHEVENT_STATUSCHANGE);
+        }
       }
       break;
 
index 64461c3..4b11c6a 100644 (file)
@@ -2,5 +2,5 @@
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  0, -1,  2, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  0, -1,  2, -1,  6, -1, -1, -1,
   5, -1,  3, -1, -1, -1, -1, -1, -1,  4
index d854fbf..5c6c982 100644 (file)
@@ -410,6 +410,7 @@ static const struct iid_vtable MediaPlayer_interfaces[INTERFACES_MediaPlayer] =
     {MPH_XASTREAMINFORMATION, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mStreamInfo)},
     {MPH_XAVOLUME, INTERFACE_IMPLICIT, offsetof(CMediaPlayer, mVolume)},
     {MPH_XASEEK, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mSeek)},
+    {MPH_XAPREFETCHSTATUS, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mPrefetchStatus)},
 #ifdef ANDROID
     {MPH_ANDROIDBUFFERQUEUE, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mAndroidBufferQueue)},
 #endif
index cdc9ac1..ced5a14 100644 (file)
@@ -309,9 +309,9 @@ typedef struct {
 typedef struct CMediaPlayer_struct {
     IObject mObject;
 #ifdef ANDROID
-#define INTERFACES_MediaPlayer 7
+#define INTERFACES_MediaPlayer 8
 #else
-#define INTERFACES_MediaPlayer 6
+#define INTERFACES_MediaPlayer 7
 #endif
     XAuint8 mInterfaceStates2[INTERFACES_MediaPlayer - INTERFACES_Default];
     IDynamicInterfaceManagement mDynamicInterfaceManagement;
@@ -320,6 +320,7 @@ typedef struct CMediaPlayer_struct {
     IStreamInformation mStreamInfo;
     IVolume mVolume;
     ISeek mSeek;
+    IPrefetchStatus mPrefetchStatus;
 #ifdef ANDROID
     IAndroidBufferQueue mAndroidBufferQueue;
 #endif
index 586af63..49892f7 100644 (file)
@@ -453,7 +453,7 @@ extern bool
     { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
     { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
     { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
-    { /* MPH_XAPREFETCHSTATUS */ NULL, NULL, NULL, NULL, NULL },
+    { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
     { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
     { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
     { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },