PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/frameworks/wilhelm/src/android/android_StreamPlayer.cpp

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
C++ | 420 lines | 275 code | 59 blank | 86 comment | 54 complexity | 02709d8682f5d7229bb75e09fff0f653 MD5 | raw file
  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. //#define USE_LOG SLAndroidLogLevel_Verbose
  17. #include "sles_allinclusive.h"
  18. #include "android_StreamPlayer.h"
  19. #include <media/IStreamSource.h>
  20. #include <media/IMediaPlayerService.h>
  21. #include <media/stagefright/foundation/ADebug.h>
  22. #include <binder/IPCThreadState.h>
  23. #include "mpeg2ts/ATSParser.h"
  24. //--------------------------------------------------------------------------------------------------
  25. namespace android {
  26. StreamSourceAppProxy::StreamSourceAppProxy(
  27. IAndroidBufferQueue *androidBufferQueue,
  28. const sp<CallbackProtector> &callbackProtector,
  29. // sp<StreamPlayer> would cause StreamPlayer's destructor to run during it's own
  30. // construction. If you pass in a sp<> to 'this' inside a constructor, then first the
  31. // refcount is increased from 0 to 1, then decreased from 1 to 0, which causes the object's
  32. // destructor to run from inside it's own constructor.
  33. StreamPlayer * /* const sp<StreamPlayer> & */ player) :
  34. mBuffersHasBeenSet(false),
  35. mAndroidBufferQueue(androidBufferQueue),
  36. mCallbackProtector(callbackProtector),
  37. mPlayer(player)
  38. {
  39. SL_LOGV("StreamSourceAppProxy::StreamSourceAppProxy()");
  40. }
  41. StreamSourceAppProxy::~StreamSourceAppProxy() {
  42. SL_LOGV("StreamSourceAppProxy::~StreamSourceAppProxy()");
  43. disconnect();
  44. }
  45. const SLuint32 StreamSourceAppProxy::kItemProcessed[NB_BUFFEREVENT_ITEM_FIELDS] = {
  46. SL_ANDROID_ITEMKEY_BUFFERQUEUEEVENT, // item key
  47. sizeof(SLuint32), // item size
  48. SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED // item data
  49. };
  50. //--------------------------------------------------
  51. // IStreamSource implementation
  52. void StreamSourceAppProxy::setListener(const sp<IStreamListener> &listener) {
  53. assert(listener != NULL);
  54. Mutex::Autolock _l(mLock);
  55. assert(mListener == NULL);
  56. mListener = listener;
  57. }
  58. void StreamSourceAppProxy::setBuffers(const Vector<sp<IMemory> > &buffers) {
  59. Mutex::Autolock _l(mLock);
  60. assert(!mBuffersHasBeenSet);
  61. mBuffers = buffers;
  62. mBuffersHasBeenSet = true;
  63. }
  64. void StreamSourceAppProxy::onBufferAvailable(size_t index) {
  65. //SL_LOGD("StreamSourceAppProxy::onBufferAvailable(%d)", index);
  66. {
  67. Mutex::Autolock _l(mLock);
  68. if (!mBuffersHasBeenSet) {
  69. // no buffers available to push data to from the buffer queue, bail
  70. return;
  71. }
  72. CHECK_LT(index, mBuffers.size());
  73. #if 0 // enable if needed for debugging
  74. sp<IMemory> mem = mBuffers.itemAt(index);
  75. SLAint64 length = (SLAint64) mem->size();
  76. #endif
  77. mAvailableBuffers.push_back(index);
  78. //SL_LOGD("onBufferAvailable() now %d buffers available in queue",
  79. // mAvailableBuffers.size());
  80. }
  81. // a new shared mem buffer is available: let's try to fill immediately
  82. pullFromBuffQueue();
  83. }
  84. void StreamSourceAppProxy::receivedCmd_l(IStreamListener::Command cmd, const sp<AMessage> &msg) {
  85. if (mListener != 0) {
  86. mListener->issueCommand(cmd, false /* synchronous */, msg);
  87. }
  88. }
  89. void StreamSourceAppProxy::receivedBuffer_l(size_t buffIndex, size_t buffLength) {
  90. if (mListener != 0) {
  91. mListener->queueBuffer(buffIndex, buffLength);
  92. }
  93. }
  94. void StreamSourceAppProxy::disconnect() {
  95. Mutex::Autolock _l(mLock);
  96. mListener.clear();
  97. // Force binder to push the decremented reference count for sp<IStreamListener>.
  98. // mediaserver and client both have sp<> to the other. When you decrement an sp<>
  99. // reference count, binder doesn't push that to the other process immediately.
  100. IPCThreadState::self()->flushCommands();
  101. mBuffers.clear();
  102. mBuffersHasBeenSet = false;
  103. mAvailableBuffers.clear();
  104. }
  105. //--------------------------------------------------
  106. // consumption from ABQ: pull from the ABQ, and push to shared memory (media server)
  107. void StreamSourceAppProxy::pullFromBuffQueue() {
  108. if (android::CallbackProtector::enterCbIfOk(mCallbackProtector)) {
  109. size_t bufferId;
  110. void* bufferLoc;
  111. size_t buffSize;
  112. slAndroidBufferQueueCallback callback = NULL;
  113. void* pBufferContext, *pBufferData, *callbackPContext = NULL;
  114. AdvancedBufferHeader *oldFront = NULL;
  115. uint32_t dataSize /* , dataUsed */;
  116. // retrieve data from the buffer queue
  117. interface_lock_exclusive(mAndroidBufferQueue);
  118. // can this read operation cause us to call the buffer queue callback
  119. // (either because there was a command with no data, or all the data has been consumed)
  120. bool queueCallbackCandidate = false;
  121. if (mAndroidBufferQueue->mState.count != 0) {
  122. // SL_LOGD("nbBuffers in ABQ = %u, buffSize=%u",abq->mState.count, buffSize);
  123. assert(mAndroidBufferQueue->mFront != mAndroidBufferQueue->mRear);
  124. oldFront = mAndroidBufferQueue->mFront;
  125. AdvancedBufferHeader *newFront = &oldFront[1];
  126. // consume events when starting to read data from a buffer for the first time
  127. if (oldFront->mDataSizeConsumed == 0) {
  128. // note this code assumes at most one event per buffer; see IAndroidBufferQueue_Enqueue
  129. if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_EOS) {
  130. receivedCmd_l(IStreamListener::EOS);
  131. // EOS has no associated data
  132. queueCallbackCandidate = true;
  133. } else if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_DISCONTINUITY) {
  134. receivedCmd_l(IStreamListener::DISCONTINUITY);
  135. } else if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_DISCON_NEWPTS) {
  136. sp<AMessage> msg = new AMessage();
  137. msg->setInt64(IStreamListener::kKeyResumeAtPTS,
  138. (int64_t)oldFront->mItems.mTsCmdData.mPts);
  139. receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
  140. } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
  141. & ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL) {
  142. sp<AMessage> msg = new AMessage();
  143. msg->setInt32(
  144. IStreamListener::kKeyDiscontinuityMask,
  145. ATSParser::DISCONTINUITY_FORMATCHANGE);
  146. receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
  147. } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
  148. & ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO) {
  149. sp<AMessage> msg = new AMessage();
  150. msg->setInt32(
  151. IStreamListener::kKeyDiscontinuityMask,
  152. ATSParser::DISCONTINUITY_VIDEO_FORMAT);
  153. receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
  154. }
  155. // note that here we are intentionally only supporting
  156. // ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO, see IAndroidBufferQueue.c
  157. // some commands may introduce a time discontinuity, reevaluate position if needed
  158. if (oldFront->mItems.mTsCmdData.mTsCmdCode & (ANDROID_MP2TSEVENT_DISCONTINUITY |
  159. ANDROID_MP2TSEVENT_DISCON_NEWPTS | ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL)) {
  160. const sp<StreamPlayer> player(mPlayer.promote());
  161. if (player != NULL) {
  162. // FIXME see note at onSeek
  163. player->seek(ANDROID_UNKNOWN_TIME);
  164. }
  165. }
  166. oldFront->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
  167. }
  168. {
  169. // we're going to change the shared mem buffer queue, so lock it
  170. Mutex::Autolock _l(mLock);
  171. if (!mAvailableBuffers.empty()) {
  172. bufferId = *mAvailableBuffers.begin();
  173. CHECK_LT(bufferId, mBuffers.size());
  174. sp<IMemory> mem = mBuffers.itemAt(bufferId);
  175. bufferLoc = mem->pointer();
  176. buffSize = mem->size();
  177. char *pSrc = ((char*)oldFront->mDataBuffer) + oldFront->mDataSizeConsumed;
  178. if (oldFront->mDataSizeConsumed + buffSize < oldFront->mDataSize) {
  179. // more available than requested, copy as much as requested
  180. // consume data: 1/ copy to given destination
  181. memcpy(bufferLoc, pSrc, buffSize);
  182. // 2/ keep track of how much has been consumed
  183. oldFront->mDataSizeConsumed += buffSize;
  184. // 3/ notify shared mem listener that new data is available
  185. receivedBuffer_l(bufferId, buffSize);
  186. mAvailableBuffers.erase(mAvailableBuffers.begin());
  187. } else {
  188. // requested as much available or more: consume the whole of the current
  189. // buffer and move to the next
  190. size_t consumed = oldFront->mDataSize - oldFront->mDataSizeConsumed;
  191. //SL_LOGD("consuming rest of buffer: enqueueing=%u", consumed);
  192. oldFront->mDataSizeConsumed = oldFront->mDataSize;
  193. // move queue to next
  194. if (newFront == &mAndroidBufferQueue->
  195. mBufferArray[mAndroidBufferQueue->mNumBuffers + 1]) {
  196. // reached the end, circle back
  197. newFront = mAndroidBufferQueue->mBufferArray;
  198. }
  199. mAndroidBufferQueue->mFront = newFront;
  200. mAndroidBufferQueue->mState.count--;
  201. mAndroidBufferQueue->mState.index++;
  202. if (consumed > 0) {
  203. // consume data: 1/ copy to given destination
  204. memcpy(bufferLoc, pSrc, consumed);
  205. // 2/ keep track of how much has been consumed
  206. // here nothing to do because we are done with this buffer
  207. // 3/ notify StreamPlayer that new data is available
  208. receivedBuffer_l(bufferId, consumed);
  209. mAvailableBuffers.erase(mAvailableBuffers.begin());
  210. }
  211. // data has been consumed, and the buffer queue state has been updated
  212. // we will notify the client if applicable
  213. queueCallbackCandidate = true;
  214. }
  215. }
  216. if (queueCallbackCandidate) {
  217. if (mAndroidBufferQueue->mCallbackEventsMask &
  218. SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED) {
  219. callback = mAndroidBufferQueue->mCallback;
  220. // save callback data while under lock
  221. callbackPContext = mAndroidBufferQueue->mContext;
  222. pBufferContext = (void *)oldFront->mBufferContext;
  223. pBufferData = (void *)oldFront->mDataBuffer;
  224. dataSize = oldFront->mDataSize;
  225. // here a buffer is only dequeued when fully consumed
  226. //dataUsed = oldFront->mDataSizeConsumed;
  227. }
  228. }
  229. //SL_LOGD("%d buffers available after reading from queue", mAvailableBuffers.size());
  230. if (!mAvailableBuffers.empty()) {
  231. // there is still room in the shared memory, recheck later if we can pull
  232. // data from the buffer queue and write it to shared memory
  233. const sp<StreamPlayer> player(mPlayer.promote());
  234. if (player != NULL) {
  235. player->queueRefilled();
  236. }
  237. }
  238. }
  239. } else { // empty queue
  240. SL_LOGD("ABQ empty, starving!");
  241. }
  242. interface_unlock_exclusive(mAndroidBufferQueue);
  243. // notify client of buffer processed
  244. if (NULL != callback) {
  245. SLresult result = (*callback)(&mAndroidBufferQueue->mItf, callbackPContext,
  246. pBufferContext, pBufferData, dataSize,
  247. dataSize, /* dataUsed */
  248. // no messages during playback other than marking the buffer as processed
  249. (const SLAndroidBufferItem*)(&kItemProcessed) /* pItems */,
  250. NB_BUFFEREVENT_ITEM_FIELDS *sizeof(SLuint32) /* itemsLength */ );
  251. if (SL_RESULT_SUCCESS != result) {
  252. // Reserved for future use
  253. SL_LOGW("Unsuccessful result %d returned from AndroidBufferQueueCallback", result);
  254. }
  255. }
  256. mCallbackProtector->exitCb();
  257. } // enterCbIfOk
  258. }
  259. //--------------------------------------------------------------------------------------------------
  260. StreamPlayer::StreamPlayer(const AudioPlayback_Parameters* params, bool hasVideo,
  261. IAndroidBufferQueue *androidBufferQueue, const sp<CallbackProtector> &callbackProtector) :
  262. GenericMediaPlayer(params, hasVideo),
  263. mAppProxy(new StreamSourceAppProxy(androidBufferQueue, callbackProtector, this)),
  264. mStopForDestroyCompleted(false)
  265. {
  266. SL_LOGD("StreamPlayer::StreamPlayer()");
  267. }
  268. StreamPlayer::~StreamPlayer() {
  269. SL_LOGD("StreamPlayer::~StreamPlayer()");
  270. mAppProxy->disconnect();
  271. }
  272. void StreamPlayer::onMessageReceived(const sp<AMessage> &msg) {
  273. switch (msg->what()) {
  274. case kWhatPullFromAbq:
  275. onPullFromAndroidBufferQueue();
  276. break;
  277. case kWhatStopForDestroy:
  278. onStopForDestroy();
  279. break;
  280. default:
  281. GenericMediaPlayer::onMessageReceived(msg);
  282. break;
  283. }
  284. }
  285. void StreamPlayer::preDestroy() {
  286. // FIXME NuPlayerDriver is currently not thread-safe, so stop() must be called by looper
  287. (new AMessage(kWhatStopForDestroy, id()))->post();
  288. {
  289. Mutex::Autolock _l(mStopForDestroyLock);
  290. while (!mStopForDestroyCompleted) {
  291. mStopForDestroyCondition.wait(mStopForDestroyLock);
  292. }
  293. }
  294. // GenericMediaPlayer::preDestroy will repeat some of what we've done, but that's benign
  295. GenericMediaPlayer::preDestroy();
  296. }
  297. void StreamPlayer::onStopForDestroy() {
  298. if (mPlayer != 0) {
  299. mPlayer->stop();
  300. // causes CHECK failure in Nuplayer
  301. //mPlayer->setDataSource(NULL);
  302. mPlayer->setVideoSurfaceTexture(NULL);
  303. mPlayer->disconnect();
  304. mPlayer.clear();
  305. {
  306. // FIXME ugh make this a method
  307. Mutex::Autolock _l(mPreparedPlayerLock);
  308. mPreparedPlayer.clear();
  309. }
  310. }
  311. {
  312. Mutex::Autolock _l(mStopForDestroyLock);
  313. mStopForDestroyCompleted = true;
  314. }
  315. mStopForDestroyCondition.signal();
  316. }
  317. /**
  318. * Asynchronously notify the player that the queue is ready to be pulled from.
  319. */
  320. void StreamPlayer::queueRefilled() {
  321. // async notification that the ABQ was refilled: the player should pull from the ABQ, and
  322. // and push to shared memory (to the media server)
  323. (new AMessage(kWhatPullFromAbq, id()))->post();
  324. }
  325. void StreamPlayer::appClear_l() {
  326. // the user of StreamPlayer has cleared its AndroidBufferQueue:
  327. // there's no clear() for the shared memory queue, so this is a no-op
  328. }
  329. //--------------------------------------------------
  330. // Event handlers
  331. void StreamPlayer::onPrepare() {
  332. SL_LOGD("StreamPlayer::onPrepare()");
  333. sp<IMediaPlayerService> mediaPlayerService(getMediaPlayerService());
  334. if (mediaPlayerService != NULL) {
  335. mPlayer = mediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
  336. mPlaybackParams.sessionId);
  337. if (mPlayer == NULL) {
  338. SL_LOGE("media player service failed to create player by app proxy");
  339. } else if (mPlayer->setDataSource(mAppProxy /*IStreamSource*/) != NO_ERROR) {
  340. SL_LOGE("setDataSource failed");
  341. mPlayer.clear();
  342. }
  343. }
  344. if (mPlayer == NULL) {
  345. mStateFlags |= kFlagPreparedUnsuccessfully;
  346. }
  347. GenericMediaPlayer::onPrepare();
  348. SL_LOGD("StreamPlayer::onPrepare() done");
  349. }
  350. void StreamPlayer::onPlay() {
  351. SL_LOGD("StreamPlayer::onPlay()");
  352. // enqueue a message that will cause StreamAppProxy to consume from the queue (again if the
  353. // player had starved the shared memory)
  354. queueRefilled();
  355. GenericMediaPlayer::onPlay();
  356. }
  357. void StreamPlayer::onPullFromAndroidBufferQueue() {
  358. SL_LOGD("StreamPlayer::onPullFromAndroidBufferQueue()");
  359. mAppProxy->pullFromBuffQueue();
  360. }
  361. } // namespace android