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,
}
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;
}
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
#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;
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;
}
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);
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
// 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
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);