OSDN Git Service

Bug 3329759 Implement streamInformation and volume in OpenMAX AL
authorJean-Michel Trivi <jmtrivi@google.com>
Wed, 9 Mar 2011 17:33:51 +0000 (09:33 -0800)
committerJean-Michel Trivi <jmtrivi@google.com>
Mon, 14 Mar 2011 23:54:23 +0000 (16:54 -0700)
- Implement StreamInformation for video size notification.
- Implement the XAVolumeItf for volume control
- Fix bug in GUID -> MPH hash.
- Fixed typo in GenericPlayer::pause() log
- Do not signal a discontinuity automatically when the ABQ is
  cleared because clearing the queue doesn't imply there will
  be a discontinuity in the data (e.g. the same data that was
  cleared could be reenqueued)
- In "native-media" test app: add test code to exercise the
  XAVolumeItf functionality.

Change-Id: I9f69f8cacbdce51b6d96d60141ec1d0f645df991

43 files changed:
wilhelm/include/OMXAL/OpenMAXAL_Android.h
wilhelm/include/SLES/OpenSLES_Android.h
wilhelm/src/MPH.h
wilhelm/src/MPH_to.c
wilhelm/src/OpenSLES_IID.c
wilhelm/src/android/AudioPlayer_to_android.cpp
wilhelm/src/android/MediaPlayer_to_android.cpp
wilhelm/src/android/MediaPlayer_to_android.h
wilhelm/src/android/android_AudioSfDecoder.cpp
wilhelm/src/android/android_GenericMediaPlayer.cpp
wilhelm/src/android/android_GenericMediaPlayer.h
wilhelm/src/android/android_GenericPlayer.cpp
wilhelm/src/android/android_GenericPlayer.h
wilhelm/src/android/android_SfPlayer.cpp
wilhelm/src/android/android_StreamPlayer.cpp
wilhelm/src/android/android_defs.h
wilhelm/src/autogen/IID_to_MPH.c
wilhelm/src/autogen/MPH_to_3DGroup.h
wilhelm/src/autogen/MPH_to_AudioPlayer.h
wilhelm/src/autogen/MPH_to_AudioRecorder.h
wilhelm/src/autogen/MPH_to_Engine.h
wilhelm/src/autogen/MPH_to_LEDDevice.h
wilhelm/src/autogen/MPH_to_Listener.h
wilhelm/src/autogen/MPH_to_MediaPlayer.h
wilhelm/src/autogen/MPH_to_MetadataExtractor.h
wilhelm/src/autogen/MPH_to_MidiPlayer.h
wilhelm/src/autogen/MPH_to_OutputMix.h
wilhelm/src/autogen/MPH_to_Vibra.h
wilhelm/src/classes.c
wilhelm/src/classes.h
wilhelm/src/data.h
wilhelm/src/interfaces.c
wilhelm/src/itf/IAndroidBufferQueue.c
wilhelm/src/itf/IEngine.c
wilhelm/src/itf/IStreamInformation.c
wilhelm/src/itfstruct.h
wilhelm/src/locks.c
wilhelm/src/sles.c
wilhelm/src/sles_allinclusive.h
wilhelm/tests/native-media/jni/native-media-jni.c
wilhelm/tests/sandbox/streamSource/slesTestPlayStream.cpp
wilhelm/tools/hashgen/Makefile
wilhelm/tools/hashgen/part6.c

index e2af814..4c6998a 100644 (file)
@@ -49,8 +49,9 @@ typedef struct XAAndroidBufferItem_ {
 
 typedef XAresult (XAAPIENTRY *xaAndroidBufferQueueCallback)(
     XAAndroidBufferQueueItf caller,/* input */
-    void *pContext,                /* input */
-    const void *pBufferData,       /* input */
+    void *pCallbackContext,        /* input */
+    void *pBufferContext,          /* input */
+    void *pBufferData,             /* input */
     XAuint32 dataSize,             /* input */
     XAuint32 dataUsed,             /* input */
     const XAAndroidBufferItem *pItems,/* input */
@@ -66,7 +67,7 @@ struct XAAndroidBufferQueueItf_ {
     XAresult (*RegisterCallback) (
         XAAndroidBufferQueueItf self,
         xaAndroidBufferQueueCallback callback,
-        void* pContext
+        void* pCallbackContext
     );
 
     XAresult (*Clear) (
@@ -75,7 +76,8 @@ struct XAAndroidBufferQueueItf_ {
 
     XAresult (*Enqueue) (
         XAAndroidBufferQueueItf self,
-        const void *pData,
+        void *pBufferContext,
+        void *pData,
         XAuint32 dataLength,
         const XAAndroidBufferItem *pItems,
         XAuint32 itemsLength
index 9f23e37..f2c03e5 100644 (file)
@@ -224,8 +224,9 @@ typedef struct SLAndroidBufferItem_ {
 
 typedef SLresult (SLAPIENTRY *slAndroidBufferQueueCallback)(
     SLAndroidBufferQueueItf caller,/* input */
-    void *pContext,                /* input */
-    const void *pBufferData,       /* input */
+    void *pCallbackContext,        /* input */
+    void *pBufferContext,          /* input */
+    void *pBufferData,             /* input */
     SLuint32 dataSize,             /* input */
     SLuint32 dataUsed,             /* input */
     const SLAndroidBufferItem *pItems,/* input */
@@ -241,7 +242,7 @@ struct SLAndroidBufferQueueItf_ {
     SLresult (*RegisterCallback) (
         SLAndroidBufferQueueItf self,
         slAndroidBufferQueueCallback callback,
-        void* pContext
+        void* pCallbackContext
     );
 
     SLresult (*Clear) (
@@ -250,7 +251,8 @@ struct SLAndroidBufferQueueItf_ {
 
     SLresult (*Enqueue) (
         SLAndroidBufferQueueItf self,
-        const void *pData,
+        void *pBufferContext,
+        void *pData,
         SLuint32 dataLength,
         const SLAndroidBufferItem *pItems,
         SLuint32 itemsLength
index 4207547..b8ca5e1 100644 (file)
 #define MPH_ANDROIDSIMPLEBUFFERQUEUE   49
 
 // Android API level 10 extended interfaces
-#define MPH_ANDROIDBUFFERQUEUE         50
+#define MPH_ANDROIDBUFFERQUEUE         50  // used for SL and XA
 
 // OpenMAX AL 1.0.1
 #define MPH_XAENGINE                   51
 #define MPH_XAPLAY                     52
 #define MPH_XASTREAMINFORMATION        53
+#define MPH_XAVOLUME                   54
 
 // total number of interface IDs
-#define MPH_MAX                        54
+#define MPH_MAX                        55
 
 #endif // !defined(__MPH_H)
index d63befd..269c6b7 100644 (file)
@@ -249,7 +249,9 @@ const signed char MPH_to_MediaPlayer[MPH_MAX] = {
     [MPH_OBJECT] = 0,
     [MPH_DYNAMICINTERFACEMANAGEMENT] = 1,
     [MPH_XAPLAY] = 2,
-    [MPH_ANDROIDBUFFERQUEUE] = 3,
+    [MPH_XASTREAMINFORMATION] = 3,
+    [MPH_XAVOLUME] = 4,
+    [MPH_ANDROIDBUFFERQUEUE] = 5,
     // FIXME more TBD
 #else
 #include "MPH_to_MediaPlayer.h"
index bef4ccc..9dbf5c4 100644 (file)
@@ -173,6 +173,8 @@ const struct SLInterfaceID_ SL_IID_array[MPH_MAX] = {
     { 0xb9c293e0, 0xf776, 0x11db, 0x80df, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
     // XA_IID_STREAMINFORMATION
     { 0x3a628fe0, 0x1238, 0x11de, 0xad9f, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
+    // XA_IID_VOLUME
+    { 0x088ba520, 0xf777, 0x11db, 0xa5e3, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
 
 // OpenMAX AL 1.0.1 Android API level 10 extended interfaces
     // XA_IID_ANDROIDBUFFERQUEUE
@@ -250,6 +252,7 @@ const XAInterfaceID XA_IID_ENGINE = (XAInterfaceID) &SL_IID_array[MPH_XAENGINE];
 const XAInterfaceID XA_IID_PLAY = (XAInterfaceID) &SL_IID_array[MPH_XAPLAY];
 const XAInterfaceID XA_IID_STREAMINFORMATION =
         (XAInterfaceID) &SL_IID_array[MPH_XASTREAMINFORMATION];
+const XAInterfaceID XA_IID_VOLUME = (XAInterfaceID) &SL_IID_array[MPH_XAVOLUME];
 
 // OpenMAX AL 1.0.1 Android API level 10 extended interfaces
 const XAInterfaceID XA_IID_ANDROIDBUFFERQUEUE =
index 243cc93..dec5c73 100644 (file)
@@ -639,7 +639,7 @@ static void sfplayer_prepare(CAudioPlayer *ap, bool lockAP) {
 //-----------------------------------------------------------------------------
 // Callback associated with an SfPlayer of an SL ES AudioPlayer that gets its data
 // from a URI or FD, for prepare and prefetch events
-static void sfplayer_handlePrefetchEvent(int event, int data1, void* user) {
+static void sfplayer_handlePrefetchEvent(int event, int data1, int data2, void* user) {
     if (NULL == user) {
         return;
     }
index a486567..8bda07a 100644 (file)
@@ -20,7 +20,7 @@
 
 
 //-----------------------------------------------------------------------------
-static void player_handleMediaPlayerEventNotifications(const int event, const int data1, void* user)
+static void player_handleMediaPlayerEventNotifications(int event, int data1, int data2, void* user)
 {
     if (NULL == user) {
         return;
@@ -31,15 +31,55 @@ static void player_handleMediaPlayerEventNotifications(const int event, const in
 
     switch(event) {
 
-    case android::GenericPlayer::kEventPrepared: {
+      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);
         }
+        break;
+      }
+
+      case android::GenericPlayer::kEventHasVideoSize: {
+        SL_LOGV("Received AVPlayer::kEventHasVideoSize (%d,%d) for CMediaPlayer %p",
+                data1, data2, mp);
+
+        object_lock_exclusive(&mp->mObject);
+
+        // remove an existing video info entry (here we only have one video stream)
+        for(size_t i=0 ; i < mp->mStreamInfo.mStreamInfoTable.size() ; i++) {
+            if (XA_DOMAINTYPE_VIDEO == mp->mStreamInfo.mStreamInfoTable.itemAt(i).domain) {
+                mp->mStreamInfo.mStreamInfoTable.removeAt(i);
+                break;
+            }
+        }
+        // update the stream information with a new video info entry
+        StreamInfo streamInfo;
+        streamInfo.domain = XA_DOMAINTYPE_VIDEO;
+        streamInfo.videoInfo.codecId = 0;// unknown, we don't have that info FIXME
+        streamInfo.videoInfo.width = (XAuint32)data1;
+        streamInfo.videoInfo.height = (XAuint32)data2;
+        streamInfo.videoInfo.bitRate = 0;// unknown, we don't have that info FIXME
+        streamInfo.videoInfo.duration = XA_TIME_UNKNOWN;
+        StreamInfo &contInfo = mp->mStreamInfo.mStreamInfoTable.editItemAt(0);
+        contInfo.containerInfo.numStreams = 1;
+        ssize_t index = mp->mStreamInfo.mStreamInfoTable.add(streamInfo);
+
+        xaStreamEventChangeCallback callback = mp->mStreamInfo.mCallback;
+        void* callbackPContext = mp->mStreamInfo.mContext;
+
+        object_unlock_exclusive(&mp->mObject);
+
+        // notify (outside of lock) that the stream information has been updated
+        if ((NULL != callback) && (index >= 0)) {
+            (*callback)(&mp->mStreamInfo.mItf, XA_STREAMCBEVENT_PROPERTYCHANGE /*eventId*/,
+                    1 /*streamIndex, only one stream supported here, 0 is reserved*/,
+                    NULL /*pEventData, always NULL in OpenMAX AL 1.0.1*/,
+                    callbackPContext /*pContext*/);
         }
         break;
+      }
 
     default:
         SL_LOGE("Received unknown event %d, data %d from AVPlayer", event, data1);
@@ -141,11 +181,6 @@ XAresult android_Player_create(CMediaPlayer *mp) {
     mp->mStreamType = ANDROID_DEFAULT_OUTPUT_STREAM_TYPE;
     mp->mSessionId = android::AudioSystem::newAudioSessionId();
 
-    mp->mAndroidAudioLevels.mAmplFromVolLevel = 1.0f;
-    mp->mAndroidAudioLevels.mAmplFromStereoPos[0] = 1.0f;
-    mp->mAndroidAudioLevels.mAmplFromStereoPos[1] = 1.0f;
-    mp->mAndroidAudioLevels.mAmplFromDirectLevel = 1.0f; // matches initial mDirectLevel value
-    mp->mAndroidAudioLevels.mAuxSendLevel = 0;
     mp->mDirectLevel = 0; // no attenuation
 
     return result;
@@ -274,6 +309,21 @@ XAresult android_Player_getDuration(IPlay *pPlayItf, XAmillisecond *pDurMsec) {
     return result;
 }
 
+
+//-----------------------------------------------------------------------------
+/**
+ * pre-condition: avp != NULL, pVolItf != NULL
+ */
+XAresult android_Player_volumeUpdate(android::GenericPlayer *avp, IVolume *pVolItf)
+{
+    XAresult result = XA_RESULT_SUCCESS;
+
+    avp->updateVolume((bool)pVolItf->mMute, (bool)pVolItf->mEnableStereoPosition,
+            pVolItf->mStereoPosition, pVolItf->mLevel);
+
+    return result;
+}
+
 //-----------------------------------------------------------------------------
 /**
  * pre-condition: avp != NULL
index 45dd542..bb8b965 100644 (file)
@@ -46,6 +46,11 @@ extern XAresult android_Player_setVideoSurfaceTexture(android::GenericMediaPlaye
 
 extern XAresult android_Player_getDuration(IPlay *pPlayItf, SLmillisecond *pDurMsec);
 
+/**
+ * pre-condition: avp != NULL, pVolItf != NULL
+ */
+extern XAresult android_Player_volumeUpdate(android::GenericPlayer *avp, IVolume *pVolItf);
+
 /**************************************************************************************************
  * Playback control and events
  ****************************/
index d480a86..f937b60 100644 (file)
@@ -459,15 +459,15 @@ void AudioSfDecoder::onNotify(const sp<AMessage> &msg) {
     int32_t val;
     if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val)) {
         SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val);
-        mNotifyClient(kEventPrefetchStatusChange, val, mNotifyUser);
+        mNotifyClient(kEventPrefetchStatusChange, val, 0, mNotifyUser);
     }
     else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val)) {
         SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val);
-        mNotifyClient(kEventPrefetchFillLevelUpdate, val, mNotifyUser);
+        mNotifyClient(kEventPrefetchFillLevelUpdate, val, 0, mNotifyUser);
     }
     else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val)) {
         SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val);
-        mNotifyClient(kEventEndOfStream, val, mNotifyUser);
+        mNotifyClient(kEventEndOfStream, val, 0, mNotifyUser);
     }
     else {
         GenericPlayer::onNotify(msg);
index 5e59008..07a1be1 100644 (file)
@@ -24,7 +24,8 @@
 namespace android {
 
 //--------------------------------------------------------------------------------------------------
-MediaPlayerNotificationClient::MediaPlayerNotificationClient() :
+MediaPlayerNotificationClient::MediaPlayerNotificationClient(GenericMediaPlayer* gmp) :
+    mGenericMediaPlayer(gmp),
     mPlayerPrepared(false)
 {
 
@@ -39,9 +40,18 @@ MediaPlayerNotificationClient::~MediaPlayerNotificationClient() {
 void MediaPlayerNotificationClient::notify(int msg, int ext1, int ext2) {
     SL_LOGI("MediaPlayerNotificationClient::notify(msg=%d, ext1=%d, ext2=%d)", msg, ext1, ext2);
 
-    if (msg == MEDIA_PREPARED) {
+    switch (msg) {
+      case MEDIA_PREPARED:
         mPlayerPrepared = true;
         mPlayerPreparedCondition.signal();
+        break;
+
+      case MEDIA_SET_VIDEO_SIZE:
+        mGenericMediaPlayer->notify(PLAYEREVENT_VIDEO_SIZE_UPDATE,
+                (int32_t)ext1, (int32_t)ext2, true /*async*/);
+        break;
+
+      default: { }
     }
 }
 
@@ -70,7 +80,7 @@ GenericMediaPlayer::GenericMediaPlayer(const AudioPlayback_Parameters* params, b
 
     CHECK(mMediaPlayerService.get() != NULL);
 
-    mPlayerClient = new MediaPlayerNotificationClient();
+    mPlayerClient = new MediaPlayerNotificationClient(this);
 }
 
 GenericMediaPlayer::~GenericMediaPlayer() {
@@ -125,6 +135,18 @@ void GenericMediaPlayer::onPause() {
         mPlayer->pause();
         mStateFlags &= ~kFlagPlaying;
     }
+}
+
+
+void GenericMediaPlayer::onVolumeUpdate() {
+    // use settings lock to read the volume settings
+    Mutex::Autolock _l(mSettingsLock);
+    if (this->mAndroidAudioLevels.mMute) {
+        mPlayer->setVolume(0.0f, 0.0f);
+    } else {
+        mPlayer->setVolume(mAndroidAudioLevels.mFinalVolume[0],
+                mAndroidAudioLevels.mFinalVolume[1]);
+    }
 
 }
 
index 0f497fd..e90604c 100644 (file)
 //--------------------------------------------------------------------------------------------------
 namespace android {
 
+class GenericMediaPlayer;
 class MediaPlayerNotificationClient : public BnMediaPlayerClient
 {
 public:
-    MediaPlayerNotificationClient();
+    MediaPlayerNotificationClient(GenericMediaPlayer* gmp);
     virtual ~MediaPlayerNotificationClient();
 
     // IMediaPlayerClient implementation
@@ -36,6 +37,7 @@ public:
 
 private:
     Mutex mLock;
+    GenericMediaPlayer* mGenericMediaPlayer;
     Condition mPlayerPreparedCondition;
     bool mPlayerPrepared;
 };
@@ -53,11 +55,13 @@ public:
     virtual void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
 
 protected:
+    friend class MediaPlayerNotificationClient;
 
     // Async event handlers (called from GenericPlayer's event loop)
     virtual void onPrepare();
     virtual void onPlay();
     virtual void onPause();
+    virtual void onVolumeUpdate();
 
     bool mHasVideo;
 
index bbedbdb..1af6db8 100644 (file)
@@ -27,12 +27,16 @@ GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) :
         mNotifyUser(NULL),
         mStateFlags(0),
         mLooperPriority(PRIORITY_DEFAULT),
-        mPlaybackParams(*params)
+        mPlaybackParams(*params),
+        mChannelCount(1)
 {
     SL_LOGI("GenericPlayer::GenericPlayer()");
 
     mLooper = new android::ALooper();
 
+    mAndroidAudioLevels.mMute = false;
+    mAndroidAudioLevels.mFinalVolume[0] = 1.0f;
+    mAndroidAudioLevels.mFinalVolume[1] = 1.0f;
 }
 
 
@@ -111,7 +115,7 @@ void GenericPlayer::play() {
 
 
 void GenericPlayer::pause() {
-    SL_LOGI("GenericPlayer::prepare()");
+    SL_LOGI("GenericPlayer::pause()");
     sp<AMessage> msg = new AMessage(kWhatPause, id());
     msg->post();
 }
@@ -147,6 +151,52 @@ void GenericPlayer::getDurationMsec(int* msec) {
     *msec = -1;
 }
 
+//--------------------------------------------------
+void GenericPlayer::updateVolume(bool mute, bool useStereoPos,
+        XApermille stereoPos, XAmillibel volume) {
+
+    // compute amplification as the combination of volume level and stereo position
+    float leftVol = 1.0f, rightVol = 1.0f;
+    //   amplification from volume level
+    leftVol  *= sles_to_android_amplification(volume);
+    rightVol = leftVol;
+
+    //   amplification from direct level (changed in SLEffectSendtItf and SLAndroidEffectSendItf)
+    // FIXME use calculation below when supporting effects
+    //leftVol  *= mAndroidAudioLevels.mAmplFromDirectLevel;
+    //rightVol *= mAndroidAudioLevels.mAmplFromDirectLevel;
+
+    // amplification from stereo position
+    if (useStereoPos) {
+        // panning law depends on number of channels of content: stereo panning vs 2ch. balance
+        if (1 == mChannelCount) {
+            // stereo panning
+            double theta = (1000 + stereoPos) * M_PI_4 / 1000.0f; // 0 <= theta <= Pi/2
+            leftVol  *= cos(theta);
+            rightVol *= sin(theta);
+        } else {
+            // stereo balance
+            if (stereoPos > 0) {
+                leftVol  *= (1000 - stereoPos) / 1000.0f;
+                rightVol *= 1.0f;
+            } else {
+                leftVol  *= 1.0f;
+                rightVol *= (1000 + stereoPos) / 1000.0f;
+            }
+        }
+    }
+
+    {
+        Mutex::Autolock _l(mSettingsLock);
+        mAndroidAudioLevels.mMute = mute;
+        mAndroidAudioLevels.mFinalVolume[0] = leftVol;
+        mAndroidAudioLevels.mFinalVolume[1] = rightVol;
+    }
+
+    // send a message for the volume to be updated by the object which implements the volume
+    (new AMessage(kWhatVolumeUpdate, id()))->post();
+}
+
 
 //--------------------------------------------------
 /*
@@ -169,6 +219,17 @@ void GenericPlayer::notify(const char* event, int data, bool async) {
 }
 
 
+void GenericPlayer::notify(const char* event, int data1, int data2, bool async) {
+    sp<AMessage> msg = new AMessage(kWhatNotif, id());
+    msg->setRect(event, 0, 0, (int32_t)data1, (int32_t)data2);
+    if (async) {
+        msg->post();
+    } else {
+        this->onNotify(msg);
+    }
+}
+
+
 //--------------------------------------------------
 // AHandler implementation
 void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) {
@@ -197,6 +258,10 @@ void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) {
             onLoop(msg);
             break;
 
+        case kWhatVolumeUpdate:
+            onVolumeUpdate();
+            break;
+
         default:
             TRESPASS();
     }
@@ -220,10 +285,13 @@ void GenericPlayer::onNotify(const sp<AMessage> &msg) {
         return;
     }
 
-    int32_t val;
-    if (msg->findInt32(PLAYEREVENT_PREPARED, &val)) {
-        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val);
-        mNotifyClient(kEventPrepared, val, mNotifyUser);
+    int32_t val1, val2;
+    if (msg->findInt32(PLAYEREVENT_PREPARED, &val1)) {
+        SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val1);
+        mNotifyClient(kEventPrepared, val1, 0, mNotifyUser);
+    } else if (msg->findRect(PLAYEREVENT_VIDEO_SIZE_UPDATE, &val1, &val2, &val1, &val2)) {
+        SL_LOGD("GenericPlayer notifying %s = %d, %d", PLAYEREVENT_VIDEO_SIZE_UPDATE, val1, val2);
+        mNotifyClient(kEventHasVideoSize, val1, val2, mNotifyUser);
     }
 }
 
@@ -257,4 +325,9 @@ void GenericPlayer::onLoop(const sp<AMessage> &msg) {
     SL_LOGV("GenericPlayer::onLoop");
 }
 
+
+void GenericPlayer::onVolumeUpdate() {
+
+}
+
 } // namespace android
index a1a3b9c..ebef9f8 100644 (file)
@@ -23,7 +23,8 @@ class GenericPlayer : public AHandler
 public:
 
     enum {
-        kEventPrepared                = 'prep'
+        kEventPrepared      = 'prep',
+        kEventHasVideoSize  = 'vsiz',
     };
 
     GenericPlayer(const AudioPlayback_Parameters* params);
@@ -43,23 +44,28 @@ public:
 
     virtual void getDurationMsec(int* msec); // -1 if unknown
 
+    void updateVolume(bool mute, bool useStereoPos, XApermille stereoPos, XAmillibel volume);
+
 protected:
+    Mutex mSettingsLock;
 
     void resetDataLocator();
     DataLocator2 mDataLocator;
     int          mDataLocatorType;
 
     enum {
-        kWhatPrepare    = 'prep',
-        kWhatNotif      = 'noti',
-        kWhatPlay       = 'play',
-        kWhatPause      = 'paus',
-        kWhatSeek       = 'seek',
-        kWhatLoop       = 'loop',
+        kWhatPrepare      = 'prep',
+        kWhatNotif        = 'noti',
+        kWhatPlay         = 'play',
+        kWhatPause        = 'paus',
+        kWhatSeek         = 'seek',
+        kWhatLoop         = 'loop',
+        kWhatVolumeUpdate = 'volu'
     };
 
     // Send a notification to one of the event listeners
-    virtual void notify(const char* event, int data, bool async);
+    virtual void notify(const char* event, int data1, bool async);
+    virtual void notify(const char* event, int data1, int data2, bool async);
 
     // AHandler implementation
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -71,6 +77,7 @@ protected:
     virtual void onPause();
     virtual void onSeek(const sp<AMessage> &msg);
     virtual void onLoop(const sp<AMessage> &msg);
+    virtual void onVolumeUpdate();
 
     // Event notification from GenericPlayer to OpenSL ES / OpenMAX AL framework
     notif_cbf_t mNotifyClient;
@@ -92,6 +99,9 @@ protected:
 
     AudioPlayback_Parameters mPlaybackParams;
 
+    AndroidAudioLevels mAndroidAudioLevels;
+    int mChannelCount; // this is used for the panning law, and is not exposed outside of the object
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(GenericPlayer);
 };
index 05c7563..9cf8d7d 100644 (file)
@@ -733,25 +733,25 @@ void SfPlayer::onNotify(const sp<AMessage> &msg) {
     int32_t val;
     if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val)) {
         SL_LOGV("\tSfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val);
-        mNotifyClient(kEventPrefetchStatusChange, val, mNotifyUser);
+        mNotifyClient(kEventPrefetchStatusChange, val, 0, mNotifyUser);
     }
     if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val)) {
         SL_LOGV("\tSfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val);
-        mNotifyClient(kEventPrefetchFillLevelUpdate, val, mNotifyUser);
+        mNotifyClient(kEventPrefetchFillLevelUpdate, val, 0, mNotifyUser);
     }
     if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val)) {
         SL_LOGV("\tSfPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val);
-        mNotifyClient(kEventEndOfStream, val, mNotifyUser);
+        mNotifyClient(kEventEndOfStream, val, 0, mNotifyUser);
     }
 
     if (msg->findInt32(PLAYEREVENT_PREPARED, &val)) {
         SL_LOGV("\tSfPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val);
-        mNotifyClient(GenericMediaPlayer::kEventPrepared, val, mNotifyUser);
+        mNotifyClient(GenericMediaPlayer::kEventPrepared, val, 0, mNotifyUser);
     }
 
     if (msg->findInt32(PLAYEREVENT_NEW_AUDIOTRACK, &val)) {
         SL_LOGV("\tSfPlayer notifying %s", PLAYEREVENT_NEW_AUDIOTRACK);
-        mNotifyClient(kEventNewAudioTrack, val, mNotifyUser);
+        mNotifyClient(kEventNewAudioTrack, val, 0, mNotifyUser);
     }
 }
 
index 609cd52..fce384e 100644 (file)
@@ -218,6 +218,7 @@ void StreamSourceAppProxy::pullFromBuffQueue() {
         // oldFront was only initialized in the code path where callback is initialized
         //    so no need to check if it's valid
         (*callback)(&mAndroidBufferQueue->mItf, callbackPContext,
+                (void *)oldFront->mBufferContext, /* pBufferContext */
                 (void *)oldFront->mDataBuffer,/* pBufferData  */
                 oldFront->mDataSize, /* dataSize  */
                 // here a buffer is only dequeued when fully consumed
@@ -286,11 +287,8 @@ void StreamPlayer::queueRefilled_l() {
 
 
 void StreamPlayer::appClear_l() {
-    // the user of StreamPlayer has cleared its AndroidBufferQueue: a discontinuity is expected
-    Mutex::Autolock _l(mAppProxyLock);
-    if (mAppProxy != 0) {
-        mAppProxy->receivedCmd_l(IStreamListener::DISCONTINUITY);
-    }
+    // the user of StreamPlayer has cleared its AndroidBufferQueue:
+    // there's no clear() for the shared memory queue, so this is a no-op
 }
 
 
index b52a95d..c47df99 100644 (file)
@@ -59,27 +59,33 @@ enum AndroidObject_state {
  * Structure to maintain the set of audio levels about a player
  */
 typedef struct AndroidAudioLevels_struct {
-/** send level to aux effect, there's a single aux bus, so there's a single level */
-    SLmillibel mAuxSendLevel;
     /**
-     * Amplification (can be attenuation) factor derived for the VolumeLevel
+     * Is this player muted
      */
-    float mAmplFromVolLevel;
+    bool mMute;
     /**
-     * Left/right amplification (can be attenuations) factors derived for the StereoPosition
+     * Send level to aux effect, there's a single aux bus, so there's a single level
      */
-    float mAmplFromStereoPos[STEREO_CHANNELS];
+    // FIXME not used yet, will be used when supporting effects in OpenMAX AL
+    //SLmillibel mAuxSendLevel;
     /**
      * Attenuation factor derived from direct level
      */
-    float mAmplFromDirectLevel;
+    // FIXME not used yet, will be used when supporting effects in OpenMAX AL
+    //float mAmplFromDirectLevel;
+    /**
+     * Android Left/Right volume
+     * The final volume of an Android AudioTrack or MediaPlayer is a stereo amplification
+     * (or attenuation) represented as a float from 0.0f to 1.0f
+     */
+    float mFinalVolume[STEREO_CHANNELS];
 } AndroidAudioLevels;
 
 
 /**
  * Event notification callback from Android to SL ES framework
  */
-typedef void (*notif_cbf_t)(int event, int data1, void* notifUser);
+typedef void (*notif_cbf_t)(int event, int data1, int data2, void* notifUser);
 
 /**
  * Audio data push callback from Android objects to SL ES framework
@@ -96,6 +102,7 @@ typedef size_t (*data_push_cbf_t)(const uint8_t *data, size_t size, void* user);
 #define PLAYEREVENT_PREFETCHFILLLEVELUPDATE "pflu"
 #define PLAYEREVENT_ENDOFSTREAM             "eos"
 #define PLAYEREVENT_NEW_AUDIOTRACK          "nwat"
+#define PLAYEREVENT_VIDEO_SIZE_UPDATE       "vsiz"
 
 
 /**
index 76a85e1..04a29ef 100644 (file)
@@ -29,37 +29,61 @@ extern const struct SLInterfaceID_ SL_IID_array[MPH_MAX];
 
 int IID_to_MPH(const SLInterfaceID iid)
 {
-#define MAX_HASH_VALUE 115
+#define MAX_HASH_VALUE 139
   static const unsigned char asso_values[] =
     {
-        5, 116, 116,   2, 116, 116,  17, 116, 116,  17,
-      116,  22, 116, 116, 116,  51, 116, 116, 116, 116,
-      116, 116,   2, 116, 116,  46, 116, 116, 116, 116,
-      116,  17,  20, 116, 116, 116, 116, 116, 116, 116,
-      116, 116,  51,  20,  46, 116,  31, 116, 116, 116,
-      116, 116, 116,  36, 116,   2, 116, 116,   2, 116,
-      116,  61, 116,   2,  55, 116, 116, 116, 116,  16,
-      116,  26, 116, 116, 116, 116, 116, 116, 116, 116,
-       21, 116, 116, 116, 116, 116,  26, 116, 116, 116,
-       11, 116, 116, 116, 116, 116,  40,  21, 116,  60,
-      116, 116, 116, 116, 116, 116,  16, 116, 116, 116,
-      116, 116,   1, 116, 116, 116, 116, 116, 116, 116,
-      116,  11,  55,   6, 116, 116, 116,   6,  45, 116,
-      116,   1, 116, 116, 116, 116, 116,   1, 116, 116,
-      116,   1, 116, 116, 116, 116, 116, 116, 116, 116,
-      116,  60, 116, 116, 116, 116, 116, 116, 116, 116,
-       10, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-       50, 116, 116, 116,  45, 116, 116, 116,  60, 116,
-       45, 116, 116, 116, 116,  55, 116, 116, 116, 116,
-      116, 116,  15, 116,  35, 116,  45,   5, 116,  50,
-      116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-      116, 116,  40, 116, 116,  50, 116, 116, 116, 116,
-      116,  25, 116, 116,  15,  40, 116, 116,  10, 116,
-      116, 116, 116, 116, 116,  10,   0, 116, 116,  15,
-       30, 116, 116, 116, 116, 116,  55, 116, 116, 116,
-      116, 116, 116, 116,   0, 116
+        5, 140, 140,   7, 140, 140,  27, 140,  17,  17,
+      140,  22, 140, 140, 140,  51, 140, 140, 140, 140,
+      140, 140,   2, 140, 140,  46, 140, 140, 140, 140,
+      140,  17,  20, 140, 140, 140, 140, 140, 140, 140,
+      140, 140,  51,  20,  46, 140,  31, 140, 140, 140,
+      140, 140, 140,  36, 140,   2, 140, 140,   2, 140,
+      140,  61, 140,   2,  55, 140, 140, 140, 140,  16,
+      140,  26, 140, 140, 140, 140, 140, 140, 140, 140,
+       21, 140, 140, 140, 140, 140,  26, 140, 140, 140,
+       11, 140, 140, 140, 140, 140,  40,  21, 140,  60,
+      140, 140, 140, 140, 140, 140,  16, 140, 140, 140,
+      140, 140,   1, 140, 140, 140, 140, 140, 140, 140,
+      140,  11,  55,   6, 140, 140, 140,   6,  45, 140,
+      140,   1, 140, 140, 140, 140, 140,   1, 140, 140,
+      140,   1, 140, 140, 140, 140, 140, 140, 140, 140,
+      140,  60, 140, 140, 140, 140, 140, 140, 140, 140,
+       10, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+       50, 140, 140, 140,  45, 140, 140, 140,  60, 140,
+       45, 140, 140, 140, 140,  55, 140, 140, 140, 140,
+      140, 140,  15, 140,  35, 140,  45,   5, 140,  50,
+      140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+      140, 140,  40, 140, 140,  50, 140, 140, 140, 140,
+      140,  25, 140, 140,  15,  40, 140, 140,  10, 140,
+      140, 140, 140, 140, 140,  10,   0, 140, 140,  15,
+       30, 140, 140, 140, 140, 140,  55, 140, 140, 140,
+      140, 140, 140, 140,   0, 140
     };
     static const signed char hash_to_MPH[] = {
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
+        -1,
         MPH_NULL,
         -1,
         -1,
@@ -97,7 +121,7 @@ int IID_to_MPH(const SLInterfaceID iid)
         -1,
         MPH_BUFFERQUEUE,
         MPH_3DMACROSCOPIC,
-        MPH_BASSBOOST,
+        MPH_XAVOLUME,
         -1,
         -1,
         MPH_3DLOCATION,
@@ -107,12 +131,12 @@ int IID_to_MPH(const SLInterfaceID iid)
         -1,
         MPH_MIDIMESSAGE,
         MPH_ANDROIDBUFFERQUEUE,
-        MPH_MIDIMUTESOLO,
+        MPH_BASSBOOST,
         -1,
         -1,
         MPH_SEEK,
         MPH_OBJECT,
-        -1,
+        MPH_MIDIMUTESOLO,
         -1,
         -1,
         MPH_PITCH,
@@ -180,8 +204,9 @@ int IID_to_MPH(const SLInterfaceID iid)
     if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid)
         return iid - &SL_IID_array[0];
     if (NULL != iid) {
-        unsigned key = asso_values[((unsigned char *)iid)[3]] +
-            asso_values[((unsigned char *)iid)[0]];
+        static const unsigned len = sizeof(struct SLInterfaceID_);
+        unsigned key = len +
+            asso_values[((unsigned char *)iid)[3]] + asso_values[((unsigned char *)iid)[0]];
         if (key <= MAX_HASH_VALUE) {
             int MPH = hash_to_MPH[key];
             if (MPH >= 0) {
index 0d1fcd2..ea40508 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1,  3, -1,  2,  5,  4, -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, -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
index 445ac37..cd4a9d7 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1,  3,  4,  5, 16,  6, -1, -1, -1, -1, 17,  7, -1,  1, 18,  8, -1, -1, 19, 20,
  -1, 10, 11, -1, -1, -1, -1,  9, -1,  0, -1, 21,  2, 23, 12, 22, 13, -1, 14, -1,
- -1, 24, 25, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ -1, 24, 25, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
index f063838..4d84a8e 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1, -1, -1, -1, -1, -1, -1,  3, -1, -1,  4, -1, -1,  1,  5, -1, -1, -1, -1,  6,
  -1, -1, -1, -1, -1, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1,  2, -1, -1,
- -1, -1,  7,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ -1, -1,  7,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
index b0fdda9..0c62597 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
   8, -1, -1, -1, -1, -1,  6, -1,  7,  5, -1, -1,  9,  1, -1, -1,  2,  3, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1,  0, -1, -1, -1, -1, -1, -1, -1, -1, -1,  4,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1
index 9812ff8..87efa73 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1,
   2, -1, -1, -1, -1, -1, -1, -1, -1,  0, -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
index a4cff75..4b0d17b 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1,  2, -1,  3, -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, -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
index 63c2e9b..33654a0 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  3, -1,  2, -1
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  5, -1,  2,  3,  4
index c05f94b..38995c4 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  1,  2, -1, -1, -1, -1, -1,
  -1,  3,  4, -1, -1, -1, -1, -1, -1,  0, -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
index d6af046..86256d2 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1,  3,  4,  5, 19,  6, -1, -1, -1, -1, 20,  7, -1,  1, 21,  8, -1, -1, 22, 23,
  -1, 10, 11, 12, 15, 14, 13,  9, -1,  0, -1, 24,  2, 26, 16, 25, -1, -1, 17, -1,
- -1, 27, 28, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ -1, 27, 28, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
index 3e466b6..829710c 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  9, -1, -1,  1, -1, -1, -1, -1,  4,  5,
  -1, -1, -1, -1, -1, -1, -1, -1, -1,  0,  2, -1, -1, -1, -1,  6, -1, -1, -1, -1,
- -1,  7, 10,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ -1,  7, 10,  8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
index f046e25..e7d4b5a 100644 (file)
@@ -1,4 +1,4 @@
 // This file is automagically generated by mphtogen, do not edit
  -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+  2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
index 5086354..c719ae6 100644 (file)
@@ -405,6 +405,8 @@ static const struct iid_vtable MediaPlayer_interfaces[INTERFACES_MediaPlayer] =
     {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT,
         offsetof(CMediaPlayer, mDynamicInterfaceManagement)},
     {MPH_XAPLAY, INTERFACE_IMPLICIT, offsetof(CMediaPlayer, mPlay)},
+    {MPH_XASTREAMINFORMATION, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mStreamInfo)},
+    {MPH_XAVOLUME, INTERFACE_IMPLICIT, offsetof(CMediaPlayer, mVolume)},
 #ifdef ANDROID
     {MPH_ANDROIDBUFFERQUEUE, INTERFACE_EXPLICIT, offsetof(CMediaPlayer, mAndroidBufferQueue)},
 #endif
index 24659c3..7f685d0 100644 (file)
@@ -302,12 +302,13 @@ typedef struct {
 
 typedef struct CMediaPlayer_struct {
     IObject mObject;
-#define INTERFACES_MediaPlayer 4
+#define INTERFACES_MediaPlayer 6
     XAuint8 mInterfaceStates2[INTERFACES_MediaPlayer - INTERFACES_Default];
     IDynamicInterfaceManagement mDynamicInterfaceManagement;
     IDynamicSource mDynamicSource;
     IPlay mPlay;
     IStreamInformation mStreamInfo;
+    IVolume mVolume;
 #ifdef ANDROID
     IAndroidBufferQueue mAndroidBufferQueue;
 #endif
@@ -331,6 +332,5 @@ typedef struct CMediaPlayer_struct {
     int mSessionId;
     /** identifies the Android stream type playback will occur on */
     int mStreamType;
-    AndroidAudioLevels mAndroidAudioLevels;
 #endif
 } CMediaPlayer;
index cfebadd..7a6e380 100644 (file)
@@ -104,5 +104,9 @@ typedef struct {
         XAImageStreamInformation imageInfo;
         XATimedTextStreamInformation textInfo;
         XAMIDIStreamInformation midiInfo;
+        XAVendorStreamInformation vendorInfo;
     };
 } StreamInfo;
+
+// FIXME a terrible hack until OpenMAX AL spec is updated
+#define XA_DOMAINTYPE_CONTAINER 0
index 97aa940..d7f90e7 100644 (file)
@@ -85,6 +85,7 @@ const char * const interface_names[MPH_MAX] = {
     "XAENGINE",
     "XAPLAY",
     "XASTREAMINFORMATION",
+    "XAVOLUME",
 
 };
 
index bea4701..fa4c7e9 100644 (file)
@@ -158,6 +158,7 @@ SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)
         thiz->mBufferArray[i].mDataBuffer = NULL;
         thiz->mBufferArray[i].mDataSize = 0;
         thiz->mBufferArray[i].mDataSizeConsumed = 0;
+        thiz->mBufferArray[i].mBufferContext = NULL;
         switch (thiz->mBufferType) {
           case kAndroidBufferTypeMpeg2Ts:
             thiz->mBufferArray[i].mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
@@ -191,7 +192,8 @@ SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)
 
 
 SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,
-        const void *pData,
+        void *pBufferContext,
+        void *pData,
         SLuint32 dataLength,
         const SLAndroidBufferItem *pItems,
         SLuint32 itemsLength)
@@ -233,6 +235,7 @@ SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,
             oldRear->mDataBuffer = pData;
             oldRear->mDataSize = dataLength;
             oldRear->mDataSizeConsumed = 0;
+            oldRear->mBufferContext = pBufferContext;
             thiz->mRear = newRear;
             ++thiz->mState.count;
             setItems(pItems, itemsLength, thiz->mBufferType, oldRear);
index 648767c..7d07c02 100644 (file)
@@ -311,6 +311,7 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
                                 switch (thiz->mAndroidBufferQueue.mBufferType) {
                                   case kAndroidBufferTypeMpeg2Ts:
                                     thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
@@ -1156,6 +1157,17 @@ static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer
                         if (XA_CONTAINERTYPE_MPEG_TS ==
                                 thiz->mDataSource.mFormat.mMIME.containerType) {
                             thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
+
+                            // Set the container type for the StreamInformation interface
+                            XAMediaContainerInformation *containerInfo =
+                                    (XAMediaContainerInformation*)
+                                        // always storing container info at index 0, as per spec
+                                        &(thiz->mStreamInfo.mStreamInfoTable.itemAt(0).
+                                                containerInfo);
+                            containerInfo->containerType = XA_CONTAINERTYPE_MPEG_TS;
+                            // there are no streams at this stage
+                            containerInfo->numStreams = 0;
+
                         } else {
                             thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
                             SL_LOGE("Invalid buffer type in Android Buffer Queue");
@@ -1173,6 +1185,7 @@ static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
                                 switch (thiz->mAndroidBufferQueue.mBufferType) {
                                   case kAndroidBufferTypeMpeg2Ts:
                                     thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
index a983caa..0769784 100644 (file)
@@ -26,6 +26,7 @@ static XAresult IStreamInformation_QueryMediaContainerInformation( XAStreamInfor
 #ifdef ANDROID
     IStreamInformation *thiz = (IStreamInformation *) self;
     interface_lock_exclusive(thiz);
+    // always storing container info at index 0, as per spec
     info = (XAMediaContainerInformation*)&(thiz->mStreamInfoTable.itemAt(0).containerInfo);
     interface_unlock_exclusive(thiz);
     // even though the pointer to the media container info is returned, the values aren't set
@@ -63,6 +64,7 @@ static XAresult IStreamInformation_QueryStreamType( XAStreamInformationItf self,
         IStreamInformation *thiz = (IStreamInformation *) self;
 
         interface_lock_exclusive(thiz);
+
         XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
         // streams in the container are numbered 1..nbStreams
         if (streamIndex <= nbStreams) {
@@ -73,6 +75,7 @@ static XAresult IStreamInformation_QueryStreamType( XAStreamInformationItf self,
                     streamIndex, nbStreams);
             result = XA_RESULT_PARAMETER_INVALID;
         }
+
         interface_unlock_exclusive(thiz);
     }
 #endif
@@ -87,8 +90,62 @@ static XAresult IStreamInformation_QueryStreamInformation( XAStreamInformationIt
 {
     XA_ENTER_INTERFACE
 
-    SL_LOGE("unsupported XAStreamInformationItf function");
-    result = XA_RESULT_CONTENT_UNSUPPORTED;
+    if (NULL == info) {
+        result = XA_RESULT_PARAMETER_INVALID;
+    } else {
+
+#ifndef ANDROID
+        result = XA_RESULT_FEATURE_UNSUPPORTED;
+#else
+
+        IStreamInformation *thiz = (IStreamInformation *) self;
+
+        interface_lock_exclusive(thiz);
+
+        XAuint32 nbStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
+        // streams in the container are numbered 1..nbStreams
+        if (streamIndex <= nbStreams) {
+            result = XA_RESULT_SUCCESS;
+            const StreamInfo& streamInfo = thiz->mStreamInfoTable.itemAt((size_t)streamIndex);
+
+            switch (streamInfo.domain) {
+            case XA_DOMAINTYPE_CONTAINER:
+                *(XAMediaContainerInformation *)info = streamInfo.containerInfo;
+                break;
+            case XA_DOMAINTYPE_AUDIO:
+                *(XAAudioStreamInformation *)info = streamInfo.audioInfo;
+                break;
+            case XA_DOMAINTYPE_VIDEO:
+                *(XAVideoStreamInformation *)info = streamInfo.videoInfo;
+                break;
+            case XA_DOMAINTYPE_IMAGE:
+                *(XAImageStreamInformation *)info = streamInfo.imageInfo;
+                break;
+            case XA_DOMAINTYPE_TIMEDTEXT:
+                *(XATimedTextStreamInformation *)info = streamInfo.textInfo;
+                break;
+            case XA_DOMAINTYPE_MIDI:
+                *(XAMIDIStreamInformation *)info = streamInfo.midiInfo;
+                break;
+            case XA_DOMAINTYPE_VENDOR:
+                *(XAVendorStreamInformation *)info = streamInfo.vendorInfo;
+                break;
+            default:
+                SL_LOGE("StreamInformation::QueryStreamInformation index %lu has unknown domain %lu", streamIndex, streamInfo.domain);
+                result = XA_RESULT_INTERNAL_ERROR;
+                break;
+            }
+
+        } else {
+            SL_LOGE("Querying stream type for stream %ld, only %ld streams available",
+                    streamIndex, nbStreams);
+            result = XA_RESULT_PARAMETER_INVALID;
+        }
+
+        interface_unlock_exclusive(thiz);
+#endif
+
+    }
 
     XA_LEAVE_INTERFACE
 }
@@ -149,10 +206,15 @@ static XAresult IStreamInformation_QueryActiveStreams( XAStreamInformationItf se
         XA_LEAVE_INTERFACE;
     }
 
-    SL_LOGE("unsupported XAStreamInformationItf function");
-    result = XA_RESULT_CONTENT_UNSUPPORTED;
-    *numStreams = 0;
-    activeStreams = NULL;
+    IStreamInformation *thiz = (IStreamInformation *) self;
+
+    interface_lock_exclusive(thiz);
+
+    result = XA_RESULT_SUCCESS;
+    *numStreams = thiz->mStreamInfoTable.itemAt(0).containerInfo.numStreams;
+    activeStreams = thiz->mActiveStreams;
+
+    interface_unlock_exclusive(thiz);
 
     XA_LEAVE_INTERFACE
 }
@@ -182,21 +244,40 @@ static const struct XAStreamInformationItf_ IStreamInformation_Itf = {
     IStreamInformation_SetActiveStream
 };
 
+
 void IStreamInformation_init(void *self)
 {
+    SL_LOGV("IStreamInformation_init\n");
     IStreamInformation *thiz = (IStreamInformation *) self;
     thiz->mItf = &IStreamInformation_Itf;
 
     thiz->mCallback = NULL;
     thiz->mContext = NULL;
 
+    for (int i=0 ; i < NB_SUPPORTED_STREAMS ; i++) {
+        thiz->mActiveStreams[i] = XA_BOOLEAN_FALSE;
+    }
+
 #ifdef ANDROID
+    // placement new constructor for C++ field within C struct
+    (void) new (&thiz->mStreamInfoTable) android::Vector<StreamInfo>();
     // initialize container info
     StreamInfo contInf;
-    contInf.domain = XA_DOMAINTYPE_UNKNOWN; // there should really be a domain for the container!
+    contInf.domain = XA_DOMAINTYPE_CONTAINER;
     contInf.containerInfo.containerType = XA_CONTAINERTYPE_UNSPECIFIED;
     contInf.containerInfo.mediaDuration = XA_TIME_UNKNOWN;
+    // FIXME shouldn't this be 1 ?
     contInf.containerInfo.numStreams = 0;
+    // always storing container info at index 0, as per spec: here, the table was still empty
     thiz->mStreamInfoTable.add(contInf);
 #endif
 }
+
+
+void IStreamInformation_deinit(void *self) {
+#ifdef ANDROID
+    IStreamInformation *thiz = (IStreamInformation *) self;
+    // explicit destructor
+    thiz->mStreamInfoTable.~Vector<StreamInfo>();
+#endif
+}
index 0318414..1a6e8dc 100644 (file)
@@ -583,11 +583,13 @@ typedef struct {
     IObject *mThis;
 } IXAEngine;
 
+#define NB_SUPPORTED_STREAMS 1 // only one (video) stream supported in this implementation
 typedef struct {
     const struct XAStreamInformationItf_ *mItf;
     IObject *mThis;
     xaStreamEventChangeCallback mCallback;
     void *mContext;
+    XAboolean mActiveStreams[NB_SUPPORTED_STREAMS];
 #ifdef ANDROID
     android::Vector<StreamInfo> mStreamInfoTable;
 #endif
index 7beba2e..cf54648 100644 (file)
@@ -139,6 +139,17 @@ void object_unlock_exclusive_attributes(IObject *thiz, unsigned attributes)
             // MIDI
             SL_LOGD("[ FIXME: gain update on an SL_OBJECTID_MIDIPLAYER to be implemented ]");
             break;
+        case XA_OBJECTID_MEDIAPLAYER: {
+#ifdef ANDROID
+            attributes &= ~ATTR_GAIN;   // no need to process asynchronously also
+            CMediaPlayer *mp = (CMediaPlayer *) thiz;
+            android::GenericPlayer* avp = mp->mAVPlayer.get();
+            if (avp != NULL) {
+                android_Player_volumeUpdate(avp, &mp->mVolume);
+            }
+#endif
+            break;
+        }
         default:
             break;
         }
index a56fbf8..7fa4065 100644 (file)
@@ -269,7 +269,8 @@ extern void
     IVibra_init(void *),
     IVirtualizer_init(void *),
     IVisualization_init(void *),
-    IVolume_init(void *);
+    IVolume_init(void *),
+    IStreamInformation_init(void*);
 
 extern void
     I3DGrouping_deinit(void *),
@@ -284,7 +285,8 @@ extern void
     IObject_deinit(void *),
     IPresetReverb_deinit(void *),
     IThreadSync_deinit(void *),
-    IVirtualizer_deinit(void *);
+    IVirtualizer_deinit(void *),
+    IStreamInformation_deinit(void *);
 
 extern bool
     IAndroidEffectCapabilities_Expose(void *),
@@ -345,6 +347,7 @@ extern void
 #define IAndroidEffectCapabilities_deinit NULL
 #define IAndroidEffectCapabilities_Expose NULL
 #define IAndroidBufferQueue_init          NULL
+#define IStreamInformation_init           NULL
 #endif
 
 #ifndef USE_OUTPUTMIXEXT
@@ -417,6 +420,9 @@ extern void
 // OpenMAX AL 1.0.1 interfaces
     { /* MPH_XAENGINE */ IXAEngine_init, NULL, NULL, NULL, NULL },
     { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
+    { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
+        NULL, NULL },
+    { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
 };
 
 
index aa59615..3a20c84 100644 (file)
@@ -250,6 +250,7 @@ typedef struct {
     SLuint32 mDataSize;
     SLuint32 mDataSizeConsumed;
     AdvancedBufferItems mItems;
+    const void *mBufferContext;
 } AdvancedBufferHeader;
 #endif
 
index e168c3e..fe087fc 100644 (file)
@@ -18,6 +18,7 @@
 #include <jni.h>
 #include <pthread.h>
 #include <string.h>
+#define LOG_NDEBUG 0
 #define LOG_TAG "NativeMedia"
 #include <utils/Log.h>
 
@@ -40,8 +41,10 @@ static XAObjectItf outputMixObject = NULL;
 static XAObjectItf             playerObj = NULL;
 static XAPlayItf               playerPlayItf = NULL;
 static XAAndroidBufferQueueItf playerBQItf = NULL;
+static XAStreamInformationItf  playerStreamInfoItf = NULL;
+static XAVolumeItf             playerVolItf;
 // number of required interfaces for the MediaPlayer creation
-#define NB_MAXAL_INTERFACES 2 // XAAndroidBufferQueueItf and XAPlayItf
+#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf
 
 // cached surface where the video display happens
 #if NO_NATIVE_WINDOW
@@ -67,17 +70,62 @@ char reachedEof = 0;
 // AndroidBufferQueueItf callback for an audio player
 XAresult AndroidBufferQueueCallback(
         XAAndroidBufferQueueItf caller,
-        void *pContext,                /* input */
-        const void *pBufferData,       /* input */
+        void *pCallbackContext,        /* input */
+        void *pBufferContext,          /* input */
+        void *pBufferData,             /* input */
         XAuint32 dataSize,             /* input */
         XAuint32 dataUsed,             /* input */
         const XAAndroidBufferItem *pItems,/* input */
         XAuint32 itemsLength           /* input */)
 {
     // assert(BUFFER_SIZE <= dataSize);
+    if (pBufferData == NULL) {
+        // this is the case when our buffer with the EOS message has been consumed
+        return XA_RESULT_SUCCESS;
+    }
+
+#if 0
+    // sample code to use the XAVolumeItf
+    XAAndroidBufferQueueState state;
+    (*caller)->GetState(caller, &state);
+    switch (state.index) {
+    case 300:
+        (*playerVolItf)->SetVolumeLevel(playerVolItf, -600); // -6dB
+        LOGV("setting volume to -6dB");
+        break;
+    case 400:
+        (*playerVolItf)->SetVolumeLevel(playerVolItf, -1200); // -12dB
+        LOGV("setting volume to -12dB");
+        break;
+    case 500:
+        (*playerVolItf)->SetVolumeLevel(playerVolItf, 0); // full volume
+        LOGV("setting volume to 0dB (full volume)");
+        break;
+    case 600:
+        (*playerVolItf)->SetMute(playerVolItf, XA_BOOLEAN_TRUE); // mute
+        LOGV("muting player");
+        break;
+    case 700:
+        (*playerVolItf)->SetMute(playerVolItf, XA_BOOLEAN_FALSE); // unmute
+        LOGV("unmuting player");
+        break;
+    case 800:
+        (*playerVolItf)->SetStereoPosition(playerVolItf, -1000);
+        (*playerVolItf)->EnableStereoPosition(playerVolItf, XA_BOOLEAN_TRUE);
+        LOGV("pan sound to the left (hard-left)");
+        break;
+    case 900:
+        (*playerVolItf)->EnableStereoPosition(playerVolItf, XA_BOOLEAN_FALSE);
+        LOGV("disabling stereo position");
+        break;
+    default:
+        break;
+    }
+#endif
+
     size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE, file);
-    if (nbRead > 0) {
-        (*caller)->Enqueue(caller,
+    if ((nbRead > 0) && (NULL != pBufferData)) {
+        (*caller)->Enqueue(caller, NULL /*pBufferContext*/,
                 pBufferData /*pData*/,
                 nbRead /*dataLength*/,
                 NULL /*pMsg*/,
@@ -89,9 +137,10 @@ XAresult AndroidBufferQueueCallback(
         msgEos.itemSize = 0;
         // EOS message has no parameters, so the total size of the message is the size of the key
         //   plus the size if itemSize, both XAuint32
-        (*caller)->Enqueue(caller, NULL /*pData*/, 0 /*dataLength*/,
-                        &msgEos /*pMsg*/,
-                        sizeof(XAuint32)*2 /*msgLength*/);
+        (*caller)->Enqueue(caller, NULL /*pBufferContext*/,
+                NULL /*pData*/, 0 /*dataLength*/,
+                &msgEos /*pMsg*/,
+                sizeof(XAuint32)*2 /*msgLength*/);
         reachedEof = 1;
     }
 
@@ -99,6 +148,29 @@ XAresult AndroidBufferQueueCallback(
 }
 
 
+void StreamChangeCallback (XAStreamInformationItf caller,
+        XAuint32 eventId,
+        XAuint32 streamIndex,
+        void * pEventData,
+        void * pContext )
+{
+    if (XA_STREAMCBEVENT_PROPERTYCHANGE == eventId) {
+        LOGD("StreamChangeCallback called for stream %lu", streamIndex);
+
+        XAuint32 domain;
+        if (XA_RESULT_SUCCESS == (*caller)->QueryStreamType(caller, streamIndex, &domain)) {
+            if (XA_DOMAINTYPE_VIDEO == domain) {
+                XAVideoStreamInformation videoInfo;
+                if (XA_RESULT_SUCCESS == (*caller)->QueryStreamInformation(caller, streamIndex,
+                        &videoInfo)) {
+                    LOGI("Found video size %lu x %lu", videoInfo.width, videoInfo.height);
+                }
+            }
+        }
+    }
+}
+
+
 // create the engine and output mix objects
 void Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz)
 {
@@ -170,8 +242,11 @@ jboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNI
     XADataSink imageVideoSink = {&loc_nd, NULL};
 
     // declare interfaces to use
-    XAboolean     required[NB_MAXAL_INTERFACES] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE};
-    XAInterfaceID iidArray[NB_MAXAL_INTERFACES] = {XA_IID_PLAY,     XA_IID_ANDROIDBUFFERQUEUE};
+    XAboolean     required[NB_MAXAL_INTERFACES]
+                           = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE,           XA_BOOLEAN_TRUE};
+    XAInterfaceID iidArray[NB_MAXAL_INTERFACES]
+                           = {XA_IID_PLAY,     XA_IID_ANDROIDBUFFERQUEUE, XA_IID_STREAMINFORMATION};
+
 
     // create media player
     res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc,
@@ -192,12 +267,25 @@ jboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNI
     res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf);
     assert(XA_RESULT_SUCCESS == res);
 
+    // get the stream information interface (for video size)
+    res = (*playerObj)->GetInterface(playerObj, XA_IID_STREAMINFORMATION, &playerStreamInfoItf);
+    assert(XA_RESULT_SUCCESS == res);
+
+    // get the volume interface
+    res = (*playerObj)->GetInterface(playerObj, XA_IID_VOLUME, &playerVolItf);
+    assert(XA_RESULT_SUCCESS == res);
+
     // get the Android buffer queue interface
     res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf);
     assert(XA_RESULT_SUCCESS == res);
 
     // register the callback from which OpenMAX AL can retrieve the data to play
     res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, NULL);
+    assert(XA_RESULT_SUCCESS == res);
+
+    // we want to be notified of the video size once it's found, so we register a callback for that
+    res = (*playerStreamInfoItf)->RegisterStreamChangeCallback(playerStreamInfoItf,
+            StreamChangeCallback, NULL);
 
     /* Fill our cache */
     if (fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file) <= 0) {
@@ -208,15 +296,20 @@ jboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNI
        we don't want to starve the player */
     int i;
     for (i=0 ; i < NB_BUFFERS ; i++) {
-        res = (*playerBQItf)->Enqueue(playerBQItf, dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0);
+        res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/,
+                dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0);
         assert(XA_RESULT_SUCCESS == res);
     }
 
-
     // prepare the player
     res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED);
     assert(XA_RESULT_SUCCESS == res);
 
+    // set the volume
+    res = (*playerVolItf)->SetVolumeLevel(playerVolItf, 0);//-300);
+    assert(XA_RESULT_SUCCESS == res);
+
+    // start the playback
     res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING);
         assert(XA_RESULT_SUCCESS == res);
 
index ed0a538..9d58606 100644 (file)
@@ -32,7 +32,8 @@
 
 #define NB_BUFFERS 16
 #define MPEG2_TS_BLOCK_SIZE 188
-#define BUFFER_SIZE 20*MPEG2_TS_BLOCK_SIZE
+#define BUFFER_SIZE (20*MPEG2_TS_BLOCK_SIZE)
+#define DISCONTINUITY_MAGIC 1977
 
 /* Where we store the data to play */
 char dataCache[BUFFER_SIZE * NB_BUFFERS];
@@ -40,6 +41,8 @@ char dataCache[BUFFER_SIZE * NB_BUFFERS];
 FILE *file;
 /* Has the app reached the end of the file */
 bool reachedEof = false;
+/* Special discontinuity buffer context */
+int myDiscBufferContext = DISCONTINUITY_MAGIC;
 
 //-----------------------------------------------------------------
 //* Exits the application if an error is encountered */
@@ -59,12 +62,13 @@ bool prefetchError = false;
 /* AndroidBufferQueueItf callback for an audio player */
 SLresult AndroidBufferQueueCallback(
         SLAndroidBufferQueueItf caller,
-        void *pContext,                /* input */
-        const void *pBufferData,       /* input */
-        SLuint32 dataSize,             /* input */
-        SLuint32 dataUsed,             /* input */
-        const SLAndroidBufferItem *pItems,/* input */
-        SLuint32 itemsLength           /* input */)
+        void *pCallbackContext,            /* input */
+        void *pBufferContext,              /* input */
+        void *pBufferData,                 /* input */
+        SLuint32 dataSize,                 /* input */
+        SLuint32 dataUsed,                 /* input */
+        const SLAndroidBufferItem *pItems, /* input */
+        SLuint32 itemsLength               /* input */)
 {
     // assert(BUFFER_SIZE <= dataSize);
 
@@ -85,7 +89,8 @@ SLresult AndroidBufferQueueCallback(
         msgDiscontinuity.itemSize = 0;
         // message has no parameters, so the total size of the message is the size of the key
         //   plus the size if itemSize, both SLuint32
-        (*caller)->Enqueue(caller, NULL /*pData*/, 0 /*dataLength*/,
+        (*caller)->Enqueue(caller, (void*)&myDiscBufferContext /*pBufferContext*/,
+                NULL /*pData*/, 0 /*dataLength*/,
                 &msgDiscontinuity /*pMsg*/,
                 sizeof(SLuint32)*2 /*msgLength*/);
 
@@ -93,7 +98,8 @@ SLresult AndroidBufferQueueCallback(
         size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE*(NB_BUFFERS/2), file);
         if (nbRead == BUFFER_SIZE*(NB_BUFFERS/2)) {
             for (int i=0 ; i < NB_BUFFERS/2 ; i++) {
-                SLresult res = (*caller)->Enqueue(caller, dataCache + i*BUFFER_SIZE,
+                SLresult res = (*caller)->Enqueue(caller,  NULL /*pBufferContext*/,
+                        dataCache + i*BUFFER_SIZE,
                         BUFFER_SIZE, NULL, 0);
                 CheckErr(res);
             }
@@ -107,10 +113,13 @@ SLresult AndroidBufferQueueCallback(
 
         // pBufferData can be null if the last consumed buffer contained only a command
         // just like we do for signalling DISCONTINUITY (above) or EOS (below)
+        if ((pBufferContext != NULL) && (*((int*)pBufferContext) == DISCONTINUITY_MAGIC)) {
+            fprintf(stdout, "Successfully detected my discontinuity buffer having been consumed\n");
+        }
         if (pBufferData != NULL) {
             size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE, file);
             if (nbRead > 0) {
-                (*caller)->Enqueue(caller,
+                (*caller)->Enqueue(caller, NULL /*pBufferContext*/,
                         pBufferData /*pData*/,
                         nbRead /*dataLength*/,
                         NULL /*pMsg*/,
@@ -122,7 +131,8 @@ SLresult AndroidBufferQueueCallback(
                 msgEos.itemSize = 0;
                 // EOS message has no parameters, so the total size of the message is the size of the key
                 //   plus the size if itemSize, both SLuint32
-                (*caller)->Enqueue(caller, NULL /*pData*/, 0 /*dataLength*/,
+                (*caller)->Enqueue(caller,  NULL /*pBufferContext*/,
+                        NULL /*pData*/, 0 /*dataLength*/,
                         &msgEos /*pMsg*/,
                         sizeof(SLuint32)*2 /*msgLength*/);
                 reachedEof = true;
@@ -258,7 +268,8 @@ void TestPlayStream( SLObjectItf sl, const char* path)
     /* Enqueue the content of our cache before starting to play,
          * we don't want to starve the player */
     for (int i=0 ; i < NB_BUFFERS ; i++) {
-        res = (*abqItf)->Enqueue(abqItf, dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0);
+        res = (*abqItf)->Enqueue(abqItf,  NULL /*pBufferContext*/,
+                dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0);
         CheckErr(res);
     }
 
index 3f17ec3..b9db863 100644 (file)
@@ -1,6 +1,6 @@
 all : IID_to_MPH.c
 
-install :
+install : IID_to_MPH.c
        cp IID_to_MPH.c ../../src/autogen
 
 CFLAGS = -I../../include -g -DNDEBUG
@@ -32,7 +32,7 @@ part5.c : part5gen
 
 part7.c : part23in.c hash.sed
 # was 55p
-       sed -n '/return asso_values/p' < part23in.c | sed -f hash.sed >> $@
+       sed -n '/return.*asso_values/p' < part23in.c | sed -f hash.sed >> $@
 
 # part8.c is human_generated
 
index e639143..be40d9f 100644 (file)
@@ -2,3 +2,4 @@
     if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid)
         return iid - &SL_IID_array[0];
     if (NULL != iid) {
+        static const unsigned len = sizeof(struct SLInterfaceID_);