OSDN Git Service

Fix bug 4109988 fix deadlock on destroy
[android-x86/system-media.git] / wilhelm / src / itf / IEngine.c
index 7e86073..9cbf3d4 100644 (file)
@@ -161,8 +161,13 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                     thiz->mpLock = NULL;
                     thiz->mAudioTrack = NULL;
                     // placement new (explicit constructor)
+                    // FIXME unnecessary once those fields are encapsulated in one class, rather
+                    //   than a structure
+                    (void) new (&thiz->mAudioTrackProtector)
+                            android::sp<android::AudioTrackProtector>();
                     (void) new (&thiz->mSfPlayer) android::sp<android::SfPlayer>();
                     (void) new (&thiz->mAuxEffect) android::sp<android::AudioEffect>();
+                    (void) new (&thiz->mAPlayer) android::sp<android::GenericPlayer>();
 #endif
 
                     // Check the source and sink parameters against generic constraints,
@@ -183,7 +188,16 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                     }
 
                     result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink,
-                            DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL);
+                            DATALOCATOR_MASK_OUTPUTMIX                  // for playback
+#ifdef ANDROID
+                            | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE // for decode to a BQ
+                            | DATALOCATOR_MASK_BUFFERQUEUE              // for decode to a BQ
+#endif
+                            , DATAFORMAT_MASK_NULL
+#ifdef ANDROID
+                            | DATAFORMAT_MASK_PCM                       // for decode to PCM
+#endif
+                            );
                     if (SL_RESULT_SUCCESS != result) {
                         break;
                     }
@@ -199,24 +213,47 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                         break;
                     }
 
-                    // copy the buffer queue count from source locator to the buffer queue interface
+                    // copy the buffer queue count from source locator (for playback) / from the
+                    // sink locator (for decode on ANDROID build) to the buffer queue interface
                     // we have already range-checked the value down to a smaller width
-
+                    SLuint16 nbBuffers = 0;
+                    bool usesAdvancedBufferHeaders = false;
                     switch (thiz->mDataSource.mLocator.mLocatorType) {
                     case SL_DATALOCATOR_BUFFERQUEUE:
 #ifdef ANDROID
                     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
 #endif
-                        thiz->mBufferQueue.mNumBuffers =
-                                (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers;
+                        nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers;
                         assert(SL_DATAFORMAT_PCM == thiz->mDataSource.mFormat.mFormatType);
                         thiz->mNumChannels = thiz->mDataSource.mFormat.mPCM.numChannels;
                         thiz->mSampleRateMilliHz = thiz->mDataSource.mFormat.mPCM.samplesPerSec;
                         break;
+#ifdef ANDROID
+                    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
+                        nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
+                        usesAdvancedBufferHeaders = true;
+                        thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
+                        break;
+#endif
                     default:
-                        thiz->mBufferQueue.mNumBuffers = 0;
+                        nbBuffers = 0;
                         break;
                     }
+#ifdef ANDROID
+                    switch(thiz->mDataSink.mLocator.mLocatorType) {
+                    case SL_DATALOCATOR_BUFFERQUEUE:
+                    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
+                        nbBuffers = thiz->mDataSink.mLocator.mBufferQueue.numBuffers;
+                        assert(SL_DATAFORMAT_PCM == thiz->mDataSink.mFormat.mFormatType);
+                        thiz->mNumChannels = thiz->mDataSink.mFormat.mPCM.numChannels;
+                        thiz->mSampleRateMilliHz = thiz->mDataSink.mFormat.mPCM.samplesPerSec;
+                        break;
+                    default:
+                        // leave nbBuffers unchanged
+                        break;
+                    }
+#endif
+                    thiz->mBufferQueue.mNumBuffers = nbBuffers;
 
                     // check the audio source and sink parameters against platform support
 #ifdef ANDROID
@@ -241,8 +278,64 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
 #endif
 
                     // Allocate memory for buffer queue
+                    if (usesAdvancedBufferHeaders) {
+                        // locator is SL_DATALOCATOR_ANDROIDBUFFERQUEUE
+                        // Avoid possible integer overflow during multiplication; this arbitrary
+                        // maximum is big enough to not interfere with real applications, but
+                        // small enough to not overflow.
+                        if (thiz->mAndroidBufferQueue.mNumBuffers >= 256) {
+                            result = SL_RESULT_MEMORY_FAILURE;
+                            break;
+                        }
+                        thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
+                                malloc( (thiz->mAndroidBufferQueue.mNumBuffers + 1)
+                                        * sizeof(AdvancedBufferHeader));
+                        if (NULL == thiz->mAndroidBufferQueue.mBufferArray) {
+                            result = SL_RESULT_MEMORY_FAILURE;
+                            break;
+                        } else {
 
-                    //if (0 != thiz->mBufferQueue.mNumBuffers) {
+                            // initialize ABQ buffer type
+                            // assert below has been checked in android_audioPlayer_checkSourceSink
+                            assert(SL_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType);
+                            if (SL_CONTAINERTYPE_MPEG_TS ==
+                                    thiz->mDataSource.mFormat.mMIME.containerType) {
+                                thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
+                            } else {
+                                thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
+                                SL_LOGE("Invalid buffer type in Android Buffer Queue");
+                                result = SL_RESULT_CONTENT_UNSUPPORTED;
+                            }
+
+                            // initialize ABQ memory
+                            for (SLuint16 i=0 ; i<(thiz->mAndroidBufferQueue.mNumBuffers + 1) ;
+                                    i++) {
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferState =
+                                        SL_ANDROIDBUFFERQUEUEEVENT_NONE;
+                                switch (thiz->mAndroidBufferQueue.mBufferType) {
+                                  case kAndroidBufferTypeMpeg2Ts:
+                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
+                                             mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
+                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
+                                             mPts = 0;
+                                    break;
+                                  default:
+                                    result = SL_RESULT_CONTENT_UNSUPPORTED;
+                                    break;
+                                }
+                            }
+                            thiz->mAndroidBufferQueue.mFront =
+                                    thiz->mAndroidBufferQueue.mBufferArray;
+                            thiz->mAndroidBufferQueue.mRear =
+                                    thiz->mAndroidBufferQueue.mBufferArray;
+                        }
+                    } else {
+                        // locator is SL_DATALOCATOR_BUFFERQUEUE
+                        //         or SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
                         // inline allocation of circular mArray, up to a typical max
                         if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) {
                             thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical;
@@ -255,7 +348,7 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                                 break;
                             }
                             thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue.
-                                mNumBuffers + 1) * sizeof(BufferHeader));
+                                    mNumBuffers + 1) * sizeof(BufferHeader));
                             if (NULL == thiz->mBufferQueue.mArray) {
                                 result = SL_RESULT_MEMORY_FAILURE;
                                 break;
@@ -263,14 +356,14 @@ static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer
                         }
                         thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray;
                         thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray;
-                        //}
+                    }
 
-                        // used to store the data source of our audio player
-                        thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
+                    // used to store the data source of our audio player
+                    thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
 
-                        // platform-specific initialization
+                    // platform-specific initialization
 #ifdef ANDROID
-                        android_audioPlayer_create(thiz);
+                    android_audioPlayer_create(thiz);
 #endif
 
                 } while (0);
@@ -746,7 +839,7 @@ static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
 
 static const char * const extensionNames[] = {
 #ifdef ANDROID
-    "ANDROID_SDK_LEVEL_11", // Android 3.0 aka "Honeycomb"
+    "ANDROID_SDK_LEVEL_12", // Android 3.0+ aka "Honeycomb MR1"
 #else
     "WILHELM_DESKTOP",
 #endif
@@ -962,9 +1055,26 @@ static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer
 
                     // Initialize private fields not associated with an interface
 
+                    // Default data source in case of failure in checkDataSource
+                    thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
+                    thiz->mDataSource.mFormat.mFormatType = XA_DATAFORMAT_NULL;
+
+                    // Default andio and image sink in case of failure in checkDataSink
+                    thiz->mAudioSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
+                    thiz->mAudioSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
+                    thiz->mImageVideoSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
+                    thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
+
+                    // More default values, in case destructor needs to be called early
+                    thiz->mDirectLevel = 0;
+
                     // (assume calloc or memset 0 during allocation)
                     // placement new
-
+#ifdef ANDROID
+                    // FIXME unnecessary once those fields are encapsulated in one class, rather
+                    //   than a structure
+                    (void) new (&thiz->mAVPlayer) android::sp<android::GenericPlayer>();
+#endif
 
                     // Check the source and sink parameters against generic constraints
 
@@ -1022,16 +1132,91 @@ static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer
                     pLEDArray = NULL;
 
                     // Check that the requested interfaces are compatible with the data source
-                    // ...
+                    // FIXME implement
 
                     // check the source and sink parameters against platform support
 #ifdef ANDROID
-                    // result = android_mediaPlayer_checkSourceSink(thiz);
+                    result = android_Player_checkSourceSink(thiz);
                     if (XA_RESULT_SUCCESS != result) {
                         break;
                     }
 #endif
 
+                    // AndroidBufferQueue-specific initialization
+                    if (XA_DATALOCATOR_ANDROIDBUFFERQUEUE ==
+                            thiz->mDataSource.mLocator.mLocatorType) {
+                        XAuint16 nbBuffers = (XAuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
+
+                        // Avoid possible integer overflow during multiplication; this arbitrary
+                        // maximum is big enough to not interfere with real applications, but
+                        // small enough to not overflow.
+                        if (nbBuffers >= 256) {
+                            result = SL_RESULT_MEMORY_FAILURE;
+                            break;
+                        }
+
+                        // initialize ABQ buffer type
+                        // assert below has been checked in android_audioPlayer_checkSourceSink
+                        assert(XA_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType);
+                        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");
+                            result = SL_RESULT_CONTENT_UNSUPPORTED;
+                        }
+
+                        // initialize ABQ memory
+                        thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
+                                    malloc( (nbBuffers + 1) * sizeof(AdvancedBufferHeader));
+                        if (NULL == thiz->mAndroidBufferQueue.mBufferArray) {
+                            result = SL_RESULT_MEMORY_FAILURE;
+                            break;
+                        } else {
+                            for (XAuint16 i=0 ; i<(nbBuffers + 1) ; i++) {
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
+                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferState =
+                                        XA_ANDROIDBUFFERQUEUEEVENT_NONE;
+                                switch (thiz->mAndroidBufferQueue.mBufferType) {
+                                  case kAndroidBufferTypeMpeg2Ts:
+                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
+                                            mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
+                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
+                                            mPts = 0;
+                                    break;
+                                  default:
+                                    result = SL_RESULT_CONTENT_UNSUPPORTED;
+                                    break;
+                                }
+                            }
+                            thiz->mAndroidBufferQueue.mFront =
+                                    thiz->mAndroidBufferQueue.mBufferArray;
+                            thiz->mAndroidBufferQueue.mRear =
+                                    thiz->mAndroidBufferQueue.mBufferArray;
+                        }
+
+                        thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
+
+                    }
+
+                    // used to store the data source of our audio player
+                    thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
+
                     // platform-specific initialization
 #ifdef ANDROID
                     android_Player_create(thiz);