sdk-hwV1.3/external/eyesee-mpp/framework/sun8iw21/media/player/EyeseePlayer.cpp

2107 lines
62 KiB
C++
Executable File

/*
* 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 <utils/plat_log.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
//#include "jni.h"
//#include "JNIHelp.h"
//#include "android_runtime/AndroidRuntime.h"
#include <cutils/properties.h>
#include <vector>
//#include <gui/SurfaceTexture.h>
//#include <gui/Surface.h>
//#include <camera/Camera.h>
//#include <binder/IMemory.h>
//#include <binder/IServiceManager.h>
#include <vdecoder.h>
#include <adecoder.h>
#include <mpi_demux.h>
#include <mpi_vdec.h>
#include <mpi_adec.h>
#include <mpi_vo.h>
#include <mpi_ao.h>
#include <mpi_clock.h>
#include <mpi_sys.h>
#include <Clock_Component.h>
#include <EyeseePlayer.h>
#include <CallbackDispatcher.h>
#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<<CLOCK_PORT_INDEX_VIDEO;
}
if(mVdecChn >= 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<<CLOCK_PORT_INDEX_AUDIO;
}
if(mAdecChn >= 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> &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; i++)
{
pTrackInfo = new TrackInfo(TrackInfo::MEDIA_TRACK_TYPE_VIDEO,
"Video"+std::to_string(i), i, DemuxMediaInfo);;
trackInfo.push_back(*pTrackInfo);
delete pTrackInfo;
}
for(i=0; i<DemuxMediaInfo.mAudioNum; i++)
{
pTrackInfo = new TrackInfo(TrackInfo::MEDIA_TRACK_TYPE_AUDIO,
(const char*)DemuxMediaInfo.mAudioStreamInfo[i].strLang, i, DemuxMediaInfo);
trackInfo.push_back(*pTrackInfo);
delete pTrackInfo;
}
for(i=0; i<DemuxMediaInfo.mSubtitleNum; i++)
{
pTrackInfo = new TrackInfo(TrackInfo::MEDIA_TRACK_TYPE_TIMEDTEXT,
(const char*)DemuxMediaInfo.mSubtitleStreamInfo[i].strLang, i, DemuxMediaInfo);
trackInfo.push_back(*pTrackInfo);
delete pTrackInfo;
}
}
void EyeseePlayer::addTimedTextSource(std::string path, std::string mimeType)
{
if (!availableMimeTypeForExternalSource(mimeType))
{
aloge("Illegal mimeType for timed text source: %s", mimeType.c_str());
return;
}
int fd = open(path.c_str(), O_RDONLY);
if (fd < 0)
{
aloge("Failed to open file %s", path.c_str());
return;
}
addTimedTextSource(fd, mimeType);
close(fd);
}
void EyeseePlayer::addTimedTextSource(int fd, string mimeType)
{
addTimedTextSource(fd, 0, 0x7ffffffffffffffL, mimeType);
}
void EyeseePlayer::addTimedTextSource(int fd, int64_t offset, int64_t length, string mimeType)
{
if (!availableMimeTypeForExternalSource(mimeType))
{
aloge("Illegal mimeType for timed text source: %s", mimeType.c_str());
return;
}
alogw("unsupported temporary");
}
void EyeseePlayer::selectTrack(int index)
{
selectOrDeselectTrack(index, true /* select */);
}
void EyeseePlayer::deselectTrack(int index)
{
selectOrDeselectTrack(index, false /* select */);
}
void EyeseePlayer::selectOrDeselectTrack(int index, bool select)
{
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;
}
if (select)
{
if (index < DemuxMediaInfo.mVideoNum)
{
AW_MPI_DEMUX_SelectVideoStream(mDmxChn, index);
}
else if (index >= 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<CMediaMemory>* 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<const CMediaMemory>(*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;
}
};