/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "EyeseePlayer" #include #include #include #include //#include "jni.h" //#include "JNIHelp.h" //#include "android_runtime/AndroidRuntime.h" #include #include //#include //#include //#include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #define ENABLE_AUDIO_TRACK (1) using namespace std; namespace EyeseeLinux { ERRORTYPE EyeseePlayer::MPPCallbackWrapper(void *cookie, MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData) { ((EyeseePlayer*)cookie)->notify(pChn, event, pEventData); return SUCCESS; } void EyeseePlayer::EventHandler::handleMessage(const CallbackMessage &msg) { switch (msg.what) { case MEDIA_PREPARED: alogv("MEDIA_PREPARED"); if (mPlayer->mOnPreparedListener != NULL) mPlayer->mOnPreparedListener->onPrepared(mPlayer); return; case MEDIA_PLAYBACK_COMPLETE: alogv("MEDIA_PLAYBACK_COMPLETE"); if (mPlayer->mOnCompletionListener != NULL) mPlayer->mOnCompletionListener->onCompletion(mPlayer); return; case MEDIA_SEEK_COMPLETE: alogv("MEDIA_SEEK_COMPLETE"); if (mPlayer->mOnSeekCompleteListener != NULL) mPlayer->mOnSeekCompleteListener->onSeekComplete(mPlayer); return; case MEDIA_SET_VIDEO_SIZE: alogv("MEDIA_SET_VIDEO_SIZE"); if (mPlayer->mOnVideoSizeChangedListener != NULL) mPlayer->mOnVideoSizeChangedListener->onVideoSizeChanged(mPlayer, msg.arg1, msg.arg2); return; case MEDIA_ERROR: { aloge("Error (%d,%d)", msg.arg1, msg.arg2); bool error_was_handled = false; if (mPlayer->mOnErrorListener != NULL) { error_was_handled = mPlayer->mOnErrorListener->onError(mPlayer, msg.arg1, msg.arg2); } if (mPlayer->mOnCompletionListener != NULL && !error_was_handled) { mPlayer->mOnCompletionListener->onCompletion(mPlayer); } //stayAwake(false); return; } case MEDIA_INFO: alogv("MEDIA_INFO"); if (msg.arg1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { alogv("Info (%d,%d)", msg.arg1, msg.arg2); } if (mPlayer->mOnInfoListener != NULL) { mPlayer->mOnInfoListener->onInfo(mPlayer, msg.arg1, msg.arg2); } // No real default action so far. return; case MEDIA_NOP: // interface test message - ignore break; #if 0 case MEDIA_TIMED_TEXT: if (mOnTimedTextListener == NULL) return; if (msg.obj == NULL) { mOnTimedTextListener.onTimedText(mPlayer, NULL); } else { if (msg.obj instanceof Parcel) { Parcel parcel = (Parcel)msg.obj; TimedText text = new TimedText(parcel); parcel.recycle(); mOnTimedTextListener.onTimedText(mPlayer, text); } } return; /*Start by Bevis. Detect http data source from other application.*/ case MEDIA_SOURCE_DETECTED: if (mDlnaSourceDetector != NULL && msg.obj != NULL){ if(msg.obj instanceof Parcel){ Parcel parcel = (Parcel)msg.obj; //parcel.setDataPosition(0); String url = parcel.readString(); Log.d(TAG, "######MEDIA_SOURCE_DETECTED! url = " + url); mDlnaSourceDetector.onSourceDetected(url); } } return; /*End by Bevis. Detect http data source from other application. */ #endif case MEDIA_NOTIFY_EOF: { MOD_ID_E eModId = (MOD_ID_E)msg.arg1; if(MOD_ID_DEMUX == eModId) { Mutex::Autolock autoLock(mPlayer->mNotifyEofLock); if(!mPlayer->mDmxNotifyEof) { alogv("receive demuxer component finish flag."); if(mPlayer->mVdecChn >= 0) { AW_MPI_VDEC_SetStreamEof(mPlayer->mVdecChn, 1); } if(mPlayer->mAdecChn >= 0) { AW_MPI_ADEC_SetStreamEof(mPlayer->mAdecChn, 1); } mPlayer->mDmxNotifyEof = true; } else { aloge("fatal error! dmx already notify eof!"); } } else if(MOD_ID_VDEC == eModId) { Mutex::Autolock autoLock(mPlayer->mNotifyEofLock); if(!mPlayer->mVdecNotifyEof) { alogv("receive vdec component finish flag."); if(mPlayer->mVOChn >= 0) { AW_MPI_VO_SetStreamEof(mPlayer->mVOLayer, mPlayer->mVOChn, 1); } mPlayer->mVdecNotifyEof = true; } else { aloge("fatal error! vdec already notify eof!"); } } else if(MOD_ID_ADEC == eModId) { Mutex::Autolock autoLock(mPlayer->mNotifyEofLock); if(!mPlayer->mAdecNotifyEof) { alogv("receive adec component finish flag."); if(mPlayer->mAOChn >= 0) { AW_MPI_AO_SetStreamEof(mPlayer->mAODev, mPlayer->mAOChn, 1, FALSE); } mPlayer->mAdecNotifyEof = true; } else { aloge("fatal error! adec already notify eof!"); } } else if(MOD_ID_VOU == eModId) { mPlayer->mNotifyEofLock.lock(); if(!mPlayer->mVONotifyEof) { alogv("receive vo component finish flag."); mPlayer->mVONotifyEof = true; mPlayer->mNotifyEofLock.unlock(); if(mPlayer->mAOChn < 0 || mPlayer->mAONotifyEof) { mPlayer->playbackComplete(); if(mPlayer->mLoop) { alogd("loop start!"); mPlayer->start(); } else { if(mPlayer->mOnCompletionListener != NULL) { alogd("notify complete message."); mPlayer->mOnCompletionListener->onCompletion(mPlayer); } } } } else { aloge("fatal error! vo already notify eof!"); mPlayer->mNotifyEofLock.unlock(); } } else if(MOD_ID_AO == eModId) { mPlayer->mNotifyEofLock.lock(); if(!mPlayer->mAONotifyEof) { alogv("receive ao component finish flag."); mPlayer->mAONotifyEof = true; mPlayer->mNotifyEofLock.unlock(); if(mPlayer->mVOChn < 0 || mPlayer->mVONotifyEof) { mPlayer->playbackComplete(); if(mPlayer->mLoop) { alogd("loop start!"); mPlayer->start(); } else { if(mPlayer->mOnCompletionListener != NULL) { alogd("notify complete message."); mPlayer->mOnCompletionListener->onCompletion(mPlayer); } } } } else { aloge("fatal error! ao already notify eof!"); mPlayer->mNotifyEofLock.unlock(); } } else { aloge("fatal error! other modId[0x%x]?", eModId); } break; } default: aloge("Unknown message type %d", msg.what); return; } } EyeseePlayer::EyeseePlayer() { mOnErrorListener = NULL; mOnCompletionListener = NULL; mOnPreparedListener = NULL; mOnSeekCompleteListener = NULL; mOnVideoSizeChangedListener = NULL; mOnTimedTextListener = NULL; mOnInfoListener = NULL; mEventHandler = new EventHandler(this); mCurrentState = MEDIA_PLAYER_IDLE; mbGrantAudio = true; mbSeekStart = false; mLoop = false; mSurfaceHolder = MM_INVALID_LAYER; mCurSubtitleTrackIndex = -1; mTempPosition = 0; mDisplayWidth = 0; mDisplayHeight = 0; mMaxVdecOutputWidth = 0; mMaxVdecOutputHeight = 0; mAOCardId = PCM_CARD_TYPE_AUDIOCODEC; mUserSetPixelFormat = MM_PIXEL_FORMAT_YVU_PLANAR_420; mInitRotation = ROTATE_NONE; mbForceFramePackage = false; mDmxNotifyEof = false; mVdecNotifyEof = false; mAdecNotifyEof = false; mVONotifyEof = false; mAONotifyEof = false; mfVps = 1; mVdecInputBufferSize = 0; int err = pthread_create(&mCommandThreadId, NULL, EyeseeCommandThread, this); if (err || !mCommandThreadId) { aloge("fatal error! create thread fail!"); } mDmxChn = MM_INVALID_CHN; mVdecChn = MM_INVALID_CHN; mVOLayer = MM_INVALID_DEV; mVOChn = MM_INVALID_CHN; mAdecChn = MM_INVALID_DEV; mAODev = MM_INVALID_DEV; mAOChn = MM_INVALID_CHN; mClockChn = MM_INVALID_CHN; } EyeseePlayer::~EyeseePlayer() { reset(); if(mCommandThreadId != 0) { EyeseeMessage cmdMsg; cmdMsg.mMsgType = PLAYER_COMMAND_STOP; mCommandQueue.queueMessage(&cmdMsg); // Wait for thread to exit so we can get the status into "error" void *retValue = NULL; pthread_join(mCommandThreadId, (void**)&retValue); mCommandThreadId = 0; } if(mEventHandler) { delete mEventHandler; mEventHandler = NULL; } } void EyeseePlayer::setDisplay(unsigned int hlay) { Mutex::Autolock _l(mLock); alogv("setDisplay, hlay=%d", hlay); mSurfaceHolder = hlay; } status_t EyeseePlayer::setOutputPixelFormat(PIXEL_FORMAT_E ePixelFormat) { mUserSetPixelFormat = ePixelFormat; return NO_ERROR; } status_t EyeseePlayer::setVideoScalingMode(int mode) { Mutex::Autolock _l(mLock); alogv("setVideoScalingMode, mode=%d", mode); if (!isVideoScalingModeSupported(mode)) { aloge("Scaling mode %d is not supported", mode); return INVALID_OPERATION; } if(mCurrentState==MEDIA_PLAYER_STATE_ERROR || mCurrentState&(MEDIA_PLAYER_IDLE|MEDIA_PLAYER_PREPARING)) { aloge("can't called in state 0x%x", mCurrentState); return INVALID_OPERATION; } if(mVideoScalingMode == mode) { return NO_ERROR; } mVideoScalingMode = mode; if(mCurrentState&(MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) { if(mVOLayer!=MM_INVALID_DEV) { AW_MPI_VO_SetVideoScalingMode(mVOLayer, mVOChn, mode); } else { aloge("fatal error! video layer is not set!"); } } return NO_ERROR; } status_t EyeseePlayer::setDataSource(string path) { alogv("setDataSource, path=%s", path.c_str()); status_t opStatus; if (access(path.c_str(), F_OK) == 0) { int fd = open(path.c_str(), O_RDONLY); if (fd < 0) { aloge("Failed to open file %s(%s)", path.c_str(), strerror(errno)); return UNKNOWN_ERROR; } opStatus = setDataSource(fd); close(fd); } else { aloge("fatal error! open file path[%s] fail!", path.c_str()); opStatus = INVALID_OPERATION; } if (NO_ERROR != opStatus) { if (NULL != mOnErrorListener) mOnErrorListener->onError(this, 0, 0); } return opStatus; } status_t EyeseePlayer::setDataSource(int fd) { return setDataSource(fd, 0, 0x7ffffffffffffffL); } status_t EyeseePlayer::setDataSource(int fd, int64_t offset, int64_t length) { Mutex::Autolock _l(mLock); if(!(mCurrentState&MEDIA_PLAYER_IDLE || mCurrentState==MEDIA_PLAYER_STATE_ERROR)) { aloge("called in wrong state %d", mCurrentState); return INVALID_OPERATION; } int demux_disable_track = 0; //DEMUX_DISABLE_AUDIO_TRACK if(false == mbGrantAudio) { demux_disable_track |= DEMUX_DISABLE_AUDIO_TRACK; } #if (!ENABLE_AUDIO_TRACK) demux_disable_track |= DEMUX_DISABLE_AUDIO_TRACK; #endif ERRORTYPE ret; bool nSuccessFlag = false; //mDmxChnAttr.mStreamType = STREAMTYPE_LOCALFILE; mDmxChnAttr.mSourceType = SOURCETYPE_FD; mDmxChnAttr.mSourceUrl = NULL; mDmxChnAttr.mFd = fd; mDmxChnAttr.mDemuxDisableTrack = demux_disable_track; mDmxChn = 0; while(mDmxChn < DEMUX_MAX_CHN_NUM) { ret = AW_MPI_DEMUX_CreateChn(mDmxChn, &mDmxChnAttr); if(SUCCESS == ret) { nSuccessFlag = TRUE; alogd("create demux channel[%d] success!", mDmxChn); break; } else if(ERR_DEMUX_EXIST == ret) { alogd("demux channel[%d] is exist, find next!", mDmxChn); mDmxChn++; } else if(ERR_DEMUX_FILE_EXCEPTION == ret) { aloge("demux detect media file exception!"); return BAD_FILE; } else { alogd("create demux channel[%d] ret[0x%x]!", mDmxChn, ret); break; } } if(false == nSuccessFlag) { mDmxChn = MM_INVALID_CHN; aloge("fatal error! create demux channel fail!"); return UNKNOWN_ERROR; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_DEMUX_RegisterCallback(mDmxChn, &cbInfo); mCurrentState = MEDIA_PLAYER_INITIALIZED; return NO_ERROR; } /** set variable play speed. support to change vps in playing. @param fVps scope:[0.5, 4] */ status_t EyeseePlayer::setVps(float fVps) { status_t ret = NO_ERROR; Mutex::Autolock autoLock(mLock); if(mCurrentState & (MEDIA_PLAYER_IDLE | MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED)) { mfVps = fVps; } else if(mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE)) { mfVps = fVps; if(mClockChn >= 0) { AW_MPI_CLOCK_SetVps(mClockChn, mfVps); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_SetChnVps(mAODev, mAOChn, mfVps); } } else { aloge("fatal error! wrong state:0x%x", mCurrentState); ret = UNKNOWN_ERROR; } return ret; } float EyeseePlayer::getVps() { Mutex::Autolock autoLock(mLock); return mfVps; } /** set vdec input vbs buffer size to config vdeclib. must be called before prepare(). */ status_t EyeseePlayer::setVdecInputBufferSize(unsigned int nBufferSize) { mVdecInputBufferSize = nBufferSize; return NO_ERROR; } unsigned int EyeseePlayer::getVdecInputBufferSize() const { return mVdecInputBufferSize; } status_t EyeseePlayer::prepare() { alogd("prepare"); Mutex::Autolock _l(mLock); status_t result = NO_ERROR; if(!(mCurrentState & (MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_STOPPED))) { aloge("called in wrong state 0x%x", mCurrentState); return INVALID_OPERATION; } mClockChnAttr.nWaitMask = 0; DEMUX_MEDIA_INFO_S DemuxMediaInfo; if(AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &DemuxMediaInfo) != SUCCESS) { aloge("fatal error! get media info fail!"); return UNKNOWN_ERROR; } if((DemuxMediaInfo.mVideoNum >0 && DemuxMediaInfo.mVideoIndex>=DemuxMediaInfo.mVideoNum) || (DemuxMediaInfo.mAudioNum >0 && DemuxMediaInfo.mAudioIndex>=DemuxMediaInfo.mAudioNum) || (DemuxMediaInfo.mSubtitleNum >0 && DemuxMediaInfo.mSubtitleIndex>=DemuxMediaInfo.mSubtitleNum)) { alogd("fatal error, trackIndex wrong! [%d][%d],[%d][%d],[%d][%d]", DemuxMediaInfo.mVideoNum, DemuxMediaInfo.mVideoIndex, DemuxMediaInfo.mAudioNum, DemuxMediaInfo.mAudioIndex, DemuxMediaInfo.mSubtitleNum, DemuxMediaInfo.mSubtitleIndex); return UNKNOWN_ERROR; } if(DemuxMediaInfo.mSubtitleNum > 0) { //select subtitle index. int dmxSubtitleIndex = mCurSubtitleTrackIndex - (DemuxMediaInfo.mVideoNum + DemuxMediaInfo.mAudioNum); if(dmxSubtitleIndex < 0) { AW_MPI_DEMUX_GetChnAttr(mDmxChn, &mDmxChnAttr); mDmxChnAttr.mDemuxDisableTrack |= DEMUX_DISABLE_SUBTITLE_TRACK; AW_MPI_DEMUX_SetChnAttr(mDmxChn, &mDmxChnAttr); } } ERRORTYPE ret; if(DemuxMediaInfo.mVideoNum>0 && !(mDmxChnAttr.mDemuxDisableTrack&DEMUX_DISABLE_VIDEO_TRACK)) { //create mpi_video decoder channel bool nSuccessFlag = false; config_VDEC_CHN_ATTR_S(&DemuxMediaInfo.mVideoStreamInfo[DemuxMediaInfo.mVideoIndex]); mVdecChn = 0; while(mVdecChn < VDEC_MAX_CHN_NUM) { ret = AW_MPI_VDEC_CreateChn(mVdecChn, &mVdecAttr); if(SUCCESS == ret) { nSuccessFlag = true; alogd("create vdec channel[%d] success!", mVdecChn); break; } else if(ERR_VDEC_EXIST == ret) { alogd("vdec channel[%d] is exist, find next!", mVdecChn); mVdecChn++; } else { alogd("create vdec channel[%d] ret[0x%x]!", mVdecChn, ret); break; } } if(false == nSuccessFlag) { mVdecChn = MM_INVALID_CHN; aloge("fatal error! create vdec channel fail!"); result = UNKNOWN_ERROR; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_VDEC_RegisterCallback(mVdecChn, &cbInfo); AW_MPI_VDEC_ForceFramePackage(mVdecChn, (BOOL)mbForceFramePackage); //bind demux component MPP_CHN_S DmxChn{MOD_ID_DEMUX, 0, mDmxChn}; MPP_CHN_S VdecChn{MOD_ID_VDEC, 0, mVdecChn}; AW_MPI_SYS_Bind(&DmxChn, &VdecChn); mClockChnAttr.nWaitMask |= 1<= 0) { //create vo channel bool bSuccessFlag = false; mVOLayer = mSurfaceHolder; mVOChn = 0; while(mVOChn < VO_MAX_CHN_NUM) { ret = AW_MPI_VO_CreateChn(mVOLayer, mVOChn); if(SUCCESS == ret) { bSuccessFlag = true; alogd("create vo channel[%d] success!", mVOChn); break; } else if(ERR_VO_CHN_NOT_DISABLE == ret) { alogd("vo channel[%d] is exist, find next!", mVOChn); mVOChn++; } else { alogd("create vo channel[%d] ret[0x%x]!", mVOChn, ret); break; } } if(false == bSuccessFlag) { mVOChn = MM_INVALID_CHN; aloge("fatal error! create vo channel fail!"); result = UNKNOWN_ERROR; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_VO_RegisterCallback(mVOLayer, mVOChn, &cbInfo); AW_MPI_VO_SetChnDispBufNum(mVOLayer, mVOChn, 2); //bind component MPP_CHN_S VdecChn{MOD_ID_VDEC, 0, mVdecChn}; MPP_CHN_S VOChn{MOD_ID_VOU, mVOLayer, mVOChn}; AW_MPI_SYS_Bind(&VdecChn, &VOChn); } if(DemuxMediaInfo.mAudioNum>0 && !(mDmxChnAttr.mDemuxDisableTrack&DEMUX_DISABLE_AUDIO_TRACK)) { //create mpi_audio decoder channel bool nSuccessFlag = false; config_ADEC_CHN_ATTR_S(&DemuxMediaInfo.mAudioStreamInfo[DemuxMediaInfo.mAudioIndex]); mAdecChn = 0; while(mAdecChn< ADEC_MAX_CHN_NUM) { ret = AW_MPI_ADEC_CreateChn(mAdecChn, &mAdecAttr); if(SUCCESS == ret) { nSuccessFlag = true; alogd("create adec channel[%d] success!", mAdecChn); break; } else if(ERR_ADEC_EXIST == ret) { alogd("adec channel[%d] is exist, find next!", mAdecChn); mAdecChn++; } else { alogd("create adec channel[%d] ret[0x%x]!", mAdecChn, ret); break; } } if(false == nSuccessFlag) { mAdecChn = MM_INVALID_CHN; aloge("fatal error! create adec channel fail!"); result = UNKNOWN_ERROR; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_ADEC_RegisterCallback(mAdecChn, &cbInfo); //bind demux component MPP_CHN_S DmxChn{MOD_ID_DEMUX, 0, mDmxChn}; MPP_CHN_S AdecChn{MOD_ID_ADEC, 0, mAdecChn}; AW_MPI_SYS_Bind(&DmxChn, &AdecChn); mClockChnAttr.nWaitMask |= 1<= 0) { mAODev = 0; //config_AIO_ATTR_S(&DemuxMediaInfo.mAudioStreamInfo[DemuxMediaInfo.mAudioIndex]); //AW_MPI_AO_SetPubAttr(mAODev, &mAioAttr); //enable audio_hw_ao //embeded in AW_MPI_AO_CreateChn, not need call this api any more. //AW_MPI_AO_Enable(mAODev); //create ao channel bool bSuccessFlag = false; mAOChn = 0; while(mAOChn < AIO_MAX_CHN_NUM) { ret = AW_MPI_AO_CreateChn(mAODev, mAOChn); if(SUCCESS == ret) { bSuccessFlag = true; alogd("create ao channel[%d] success!", mAOChn); break; } else if (ERR_AO_EXIST == ret) { alogd("ao channel[%d] exist, find next!", mAOChn); mAOChn++; } else if(ERR_AO_NOT_ENABLED == ret) { aloge("audio_hw_ao not started!"); break; } else { aloge("create ao channel[%d] fail! ret[0x%x]!", mAOChn, ret); break; } } if(false == bSuccessFlag) { mAOChn = MM_INVALID_CHN; aloge("fatal error! create ao channel fail!"); result = UNKNOWN_ERROR; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_AO_RegisterCallback(mAODev, mAOChn, &cbInfo); AW_MPI_AO_SetPcmCardType(mAODev, mAOChn, mAOCardId); AW_MPI_AO_SetChnVps(mAODev, mAOChn, mfVps); // AUDIO_SAVE_FILE_INFO_S stSaveFileInfo; // memset(&stSaveFileInfo, 0, sizeof(AUDIO_SAVE_FILE_INFO_S)); // strcpy(stSaveFileInfo.mFilePath, "/mnt/extsd/"); // strcpy(stSaveFileInfo.mFileName, "ao.pcm"); // AW_MPI_AO_SaveFile(mAODev, mAOChn, &stSaveFileInfo); //bind component MPP_CHN_S AdecChn{MOD_ID_ADEC, 0, mAdecChn}; MPP_CHN_S AOChn{MOD_ID_AO, mAODev, mAOChn}; AW_MPI_SYS_Bind(&AdecChn, &AOChn); } { //create clock channel if(mClockChn >= 0) { aloge("fatal error! clock channel should not exist now!"); } bool bSuccessFlag = false; mClockChn = 0; while(mClockChn < CLOCK_MAX_CHN_NUM) { ret = AW_MPI_CLOCK_CreateChn(mClockChn, &mClockChnAttr); if(SUCCESS == ret) { bSuccessFlag = true; alogd("create clock channel[%d] success!", mClockChn); break; } else if(ERR_CLOCK_EXIST == ret) { alogd("clock channel[%d] is exist, find next!", mClockChn); mClockChn++; } else { alogd("create clock channel[%d] ret[0x%x]!", mClockChn, ret); break; } } if(false == bSuccessFlag) { mClockChn = MM_INVALID_CHN; aloge("fatal error! create clock channel fail!"); result = UNKNOWN_ERROR; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)this; cbInfo.callback = (MPPCallbackFuncType)&MPPCallbackWrapper; AW_MPI_CLOCK_RegisterCallback(mClockChn, &cbInfo); AW_MPI_CLOCK_SetVps(mClockChn, mfVps); //bind component MPP_CHN_S ClockChn{MOD_ID_CLOCK, 0, mClockChn}; MPP_CHN_S DmxChn{MOD_ID_DEMUX, 0, mDmxChn}; AW_MPI_SYS_Bind(&ClockChn, &DmxChn); if(mVOChn >= 0) { MPP_CHN_S VOChn{MOD_ID_VOU, mVOLayer, mVOChn}; AW_MPI_SYS_Bind(&ClockChn, &VOChn); } if (mAOChn>=0) { MPP_CHN_S ClockChn{MOD_ID_CLOCK, 0, mClockChn}; MPP_CHN_S AOChn{MOD_ID_AO, mAODev, mAOChn}; AW_MPI_SYS_Bind(&ClockChn, &AOChn); } } if(DemuxMediaInfo.mVideoNum>0 && !(mDmxChnAttr.mDemuxDisableTrack&DEMUX_DISABLE_VIDEO_TRACK)) { DEMUX_VIDEO_STREAM_INFO_S *pVideoStream = &DemuxMediaInfo.mVideoStreamInfo[DemuxMediaInfo.mVideoIndex]; mDisplayWidth = pVideoStream->mWidth; mDisplayHeight = pVideoStream->mHeight; postEventFromNative(this, MEDIA_SET_VIDEO_SIZE, pVideoStream->mWidth, pVideoStream->mHeight, NULL); } mCurrentState = MEDIA_PLAYER_PREPARED; _err0: return result; } status_t EyeseePlayer::start_l() { alogv("start_l"); status_t opStatus = NO_ERROR; if(!(mCurrentState & (MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))) { aloge("called in wrong state 0x%x", mCurrentState); return INVALID_OPERATION; } { Mutex::Autolock autoLock(mNotifyEofLock); mDmxNotifyEof = false; mVdecNotifyEof = false; mAdecNotifyEof = false; mVONotifyEof = false; mAONotifyEof = false; } if(mbSeekStart) { seekTo_l(mSeekStartPosition); mbSeekStart = false; } else { if(mCurrentState & MEDIA_PLAYER_PLAYBACK_COMPLETE) { seekTo_l(0); } } if(mClockChn >= 0) { AW_MPI_CLOCK_Start(mClockChn); } if(mVdecChn >= 0) { AW_MPI_VDEC_StartRecvStream(mVdecChn); } if(mVOChn>=0) { AW_MPI_VO_StartChn(mVOLayer, mVOChn); } if(mAdecChn >= 0) { AW_MPI_ADEC_StartRecvStream(mAdecChn); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_StartChn(mAODev, mAOChn); } if(mDmxChn >= 0) { AW_MPI_DEMUX_Start(mDmxChn); } mCurrentState = MEDIA_PLAYER_STARTED; return opStatus; } status_t EyeseePlayer::start() { alogd("start"); Mutex::Autolock _l(mLock); return start_l(); } status_t EyeseePlayer::stop_l() { alogv("stop_l"); status_t opStatus = NO_ERROR; if(!(mCurrentState & (MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))) { aloge("called in wrong state 0x%x", mCurrentState); return INVALID_OPERATION; } if(mVOChn>=0) { AW_MPI_VO_HideChn(mVOLayer, mVOChn); AW_MPI_VO_StopChn(mVOLayer, mVOChn); } if(mVdecChn >= 0) { AW_MPI_VDEC_StopRecvStream(mVdecChn); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_StopChn(mAODev, mAOChn); } if(mAdecChn >= 0) { AW_MPI_ADEC_StopRecvStream(mAdecChn); } if(mDmxChn >= 0) { AW_MPI_DEMUX_Stop(mDmxChn); } if(mClockChn >= 0) { AW_MPI_CLOCK_Stop(mClockChn); } //keep demux channel, destroy others. if(mVOChn>=0) { AW_MPI_VO_DestroyChn(mVOLayer, mVOChn); mVOChn = MM_INVALID_CHN; } if(mVdecChn >= 0) { AW_MPI_VDEC_DestroyChn(mVdecChn); mVdecChn = MM_INVALID_CHN; } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_DestroyChn(mAODev, mAOChn); mAOChn = MM_INVALID_CHN; } if(mAdecChn >= 0) { AW_MPI_ADEC_DestroyChn(mAdecChn); mAdecChn = MM_INVALID_CHN; } if(mClockChn >= 0) { AW_MPI_CLOCK_DestroyChn(mClockChn); mClockChn = MM_INVALID_CHN; } mCurrentState = MEDIA_PLAYER_STOPPED; return opStatus; } status_t EyeseePlayer::stop() { alogv("stop"); Mutex::Autolock _l(mLock); return stop_l(); } status_t EyeseePlayer::pause_l() { alogv("pause_l"); status_t opStatus = NO_ERROR; if(!(mCurrentState & MEDIA_PLAYER_STARTED)) { aloge("fatal error! called in wrong state 0x%x", mCurrentState); return INVALID_OPERATION; } if(mDmxChn >= 0) { AW_MPI_DEMUX_Pause(mDmxChn); } if(mVOChn>=0) { AW_MPI_VO_PauseChn(mVOLayer, mVOChn); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_PauseChn(mAODev, mAOChn); } if(mClockChn >= 0) { AW_MPI_CLOCK_Pause(mClockChn); } if(mVdecChn >= 0) { AW_MPI_VDEC_Pause(mVdecChn); } if(mAdecChn >= 0) { AW_MPI_ADEC_Pause(mAdecChn); } mTempPosition = getCurrentPosition_l(); mCurrentState = MEDIA_PLAYER_PAUSED; return opStatus; } status_t EyeseePlayer::pause() { alogv("pause"); Mutex::Autolock _l(mLock); return pause_l(); } status_t EyeseePlayer::playbackComplete() { alogv("playbackComplete"); Mutex::Autolock _l(mLock); if(!(mCurrentState & MEDIA_PLAYER_STARTED)) { aloge("fatal error! called in wrong state 0x%x", mCurrentState); return INVALID_OPERATION; } if(mVOChn>=0) { AW_MPI_VO_StopChn(mVOLayer, mVOChn); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_StopChn(mAODev, mAOChn); } if(mVdecChn >= 0) { AW_MPI_VDEC_StopRecvStream(mVdecChn); } if(mAdecChn >= 0) { AW_MPI_ADEC_StopRecvStream(mAdecChn); } if(mDmxChn >= 0) { AW_MPI_DEMUX_Stop(mDmxChn); } if(mClockChn >= 0) { AW_MPI_CLOCK_Stop(mClockChn); } mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; return NO_ERROR; } status_t EyeseePlayer::getVideoWidth(int *width) { Mutex::Autolock _l(mLock); *width = 0; if(mCurrentState&MEDIA_PLAYER_IDLE || mCurrentState==MEDIA_PLAYER_STATE_ERROR) { return NO_ERROR; } else if(mCurrentState & (MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_PREPARING|MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STOPPED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) { if(mDmxChn >= 0) { DEMUX_MEDIA_INFO_S DemuxMediaInfo; AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &DemuxMediaInfo); *width = DemuxMediaInfo.mVideoStreamInfo[DemuxMediaInfo.mVideoIndex].mWidth; } else { aloge("fatal error! why demux channel not exist?"); } } else if(mCurrentState & (MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED)) { if(mVOChn>=0) { SIZE_S displaySize; AW_MPI_VO_GetDisplaySize(mVOLayer, mVOChn, &displaySize); *width = displaySize.Width; } else { aloge("fatal error! why VO channel not exist?"); } } else { aloge("fatal error! check code!"); } return NO_ERROR; } status_t EyeseePlayer::getVideoHeight(int *height) { Mutex::Autolock _l(mLock); *height = 0; if(mCurrentState&MEDIA_PLAYER_IDLE || mCurrentState==MEDIA_PLAYER_STATE_ERROR) { return NO_ERROR; } else if(mCurrentState & (MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_PREPARING|MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STOPPED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) { if(mDmxChn >= 0) { DEMUX_MEDIA_INFO_S DemuxMediaInfo; AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &DemuxMediaInfo); *height = DemuxMediaInfo.mVideoStreamInfo[DemuxMediaInfo.mVideoIndex].mHeight; } else { aloge("fatal error! why demux channel not exist?"); } } else if(mCurrentState & (MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED)) { if(mVOChn>=0) { SIZE_S displaySize; AW_MPI_VO_GetDisplaySize(mVOLayer, mVOChn, &displaySize); *height = displaySize.Height; } else { aloge("fatal error! why VO channel not exist?"); } } else { aloge("fatal error! check code!"); } return NO_ERROR; } bool EyeseePlayer::isPlaying() { Mutex::Autolock _l(mLock); bool is_playing = false; if(mCurrentState & MEDIA_PLAYER_STARTED) { is_playing = true; } return is_playing; } status_t EyeseePlayer::seekTo_l(int msec) { alogv("seekTo_l: %d(msec)", msec); Mutex::Autolock autoLock(mNotifyEofLock); status_t opStatus = NO_ERROR; if(mDmxChn >= 0) { opStatus = AW_MPI_DEMUX_Seek(mDmxChn, msec); if(opStatus != NO_ERROR) { return opStatus; } if(mAdecChn >= 0) { AW_MPI_ADEC_SetStreamEof(mAdecChn, 0); } if(mAOChn >= 0) { AW_MPI_AO_SetStreamEof(mAODev, mAOChn, 0, FALSE); } if(mVdecChn >= 0) { AW_MPI_VDEC_SetStreamEof(mVdecChn, 0); } if(mVOChn >= 0) { AW_MPI_VO_SetStreamEof(mVOLayer, mVOChn, 0); } mDmxNotifyEof = false; mVdecNotifyEof = false; mAdecNotifyEof = false; mVONotifyEof = false; mAONotifyEof = false; } if(mVOChn>=0) { AW_MPI_VO_Seek(mVOLayer, mVOChn); } if(mVdecChn >= 0) { AW_MPI_VDEC_Seek(mVdecChn); } if(mAODev>=0 && mAOChn>=0) { AW_MPI_AO_Seek(mAODev, mAOChn); } if(mAdecChn >= 0) { AW_MPI_ADEC_Seek(mAdecChn); } if(mClockChn >= 0) { AW_MPI_CLOCK_Seek(mClockChn); } return opStatus; } status_t EyeseePlayer::processSeekTo(int msec) { Mutex::Autolock _l(mLock); alogv("processSeekTo: %d(msec)", msec); status_t opStatus = NO_ERROR; if(mCurrentState & (MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_PLAYBACK_COMPLETE|MEDIA_PLAYER_PAUSED)) { mSeekStartPosition = msec; mbSeekStart = true; } else if(mCurrentState & MEDIA_PLAYER_STARTED) { mbSeekStart = false; pause_l(); seekTo_l(msec); start_l(); } else { aloge("fatal error! illegal state[0x%x] can't come here!", mCurrentState); opStatus = UNKNOWN_ERROR; } mTempPosition = msec; postEventFromNative(this, MEDIA_SEEK_COMPLETE, 0, 0, NULL); return opStatus; } status_t EyeseePlayer::seekTo(int msec) { Mutex::Autolock _l(mLock); alogv("seekTo: %d(msec)", msec); status_t opStatus = NO_ERROR; if(!(mCurrentState & (MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))) { alogw("can't seek in current state[0x%x]", mCurrentState); return INVALID_OPERATION; } EyeseeMessage cmdMsg; cmdMsg.mMsgType = PLAYER_COMMAND_SEEK; cmdMsg.mPara0 = msec; mCommandQueue.queueMessage(&cmdMsg); return opStatus; } int EyeseePlayer::getCurrentPosition_l() { if(mCurrentState&(MEDIA_PLAYER_IDLE|MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_PREPARING|MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STOPPED) || MEDIA_PLAYER_STATE_ERROR==mCurrentState) { return 0; } else if(mCurrentState & (MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED)) { if(mbSeekStart) { alogd("playerState[0x%x], during seeking ,use seekDstPos[%d]ms", mCurrentState, mTempPosition); return mTempPosition; } else { int mediaTime = -1; AW_MPI_CLOCK_GetCurrentMediaTime(mClockChn, &mediaTime); if(-1 == mediaTime) { mediaTime = mTempPosition; } return mediaTime; } } else if(mCurrentState & MEDIA_PLAYER_PLAYBACK_COMPLETE) { DEMUX_MEDIA_INFO_S DemuxMediaInfo; if(AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &DemuxMediaInfo) != SUCCESS) { aloge("fatal error! get media info fail in playback_complete state!"); } return DemuxMediaInfo.mDuration; } else { aloge("fatal error! unknown state[0x%x]!", mCurrentState); return 0; } } int EyeseePlayer::getCurrentPosition() { Mutex::Autolock _l(mLock); return getCurrentPosition_l(); } int EyeseePlayer::getDuration() { Mutex::Autolock _l(mLock); if(mCurrentState&MEDIA_PLAYER_IDLE || MEDIA_PLAYER_STATE_ERROR==mCurrentState) { aloge("fatal error! call in wrong state[0x%x]!", mCurrentState); return 0; } else if(mCurrentState & (MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_PREPARING|MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_STOPPED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) { DEMUX_MEDIA_INFO_S stMediaInfo; AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &stMediaInfo); return stMediaInfo.mDuration; } else { aloge("fatal error! unknown state[0x%x]!", mCurrentState); return 0; } } status_t EyeseePlayer::reset_l() { alogv("reset_l"); if(MEDIA_PLAYER_STATE_ERROR == mCurrentState) { alogd("can't reset in stateError, try to destruct it."); return INVALID_OPERATION; } if(MEDIA_PLAYER_PREPARING == mCurrentState) { aloge("fatal error! can't reset_l() in statePreparing!"); return INVALID_OPERATION; } if(mCurrentState & (MEDIA_PLAYER_PREPARED|MEDIA_PLAYER_STARTED|MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) { stop_l(); } if(mCurrentState & (MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_STOPPED)) { if(mDmxChn >= 0) { AW_MPI_DEMUX_DestroyChn(mDmxChn); mDmxChn = MM_INVALID_CHN; } mCurrentState = MEDIA_PLAYER_IDLE; } mbGrantAudio = true; mCurSubtitleTrackIndex = -1; mDisplayWidth = 0; mDisplayHeight = 0; mDmxNotifyEof = false; mVdecNotifyEof = false; mAdecNotifyEof = false; mVONotifyEof = false; mAONotifyEof = false; mDmxChn = MM_INVALID_CHN; mVdecChn = MM_INVALID_CHN; mVOLayer = MM_INVALID_DEV; mVOChn = MM_INVALID_CHN; mAdecChn = MM_INVALID_CHN; mAODev = MM_INVALID_DEV; mAOChn = MM_INVALID_CHN; mClockChn = MM_INVALID_CHN; return NO_ERROR; } status_t EyeseePlayer::reset() { alogv("reset"); Mutex::Autolock _l(mLock); return reset_l(); } status_t EyeseePlayer::setAudioStreamType(int streamtype) { alogv("setAudioStreamType: %d", streamtype); alogw("unsupported temporary"); //streamtype: AUDIO_STREAM_MUSIC return UNKNOWN_ERROR; } status_t EyeseePlayer::setLooping(bool looping) { alogv("setLooping: %d", looping); Mutex::Autolock _l(mLock); status_t opStatus = NO_ERROR; mLoop = looping; return opStatus; } bool EyeseePlayer::isLooping() { alogv("isLooping"); Mutex::Autolock _l(mLock); return mLoop; } status_t EyeseePlayer::getVolume(float *leftVolume, float *rightVolume) { int val; AW_MPI_AO_GetDevVolume(mAODev, &val); *leftVolume = *rightVolume = (float)val/100; return NO_ERROR; } status_t EyeseePlayer::setVolume(float leftVolume, float rightVolume) { AW_MPI_AO_SetDevVolume(mAODev, (int)(leftVolume*100)); return NO_ERROR; } status_t EyeseePlayer::setMuteMode(bool mute) { if (true == mute) AW_MPI_AO_SetDevMute(mAODev, 1, NULL); else AW_MPI_AO_SetDevMute(mAODev, 0, NULL); return NO_ERROR; } status_t EyeseePlayer::getMuteMode(BOOL* pMute) { AW_MPI_AO_GetDevMute(mAODev, pMute, NULL); return NO_ERROR; } status_t EyeseePlayer::setAOCardType(PCM_CARD_TYPE_E cardId) { alogd("set audio card type(%d)", cardId); mAOCardId = cardId; return NO_ERROR; } status_t EyeseePlayer::setAudioSessionId(int sessionId) { alogv("set_session_id(): %d", sessionId); alogw("unsupported temporary"); return UNKNOWN_ERROR; } int EyeseePlayer::getAudioSessionId() { alogv("get_session_id()"); alogw("unsupported temporary"); return UNKNOWN_ERROR; } status_t EyeseePlayer::attachAuxEffect(int effectId) { alogv("attachAuxEffect(): %d", effectId); alogw("unsupported temporary"); return UNKNOWN_ERROR; } status_t EyeseePlayer::setAuxEffectSendLevel(float level) { alogv("setAuxEffectSendLevel: level %f", level); alogw("unsupported temporary"); return UNKNOWN_ERROR; } status_t EyeseePlayer::grantPlayAudio(bool bGrant) { Mutex::Autolock _l(mLock); if(!(mCurrentState&MEDIA_PLAYER_IDLE)) { aloge("called in wrong state %d", mCurrentState); return INVALID_OPERATION; } mbGrantAudio = bGrant; return NO_ERROR; } int EyeseePlayer::TrackInfo::getTrackType() const { return mTrackType; } const string& EyeseePlayer::TrackInfo::getLanguage() const { return mLanguage; } EyeseePlayer::TrackInfo::TrackInfo(int trackType, string language, int StreamIndex, DEMUX_MEDIA_INFO_S &DemuxMediaInfo) : mTrackType(trackType), mLanguage(language) { switch (mTrackType) { case MEDIA_TRACK_TYPE_VIDEO: { mVideoTrackInfo = DemuxMediaInfo.mVideoStreamInfo[StreamIndex]; break; } case MEDIA_TRACK_TYPE_AUDIO: { mAudioTrackInfo = DemuxMediaInfo.mAudioStreamInfo[StreamIndex]; break; } case MEDIA_TRACK_TYPE_TIMEDTEXT: { mSubitleTrackInfo = DemuxMediaInfo.mSubtitleStreamInfo[StreamIndex]; break; } default : break; } } EyeseePlayer::TrackInfo::TrackInfo(const TrackInfo& trackInfo) : mTrackType(trackInfo.getTrackType()), mLanguage(trackInfo.getLanguage()) { switch (mTrackType) { case MEDIA_TRACK_TYPE_VIDEO: { mVideoTrackInfo = trackInfo.mVideoTrackInfo; break; } case MEDIA_TRACK_TYPE_AUDIO: { mAudioTrackInfo = trackInfo.mAudioTrackInfo; break; } case MEDIA_TRACK_TYPE_TIMEDTEXT: { mSubitleTrackInfo = trackInfo.mSubitleTrackInfo; break; } default : break; } } EyeseePlayer::TrackInfo& EyeseePlayer::TrackInfo::operator=(const EyeseePlayer::TrackInfo& trackInfo) { mTrackType = trackInfo.getTrackType(); mLanguage = trackInfo.getLanguage(); switch (mTrackType) { case MEDIA_TRACK_TYPE_VIDEO: { mVideoTrackInfo = trackInfo.mVideoTrackInfo; break; } case MEDIA_TRACK_TYPE_AUDIO: { mAudioTrackInfo = trackInfo.mAudioTrackInfo; break; } case MEDIA_TRACK_TYPE_TIMEDTEXT: { mSubitleTrackInfo = trackInfo.mSubitleTrackInfo; break; } default : break; } return *this; } void EyeseePlayer::getTrackInfo(vector &trackInfo) { Mutex::Autolock _l(mLock); if(mCurrentState&MEDIA_PLAYER_IDLE || MEDIA_PLAYER_STATE_ERROR==mCurrentState) { alogw("not get track info in state[0x%x]!", mCurrentState); return; } DEMUX_MEDIA_INFO_S DemuxMediaInfo; if(AW_MPI_DEMUX_GetMediaInfo(mDmxChn, &DemuxMediaInfo) != SUCCESS) { aloge("fatal error! get media info fail!"); return; } int i; TrackInfo *pTrackInfo; for(i=0; i= DemuxMediaInfo.mVideoNum && index < (DemuxMediaInfo.mVideoNum+DemuxMediaInfo.mAudioNum)) { index = index - DemuxMediaInfo.mVideoNum; AW_MPI_DEMUX_SelectAudioStream(mDmxChn, index); } else if (index >= (DemuxMediaInfo.mVideoNum+DemuxMediaInfo.mAudioNum) && index < (DemuxMediaInfo.mVideoNum+DemuxMediaInfo.mAudioNum+DemuxMediaInfo.mSubtitleNum)) { index = index - DemuxMediaInfo.mVideoNum - DemuxMediaInfo.mAudioNum; AW_MPI_DEMUX_SelectSubtitleStream(mDmxChn, index); } } } void EyeseePlayer::setOnPreparedListener(OnPreparedListener *pListener) { mOnPreparedListener = pListener; } void EyeseePlayer::setOnCompletionListener(OnCompletionListener *pListener) { mOnCompletionListener = pListener; } void EyeseePlayer::setOnSeekCompleteListener(OnSeekCompleteListener *pListener) { mOnSeekCompleteListener = pListener; } void EyeseePlayer::setOnVideoSizeChangedListener(OnVideoSizeChangedListener *pListener) { mOnVideoSizeChangedListener = pListener; } void EyeseePlayer::setOnTimedTextListener(OnTimedTextListener *pListener) { mOnTimedTextListener = pListener; } void EyeseePlayer::setOnErrorListener(OnErrorListener *pListener) { mOnErrorListener = pListener; } void EyeseePlayer::setOnInfoListener(OnInfoListener *pListener) { mOnInfoListener = pListener; } status_t EyeseePlayer::setSubCharset(string charset) { alogw("unsupported temporary"); return UNKNOWN_ERROR; } status_t EyeseePlayer::getSubCharset(string &charset) { alogw("unsupported temporary"); return UNKNOWN_ERROR; } status_t EyeseePlayer::setSubDelay(int time) { alogw("unsupported temporary"); return UNKNOWN_ERROR; } int EyeseePlayer::getSubDelay() { alogw("unsupported temporary"); return 0; } status_t EyeseePlayer::enableScaleMode(bool enable, int width, int height) { Mutex::Autolock _l(mLock); if(!(mCurrentState&(MEDIA_PLAYER_IDLE|MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_STOPPED))) { alogw("not set scale mode in state[0x%x]!", mCurrentState); return UNKNOWN_ERROR; } if(enable) { mMaxVdecOutputWidth = width; mMaxVdecOutputHeight = height; } else { mMaxVdecOutputWidth = 0; mMaxVdecOutputHeight = 0; } return NO_ERROR; } status_t EyeseePlayer::setRotation(ROTATE_E val) { Mutex::Autolock _l(mLock); if(!(mCurrentState&(MEDIA_PLAYER_IDLE|MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_STOPPED))) { alogw("not set rotation in state[0x%x]!", mCurrentState); return UNKNOWN_ERROR; } mInitRotation = val; return NO_ERROR; } status_t EyeseePlayer::ForceFramePackage(bool bFlag) { Mutex::Autolock _l(mLock); if(!(mCurrentState&(MEDIA_PLAYER_IDLE|MEDIA_PLAYER_INITIALIZED|MEDIA_PLAYER_STOPPED))) { alogw("not set force frame package in state[0x%x]!", mCurrentState); return UNKNOWN_ERROR; } mbForceFramePackage = bFlag; return NO_ERROR; } void EyeseePlayer::postEventFromNative(EyeseePlayer *pPlayer, int what, int arg1, int arg2, const std::shared_ptr* pDataPtr) { if (pPlayer == NULL) { aloge("pPlayer == NULL"); return; } if (pPlayer->mEventHandler != NULL) { CallbackMessage msg; msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; //msg.obj = obj; if(pDataPtr) { msg.mDataPtr = std::const_pointer_cast(*pDataPtr); } pPlayer->mEventHandler->post(msg); } } void EyeseePlayer::notify(MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData) { if(MOD_ID_DEMUX == pChn->mModId) { switch(event) { case MPP_EVENT_NOTIFY_EOF: { postEventFromNative(this, MEDIA_NOTIFY_EOF, pChn->mModId, 0, NULL); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else if(MOD_ID_VDEC == pChn->mModId) { switch(event) { case MPP_EVENT_NOTIFY_EOF: { postEventFromNative(this, MEDIA_NOTIFY_EOF, pChn->mModId, 0, NULL); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else if(MOD_ID_VOU == pChn->mModId) { switch(event) { case MPP_EVENT_NOTIFY_EOF: { postEventFromNative(this, MEDIA_NOTIFY_EOF, pChn->mModId, 0, NULL); break; } case MPP_EVENT_SET_VIDEO_SIZE: { SIZE_S *pDisplaySize = (SIZE_S*)pEventData; if(mDisplayWidth!=(int)pDisplaySize->Width || mDisplayHeight!=(int)pDisplaySize->Height) { alogd("vdec display size[%dx%d] not match with demuxInfo[%dx%d]", pDisplaySize->Width, pDisplaySize->Height, mDisplayWidth, mDisplayHeight); mDisplayWidth = pDisplaySize->Width; mDisplayHeight = pDisplaySize->Height; postEventFromNative(this, MEDIA_SET_VIDEO_SIZE, pDisplaySize->Width, pDisplaySize->Height, NULL); } else { alogd("vdec display size[%dx%d] same to demuxInfo", pDisplaySize->Width, pDisplaySize->Height); } break; } case MPP_EVENT_RENDERING_START: { postEventFromNative(this, MEDIA_INFO, MEDIA_INFO_VIDEO_RENDERING_START, 0, NULL); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else if (MOD_ID_ADEC == pChn->mModId) { switch(event) { case MPP_EVENT_NOTIFY_EOF: { postEventFromNative(this, MEDIA_NOTIFY_EOF, pChn->mModId, 0, NULL); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else if (MOD_ID_AO == pChn->mModId) { switch(event) { case MPP_EVENT_NOTIFY_EOF: { postEventFromNative(this, MEDIA_NOTIFY_EOF, pChn->mModId, 0, NULL); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else { aloge("fatal error! need implement!"); } } /* Do not change these values without updating their counterparts * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp! */ /** * MIME type for SubRip (SRT) container. Used in addTimedTextSource APIs. */ const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SUBRIP[] = "application/x-subrip"; /* Do not change these values without updating their counterparts * in media/CedarX-Projects/CedarX/libutil/CDX_MediaDefs.h * and media/CedarX-Projects/CedarX/libutil/CDX_MediaDefs.cpp */ const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_IDXSUB[] = "application/idx-sub"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SUB[] = "application/sub"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SMI[] = "text/smi"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_RT[] = "text/rt"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_TXT[] = "text/txt"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SSA[] = "text/ssa"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_AQT[] = "text/aqt"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_JSS[] = "text/jss"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_JS[] = "text/js"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_ASS[] = "text/ass"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_VSF[] = "text/vsf"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_TTS[] = "text/tts"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_STL[] = "text/stl"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_ZEG[] = "text/zeg"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_OVR[] = "text/ovr"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_DKS[] = "text/dks"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_LRC[] = "text/lrc"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_PAN[] = "text/pan"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SBT[] = "text/sbt"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_VKT[] = "text/vkt"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_PJS[] = "text/pjs"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_MPL[] = "text/mpl"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SCR[] = "text/scr"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_PSB[] = "text/psb"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_ASC[] = "text/asc"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_RTF[] = "text/rtf"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_S2K[] = "text/s2k"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SST[] = "text/sst"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SON[] = "text/son"; const char EyeseePlayer::MEDIA_MIMETYPE_TEXT_SSTS[] = "text/ssts"; bool EyeseePlayer::availableMimeTypeForExternalSource(string mimeType) { if (mimeType == MEDIA_MIMETYPE_TEXT_SUBRIP || mimeType == MEDIA_MIMETYPE_TEXT_IDXSUB || mimeType == MEDIA_MIMETYPE_TEXT_SUB || mimeType == MEDIA_MIMETYPE_TEXT_SMI || mimeType == MEDIA_MIMETYPE_TEXT_RT || mimeType == MEDIA_MIMETYPE_TEXT_TXT || mimeType == MEDIA_MIMETYPE_TEXT_SSA || mimeType == MEDIA_MIMETYPE_TEXT_AQT || mimeType == MEDIA_MIMETYPE_TEXT_JSS || mimeType == MEDIA_MIMETYPE_TEXT_JS || mimeType == MEDIA_MIMETYPE_TEXT_ASS || mimeType == MEDIA_MIMETYPE_TEXT_VSF || mimeType == MEDIA_MIMETYPE_TEXT_TTS || mimeType == MEDIA_MIMETYPE_TEXT_STL || mimeType == MEDIA_MIMETYPE_TEXT_ZEG || mimeType == MEDIA_MIMETYPE_TEXT_OVR || mimeType == MEDIA_MIMETYPE_TEXT_DKS || mimeType == MEDIA_MIMETYPE_TEXT_LRC || mimeType == MEDIA_MIMETYPE_TEXT_PAN || mimeType == MEDIA_MIMETYPE_TEXT_SBT || mimeType == MEDIA_MIMETYPE_TEXT_VKT || mimeType == MEDIA_MIMETYPE_TEXT_PJS || mimeType == MEDIA_MIMETYPE_TEXT_MPL || mimeType == MEDIA_MIMETYPE_TEXT_SCR || mimeType == MEDIA_MIMETYPE_TEXT_PSB || mimeType == MEDIA_MIMETYPE_TEXT_ASC || mimeType == MEDIA_MIMETYPE_TEXT_RTF || mimeType == MEDIA_MIMETYPE_TEXT_S2K || mimeType == MEDIA_MIMETYPE_TEXT_SST || mimeType == MEDIA_MIMETYPE_TEXT_SON || mimeType == MEDIA_MIMETYPE_TEXT_SSTS) { return true; } return false; } status_t EyeseePlayer::config_VDEC_CHN_ATTR_S(DEMUX_VIDEO_STREAM_INFO_S *pStreamInfo) { memset(&mVdecAttr, 0, sizeof(VDEC_CHN_ATTR_S)); mVdecAttr.mType = pStreamInfo->mCodecType; mVdecAttr.mBufSize = mVdecInputBufferSize; mVdecAttr.mPicWidth = mMaxVdecOutputWidth; mVdecAttr.mPicHeight = mMaxVdecOutputHeight; mVdecAttr.mInitRotation = mInitRotation; mVdecAttr.mOutputPixelFormat = mUserSetPixelFormat; mVdecAttr.mVdecVideoAttr.mMode = VIDEO_MODE_FRAME; mVdecAttr.mVdecVideoAttr.mSupportBFrame = 1; return NO_ERROR; } status_t EyeseePlayer::config_ADEC_CHN_ATTR_S(DEMUX_AUDIO_STREAM_INFO_S *pStreamInfo) { memset(&mAdecAttr, 0, sizeof(ADEC_CHN_ATTR_S)); mAdecAttr.mType = pStreamInfo->mCodecType; mAdecAttr.sampleRate = pStreamInfo->mSampleRate; mAdecAttr.channels = pStreamInfo->mChannelNum; mAdecAttr.bitsPerSample = pStreamInfo->mBitsPerSample; // only support mono and 8k now //assert(mAdecAttr.channels <= 1 && mAdecAttr.sampleRate == 8000); return NO_ERROR; } status_t EyeseePlayer::config_AIO_ATTR_S(DEMUX_AUDIO_STREAM_INFO_S *pStreamInfo) { memset(&mAioAttr, 0, sizeof(AIO_ATTR_S)); mAioAttr.mChnCnt = pStreamInfo->mChannelNum; mAioAttr.enSamplerate = (AUDIO_SAMPLE_RATE_E)pStreamInfo->mSampleRate; switch(pStreamInfo->mBitsPerSample) { case 8: mAioAttr.enBitwidth = AUDIO_BIT_WIDTH_8; break; case 16: mAioAttr.enBitwidth = AUDIO_BIT_WIDTH_16; break; case 24: mAioAttr.enBitwidth = AUDIO_BIT_WIDTH_24; break; case 32: mAioAttr.enBitwidth = AUDIO_BIT_WIDTH_32; break; default: alogw("Why movie's audio_bitwidth is %d?! Init Audio_Hw with 16!", pStreamInfo->mBitsPerSample); break; } mAioAttr.mPcmCardId = mAOCardId; alogd("AIO_ATTR: chncnt-%d, bitwidth-%d, samplerate-%d, cardid-%d", mAioAttr.mChnCnt, pStreamInfo->mBitsPerSample, mAioAttr.enSamplerate, mAOCardId); return NO_ERROR; } void* EyeseePlayer::EyeseeCommandThread(void *pThreadData) { EyeseePlayer *pPlayer = (EyeseePlayer*)pThreadData; EyeseeMessage cmdMsg; while(1) { if(pPlayer->mCommandQueue.dequeueMessage(&cmdMsg) == NO_ERROR) { if(PLAYER_COMMAND_SEEK == cmdMsg.mMsgType) { pPlayer->processSeekTo(cmdMsg.mPara0); } else if(PLAYER_COMMAND_STOP == cmdMsg.mMsgType) { alogd("receive stop command, exit!"); goto _exit; } } else { pPlayer->mCommandQueue.waitMessage(0); } } _exit: return (void*)NO_ERROR; } };