status_t PlayerDriver::enqueueCommand(PlayerCommand* ec) { if (mPlayer == NULL) { delete ec; return NO_INIT; } OsclSemaphore *syncsemcopy = NULL; // If the user didn't specify a completion callback, we // are running in synchronous mode. if (ec->hasCompletionHook()) { ec->set(PlayerDriver::syncCompletion, this); // make a copy of this semaphore for special handling of the PLAYER_QUIT command syncsemcopy = mSyncSem; } // Add the command to the queue. mQueueLock.lock(); mCommandQueue.push_front(ec); // save command, since ec will be deleted by the standard completion function int command = ec->command(); // AO needs to be scheduled only if this is the first cmd after queue was empty if (mCommandQueue.size() == 1) { PendComplete(OSCL_REQUEST_ERR_NONE); } mQueueLock.unlock(); // If we are in synchronous mode, wait for completion. if (syncsemcopy) { syncsemcopy->Wait(); if (command == PlayerCommand::PLAYER_QUIT) { syncsemcopy->Close(); delete syncsemcopy; return 0; } return mSyncStatus; } return OK; }
status_t AuthorDriver::enqueueCommand(author_command *ac, media_completion_f comp, void *cookie) { if (mAuthor == NULL) { return NO_INIT; } // If the user didn't specify a completion callback, we // are running in synchronous mode. if (comp == NULL) { ac->comp = AuthorDriver::syncCompletion; ac->cookie = this; } else { ac->comp = comp; ac->cookie = cookie; } // Add the command to the queue. mQueueLock.lock(); mCommandQueue.push_front(ac); // make a copy of this semaphore for special handling of the AUTHOR_QUIT command OsclSemaphore *syncsemcopy = mSyncSem; // make a copy of ac->which, since ac will be deleted by the standard completion function author_command_type whichcopy = ac->which; // Wake up the author thread so it can dequeue the command. if (mCommandQueue.size() == 1) { PendComplete(OSCL_REQUEST_ERR_NONE); } mQueueLock.unlock(); // If we are in synchronous mode, wait for completion. if (syncsemcopy) { syncsemcopy->Wait(); if (whichcopy == AUTHOR_QUIT) { syncsemcopy->Close(); delete syncsemcopy; return 0; } return mSyncStatus; } return OK; }
int PlayerDriver::playerThread() { int error; LOGV("InitializeForThread"); if(!InitializeForThread()) { LOGV("InitializeForThread fail"); mPlayer = NULL; mSyncSem->Signal(); return -1; } LOGV("OMX_Init"); PV_MasterOMX_Init(); LOGV("OsclScheduler::Init"); OsclScheduler::Init("AndroidPVWrapper"); LOGV("CreatePlayer"); OSCL_TRY(error, mPlayer = PVPlayerFactory::CreatePlayer(this, this, this)); if (error) { // Just crash the first time someone tries to use it for now? mPlayer = NULL; mSyncSem->Signal(); return -1; } LOGV("AddToScheduler"); AddToScheduler(); LOGV("PendForExec"); PendForExec(); LOGV("OsclActiveScheduler::Current"); OsclExecScheduler *sched = OsclExecScheduler::Current(); LOGV("StartScheduler"); sched->StartScheduler(mSyncSem); LOGV("DeletePlayer"); PVPlayerFactory::DeletePlayer(mPlayer); delete mDownloadContextData; mDownloadContextData = NULL; delete mDataSource; mDataSource = NULL; delete mAudioSink; PVMediaOutputNodeFactory::DeleteMediaOutputNode(mAudioNode); delete mAudioOutputMIO; delete mVideoSink; if (mVideoNode) { PVMediaOutputNodeFactory::DeleteMediaOutputNode(mVideoNode); delete mVideoOutputMIO; } mSyncStatus = OK; mSyncSem->Signal(); // note that we only signal mSyncSem. Deleting it is handled // in enqueueCommand(). This is done because waiting for an // already-deleted OsclSemaphore doesn't work (it blocks), // and it's entirely possible for this thread to exit before // enqueueCommand() gets around to waiting for the semaphore. // do some of destructor's work here // goodbye cruel world delete this; //Moved after the delete this, as Oscl cleanup should be done in the end. //delete this was cleaning up OsclSemaphore objects, eventually causing a crash OsclScheduler::Cleanup(); LOGV("OsclScheduler::Cleanup"); PV_MasterOMX_Deinit(); UninitializeForThread(); return 0; }