MediaPlayer_to_android.cpp revision b05ea38e5131001884aa226f90fd50cf594a23f3
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "sles_allinclusive.h" 18#include "utils/RefBase.h" 19#include "android_prompts.h" 20// LocAVPlayer and StreamPlayer derive from GenericMediaPlayer, 21// so no need to #include "android_GenericMediaPlayer.h" 22#include "android_LocAVPlayer.h" 23#include "android_StreamPlayer.h" 24 25 26//----------------------------------------------------------------------------- 27static void player_handleMediaPlayerEventNotifications(int event, int data1, int data2, void* user) 28{ 29 if (NULL == user) { 30 return; 31 } 32 33 CMediaPlayer* mp = (CMediaPlayer*) user; 34 //SL_LOGV("received event %d, data %d from AVPlayer", event, data1); 35 36 switch(event) { 37 38 case android::GenericPlayer::kEventPrepared: { 39 if (PLAYER_SUCCESS == data1) { 40 object_lock_exclusive(&mp->mObject); 41 SL_LOGV("Received AVPlayer::kEventPrepared from AVPlayer for CMediaPlayer %p", mp); 42 mp->mAndroidObjState = ANDROID_READY; 43 object_unlock_exclusive(&mp->mObject); 44 } 45 break; 46 } 47 48 case android::GenericPlayer::kEventHasVideoSize: { 49 SL_LOGV("Received AVPlayer::kEventHasVideoSize (%d,%d) for CMediaPlayer %p", 50 data1, data2, mp); 51 52 object_lock_exclusive(&mp->mObject); 53 54 // remove an existing video info entry (here we only have one video stream) 55 for(size_t i=0 ; i < mp->mStreamInfo.mStreamInfoTable.size() ; i++) { 56 if (XA_DOMAINTYPE_VIDEO == mp->mStreamInfo.mStreamInfoTable.itemAt(i).domain) { 57 mp->mStreamInfo.mStreamInfoTable.removeAt(i); 58 break; 59 } 60 } 61 // update the stream information with a new video info entry 62 StreamInfo streamInfo; 63 streamInfo.domain = XA_DOMAINTYPE_VIDEO; 64 streamInfo.videoInfo.codecId = 0;// unknown, we don't have that info FIXME 65 streamInfo.videoInfo.width = (XAuint32)data1; 66 streamInfo.videoInfo.height = (XAuint32)data2; 67 streamInfo.videoInfo.bitRate = 0;// unknown, we don't have that info FIXME 68 streamInfo.videoInfo.duration = XA_TIME_UNKNOWN; 69 StreamInfo &contInfo = mp->mStreamInfo.mStreamInfoTable.editItemAt(0); 70 contInfo.containerInfo.numStreams = 1; 71 ssize_t index = mp->mStreamInfo.mStreamInfoTable.add(streamInfo); 72 73 xaStreamEventChangeCallback callback = mp->mStreamInfo.mCallback; 74 void* callbackPContext = mp->mStreamInfo.mContext; 75 76 object_unlock_exclusive(&mp->mObject); 77 78 // notify (outside of lock) that the stream information has been updated 79 if ((NULL != callback) && (index >= 0)) { 80 (*callback)(&mp->mStreamInfo.mItf, XA_STREAMCBEVENT_PROPERTYCHANGE /*eventId*/, 81 1 /*streamIndex, only one stream supported here, 0 is reserved*/, 82 NULL /*pEventData, always NULL in OpenMAX AL 1.0.1*/, 83 callbackPContext /*pContext*/); 84 } 85 break; 86 } 87 88 default: 89 SL_LOGE("Received unknown event %d, data %d from AVPlayer", event, data1); 90 break; 91 } 92} 93 94 95//----------------------------------------------------------------------------- 96XAresult android_Player_checkSourceSink(CMediaPlayer *mp) { 97 98 XAresult result = XA_RESULT_SUCCESS; 99 100 const SLDataSource *pSrc = &mp->mDataSource.u.mSource; 101 const SLDataSink *pAudioSnk = &mp->mAudioSink.u.mSink; 102 103 // format check: 104 const SLuint32 sourceLocatorType = *(SLuint32 *)pSrc->pLocator; 105 const SLuint32 sourceFormatType = *(SLuint32 *)pSrc->pFormat; 106 const SLuint32 audioSinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator; 107 //const SLuint32 sinkFormatType = *(SLuint32 *)pAudioSnk->pFormat; 108 109 // Source check 110 switch(sourceLocatorType) { 111 112 case XA_DATALOCATOR_ANDROIDBUFFERQUEUE: { 113 switch (sourceFormatType) { 114 case XA_DATAFORMAT_MIME: { 115 SLDataFormat_MIME *df_mime = (SLDataFormat_MIME *) pSrc->pFormat; 116 if (SL_CONTAINERTYPE_MPEG_TS != df_mime->containerType) { 117 SL_LOGE("Cannot create player with XA_DATALOCATOR_ANDROIDBUFFERQUEUE data source " 118 "that is not fed MPEG-2 TS data"); 119 return SL_RESULT_CONTENT_UNSUPPORTED; 120 } 121 } break; 122 default: 123 SL_LOGE("Cannot create player with XA_DATALOCATOR_ANDROIDBUFFERQUEUE data source " 124 "without SL_DATAFORMAT_MIME format"); 125 return XA_RESULT_CONTENT_UNSUPPORTED; 126 } 127 } break; 128 129 case XA_DATALOCATOR_URI: // intended fall-through 130 case XA_DATALOCATOR_ANDROIDFD: 131 break; 132 133 default: 134 SL_LOGE("Cannot create media player with data locator type 0x%x", 135 (unsigned) sourceLocatorType); 136 return SL_RESULT_PARAMETER_INVALID; 137 }// switch (locatorType) 138 139 // Audio sink check: only playback is supported here 140 switch(audioSinkLocatorType) { 141 142 case XA_DATALOCATOR_OUTPUTMIX: 143 break; 144 145 default: 146 SL_LOGE("Cannot create media player with audio sink data locator of type 0x%x", 147 (unsigned) audioSinkLocatorType); 148 return XA_RESULT_PARAMETER_INVALID; 149 }// switch (locaaudioSinkLocatorTypeorType) 150 151 return result; 152} 153 154 155//----------------------------------------------------------------------------- 156XAresult android_Player_create(CMediaPlayer *mp) { 157 158 XAresult result = XA_RESULT_SUCCESS; 159 160 // FIXME verify data source 161 const SLDataSource *pDataSrc = &mp->mDataSource.u.mSource; 162 // FIXME verify audio data sink 163 const SLDataSink *pAudioSnk = &mp->mAudioSink.u.mSink; 164 // FIXME verify image data sink 165 const SLDataSink *pVideoSnk = &mp->mImageVideoSink.u.mSink; 166 167 XAuint32 sourceLocator = *(XAuint32 *)pDataSrc->pLocator; 168 switch(sourceLocator) { 169 // FIXME support Android simple buffer queue as well 170 case XA_DATALOCATOR_ANDROIDBUFFERQUEUE: 171 mp->mAndroidObjType = AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE; 172 break; 173 case XA_DATALOCATOR_URI: // intended fall-through 174 case SL_DATALOCATOR_ANDROIDFD: 175 mp->mAndroidObjType = AUDIOVIDEOPLAYER_FROM_URIFD; 176 break; 177 case XA_DATALOCATOR_ADDRESS: // intended fall-through 178 default: 179 SL_LOGE("Unable to create MediaPlayer for data source locator 0x%lx", sourceLocator); 180 result = XA_RESULT_PARAMETER_INVALID; 181 break; 182 } 183 184 mp->mAndroidObjState = ANDROID_UNINITIALIZED; 185 mp->mStreamType = ANDROID_DEFAULT_OUTPUT_STREAM_TYPE; 186 mp->mSessionId = android::AudioSystem::newAudioSessionId(); 187 188 mp->mDirectLevel = 0; // no attenuation 189 190 return result; 191} 192 193 194//----------------------------------------------------------------------------- 195// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer 196XAresult android_Player_realize(CMediaPlayer *mp, SLboolean async) { 197 SL_LOGI("android_Player_realize_l(%p)", mp); 198 XAresult result = XA_RESULT_SUCCESS; 199 200 const SLDataSource *pDataSrc = &mp->mDataSource.u.mSource; 201 const SLuint32 sourceLocator = *(SLuint32 *)pDataSrc->pLocator; 202 203 AudioPlayback_Parameters ap_params; 204 ap_params.sessionId = mp->mSessionId; 205 ap_params.streamType = mp->mStreamType; 206 ap_params.trackcb = NULL; 207 ap_params.trackcbUser = NULL; 208 209 switch(mp->mAndroidObjType) { 210 case AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE: { 211 mp->mAVPlayer = new android::StreamPlayer(&ap_params, true /*hasVideo*/); 212 mp->mAVPlayer->init(player_handleMediaPlayerEventNotifications, (void*)mp); 213 } 214 break; 215 case AUDIOVIDEOPLAYER_FROM_URIFD: { 216 mp->mAVPlayer = new android::LocAVPlayer(&ap_params, true /*hasVideo*/); 217 mp->mAVPlayer->init(player_handleMediaPlayerEventNotifications, (void*)mp); 218 switch (mp->mDataSource.mLocator.mLocatorType) { 219 case XA_DATALOCATOR_URI: 220 ((android::LocAVPlayer*)mp->mAVPlayer.get())->setDataSource( 221 (const char*)mp->mDataSource.mLocator.mURI.URI); 222 break; 223 case XA_DATALOCATOR_ANDROIDFD: { 224 int64_t offset = (int64_t)mp->mDataSource.mLocator.mFD.offset; 225 ((android::LocAVPlayer*)mp->mAVPlayer.get())->setDataSource( 226 (int)mp->mDataSource.mLocator.mFD.fd, 227 offset == SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE ? 228 (int64_t)PLAYER_FD_FIND_FILE_SIZE : offset, 229 (int64_t)mp->mDataSource.mLocator.mFD.length); 230 } 231 break; 232 default: 233 SL_LOGE("Invalid or unsupported data locator type %lu for data source", 234 mp->mDataSource.mLocator.mLocatorType); 235 result = XA_RESULT_PARAMETER_INVALID; 236 } 237 } 238 break; 239 case INVALID_TYPE: // intended fall-through 240 default: 241 SL_LOGE("Unable to realize MediaPlayer, invalid internal Android object type"); 242 result = XA_RESULT_PARAMETER_INVALID; 243 break; 244 } 245 246 return result; 247} 248 249//----------------------------------------------------------------------------- 250XAresult android_Player_destroy(CMediaPlayer *mp) { 251 SL_LOGI("android_Player_destroy(%p)", mp); 252 XAresult result = XA_RESULT_SUCCESS; 253 254 if (mp->mAVPlayer != 0) { 255 mp->mAVPlayer.clear(); 256 } 257 258 return result; 259} 260 261//----------------------------------------------------------------------------- 262/** 263 * pre-conditions: gp != 0, surface != 0 264 */ 265XAresult android_Player_setVideoSurface(const android::sp<android::GenericPlayer> &gp, 266 const android::sp<android::Surface> &surface) { 267 XAresult result = XA_RESULT_SUCCESS; 268 269 android::GenericMediaPlayer* gmp = static_cast<android::GenericMediaPlayer*>(gp.get()); 270 gmp->setVideoSurface(surface); 271 272 return result; 273} 274 275 276/** 277 * pre-conditions: gp != 0, surfaceTexture != 0 278 */ 279XAresult android_Player_setVideoSurfaceTexture(const android::sp<android::GenericPlayer> &gp, 280 const android::sp<android::ISurfaceTexture> &surfaceTexture) { 281 XAresult result = XA_RESULT_SUCCESS; 282 283 android::GenericMediaPlayer* gmp = static_cast<android::GenericMediaPlayer*>(gp.get()); 284 gmp->setVideoSurfaceTexture(surfaceTexture); 285 286 return result; 287} 288 289 290XAresult android_Player_getDuration(IPlay *pPlayItf, XAmillisecond *pDurMsec) { 291 XAresult result = XA_RESULT_SUCCESS; 292 CMediaPlayer *avp = (CMediaPlayer *)pPlayItf->mThis; 293 294 switch (avp->mAndroidObjType) { 295 296 case AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE: // intended fall-through 297 case AUDIOVIDEOPLAYER_FROM_URIFD: { 298 // FIXME implement for a MediaPlayer playing on URI or FD (on LocAVPlayer, returns -1) 299 int dur = -1; 300 if (avp->mAVPlayer != 0) { 301 avp->mAVPlayer->getDurationMsec(&dur); 302 } 303 if (dur < 0) { 304 *pDurMsec = SL_TIME_UNKNOWN; 305 } else { 306 *pDurMsec = (XAmillisecond)dur; 307 } 308 } break; 309 310 default: 311 *pDurMsec = XA_TIME_UNKNOWN; 312 break; 313 } 314 315 return result; 316} 317 318 319//----------------------------------------------------------------------------- 320/** 321 * pre-condition: avp != NULL, pVolItf != NULL 322 */ 323XAresult android_Player_volumeUpdate(android::GenericPlayer *avp, IVolume *pVolItf) 324{ 325 XAresult result = XA_RESULT_SUCCESS; 326 327 avp->setVolume((bool)pVolItf->mMute, (bool)pVolItf->mEnableStereoPosition, 328 pVolItf->mStereoPosition, pVolItf->mLevel); 329 330 return result; 331} 332 333//----------------------------------------------------------------------------- 334/** 335 * pre-condition: avp != NULL 336 */ 337XAresult android_Player_setPlayState(android::GenericPlayer *avp, SLuint32 playState, 338 AndroidObjectState* pObjState) 339{ 340 XAresult result = XA_RESULT_SUCCESS; 341 AndroidObjectState objState = *pObjState; 342 343 switch (playState) { 344 case SL_PLAYSTATE_STOPPED: { 345 SL_LOGV("setting AVPlayer to SL_PLAYSTATE_STOPPED"); 346 avp->stop(); 347 } 348 break; 349 case SL_PLAYSTATE_PAUSED: { 350 SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PAUSED"); 351 switch(objState) { 352 case ANDROID_UNINITIALIZED: 353 *pObjState = ANDROID_PREPARING; 354 avp->prepare(); 355 break; 356 case ANDROID_PREPARING: 357 break; 358 case ANDROID_READY: 359 avp->pause(); 360 break; 361 default: 362 SL_LOGE("Android object in invalid state"); 363 break; 364 } 365 } 366 break; 367 case SL_PLAYSTATE_PLAYING: { 368 SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PLAYING"); 369 switch(objState) { 370 case ANDROID_UNINITIALIZED: 371 *pObjState = ANDROID_PREPARING; 372 avp->prepare(); 373 // intended fall through 374 case ANDROID_PREPARING: 375 // intended fall through 376 case ANDROID_READY: 377 avp->play(); 378 break; 379 default: 380 SL_LOGE("Android object in invalid state"); 381 break; 382 } 383 } 384 break; 385 default: 386 // checked by caller, should not happen 387 break; 388 } 389 390 return result; 391} 392 393 394//----------------------------------------------------------------------------- 395void android_Player_androidBufferQueue_registerCallback_l(CMediaPlayer *mp) { 396 if ((mp->mAndroidObjType == AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE) 397 && (mp->mAVPlayer != 0)) { 398 SL_LOGD("android_Player_androidBufferQueue_registerCallback_l"); 399 android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(mp->mAVPlayer.get()); 400 splr->registerQueueCallback( 401 (const void*)mp, false /*userIsAudioPlayer*/, 402 mp->mAndroidBufferQueue.mContext, (const void*)&(mp->mAndroidBufferQueue.mItf)); 403 404 } 405} 406 407 408void android_Player_androidBufferQueue_clear_l(CMediaPlayer *mp) { 409 if ((mp->mAndroidObjType == AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE) 410 && (mp->mAVPlayer != 0)) { 411 android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(mp->mAVPlayer.get()); 412 splr->appClear_l(); 413 } 414} 415 416 417void android_Player_androidBufferQueue_onRefilled_l(CMediaPlayer *mp) { 418 if ((mp->mAndroidObjType == AUDIOVIDEOPLAYER_FROM_TS_ANDROIDBUFFERQUEUE) 419 && (mp->mAVPlayer != 0)) { 420 android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(mp->mAVPlayer.get()); 421 splr->queueRefilled_l(); 422 } 423} 424 425 426 427