/* * Copyright (c) 2020 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #define LOG_NDEBUG 0 #define LOG_TAG "AmlMpPlayerImpl" #include "Aml_MP_PlayerImpl.h" #include #include #include #include #include #include #include #include "AmlPlayerBase.h" #include "utils/Amlsysfsutils.h" #ifdef ANDROID #ifndef __ANDROID_VNDK__ #ifndef __ANDROID_RECOVERY__ #include #include #endif #endif #include #endif #include namespace aml_mp { #define TS_BUFFER_SIZE (2 * 1024 * 1024) #define TEMP_BUFFER_SIZE (188 * 100) #define START_ALL_PENDING (1 << 0) #define START_VIDEO_PENDING (1 << 1) #define START_AUDIO_PENDING (1 << 2) #define START_SUBTITLE_PENDING (1 << 3) #define FAST_PLAY_THRESHOLD 2.0f #define DEFAULT_DEMUX_MEM_SEC_LEVEL AML_MP_DEMUX_MEM_SEC_LEVEL2 #define DEFAULT_DEMUX_MEM_SEC_SIZE (20<<20)//20M #define PIP_DEMUX_MEM_SEC_SIZE (36<<20)//36M #define FCC_DEMUX_MEM_SEC_SIZE (54<<20)//54M /////////////////////////////////////////////////////////////////////////////// #ifdef CONFIG_AMP_SERVER void AmpMpPlayerDumpFile(const char *name, FILE** dump, const uint8_t* data, int32_t len) { if (dump == nullptr) { return; } FILE *dumpFile = *dump; if (!property_get_bool("vendor.media.aml_mp.server.dump", false)) { if (dumpFile != nullptr) { fclose(dumpFile); *dump = nullptr; } return; } if (dumpFile == nullptr) { char saveName[100] = { 0 }; snprintf(saveName, sizeof(saveName), "/data/%s_server.ts", name); dumpFile = fopen(saveName, "wb+"); if (dumpFile == nullptr) { ALOGE("%s open dump ts failed:%s", name, strerror(errno)); return; } } fwrite(data, 1, len, dumpFile); *dump = dumpFile; } #endif AmlMpPlayerImpl::AmlMpPlayerImpl(const Aml_MP_PlayerCreateParams* createParams, int32_t clientId) : mInstanceId(AmlMpPlayerRoster::instance().registerPlayer(this)) , mClientId(clientId) , mCreateParams(*createParams) { snprintf(mName, sizeof(mName), "%s_%p_%d_%d", LOG_TAG, this, mClientId >= 0 ? mClientId : mInstanceId, mInstanceId); AmlMpConfig::instance().init(); #ifdef ANDROID int sdkVersion = ANDROID_PLATFORM_SDK_VERSION; const char* platform = #ifdef __ANDROID_VNDK__ "vendor"; #elif __ANDROID_RECOVERY__ "recovery"; #else "system"; #endif MLOG("sdk:%d, platform:%s, mTsPlayerNonTunnel: %d", sdkVersion, platform, AmlMpConfig::instance().mTsPlayerNonTunnel); #endif #ifdef HAVE_VERSION_INFO MLOGI("%s", getCommitInfo().c_str()); #endif MLOG("drmMode:%s, sourceType:%s, options:%#" PRIx64, mpInputStreamType2Str(createParams->drmMode), mpInputSourceType2Str(createParams->sourceType), createParams->options); memset(&mVideoParams, 0, sizeof(mVideoParams)); mVideoParams.pid = AML_MP_INVALID_PID; mVideoParams.videoCodec = AML_MP_CODEC_UNKNOWN; memset(&mAudioParams, 0, sizeof(mAudioParams)); mAudioParams.pid = AML_MP_INVALID_PID; mAudioParams.audioCodec = AML_MP_CODEC_UNKNOWN; memset(&mSubtitleParams, 0, sizeof(mSubtitleParams)); mSubtitleParams.pid = AML_MP_INVALID_PID; mSubtitleParams.subtitleCodec = AML_MP_CODEC_UNKNOWN; memset(&mADParams, 0, sizeof(mADParams)); mADParams.pid = AML_MP_INVALID_PID; mADParams.audioCodec = AML_MP_CODEC_UNKNOWN; memset(&mIptvCasParams, 0, sizeof(mIptvCasParams)); memset(&mTeletextCtrlParam, 0, sizeof(mTeletextCtrlParam)); mTeletextCtrlParam.event = AML_MP_TT_EVENT_INVALID; memset(&mAudioLanguage, 0, sizeof(mAudioLanguage)); mUserWaitingEcmMode = mWaitingEcmMode = (WaitingEcmMode)AmlMpConfig::instance().mWaitingEcmMode; MLOGI("mWaitingEcmMode:%d", mWaitingEcmMode); mTsBuffer.init(AmlMpConfig::instance().mWriteBufferSize * 1024 * 1024); mWriteBuffer = new AmlMpBuffer(TEMP_BUFFER_SIZE); mWriteBuffer->setRange(0, 0); mZorder = kZorderBase + mInstanceId; mPlayer = AmlPlayerBase::create(&mCreateParams, mInstanceId); // in CAS PIP case we need increase the sec buffer size increaseDmxSecMemSize(); } AmlMpPlayerImpl::~AmlMpPlayerImpl() { MLOG(); #ifdef CONFIG_AMP_SERVER freeBuffs(); #endif if (mState != STATE_IDLE) { MLOG("Waring!! mState is not STATE_IDLE. Force to stop enter."); stop(); MLOG("Force to stop exit."); } // try release mPlayer as it may be retained during the stop phase. mPlayer.clear(); // recover demux sec mem size to default, this value same as DMC_MEM_DEFAULT_SIZE recoverDmxSecMemSize(); /* Set Aspect Mode to NONE & Disable AFD when exit playback */ if (mVideoAFDAspectMode >= 0) { setVideoAFDAspectMode_l(AML_MP_VIDEO_AFD_ASPECT_MODE_NONE); } AmlMpPlayerRoster::instance().unregisterPlayer(mInstanceId); } int AmlMpPlayerImpl::registerEventCallback(Aml_MP_PlayerEventCallback cb, void* userData) { MLOG(); { std::unique_lock _l(mLock); if (mState != STATE_IDLE) { MLOGW("can't registerEventCallback now!"); return -1; } } std::unique_lock _eventLock(mEventLock); mEventCb = cb; mUserData = userData; return 0; } int AmlMpPlayerImpl::setVideoParams(const Aml_MP_VideoParams* params) { std::unique_lock _l(mLock); if (getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) != AML_MP_DECODING_STATE_STOPPED) { MLOGE("video started already!"); return -1; } mVideoParams.pid = params->pid; mVideoParams.videoCodec = params->videoCodec; mVideoParams.width = params->width; mVideoParams.height = params->height; mVideoParams.frameRate = params->frameRate; memcpy(mVideoParams.extraData, params->extraData, sizeof(mVideoParams.extraData)); mVideoParams.extraDataSize = params->extraDataSize; mVideoParams.secureLevel = params->secureLevel; MLOGI("setVideoParams vpid: 0x%x, fmt: %s", params->pid, mpCodecId2Str(params->videoCodec)); #if 1 // This commit commit config the secure level 2. if (mVideoParams.secureLevel == AML_MP_DEMUX_MEM_SEC_NONE && mCreateParams.drmMode != AML_MP_INPUT_STREAM_NORMAL) { mVideoParams.secureLevel = DEFAULT_DEMUX_MEM_SEC_LEVEL; MLOGI("change video secure level to %d", mVideoParams.secureLevel); } #endif return 0; } int AmlMpPlayerImpl::setAudioParams(const Aml_MP_AudioParams* params) { std::unique_lock _l(mLock); if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) != AML_MP_DECODING_STATE_STOPPED) { MLOGE("audio started already!"); return -1; } return setAudioParams_l(params); } int AmlMpPlayerImpl::setAudioParams_l(const Aml_MP_AudioParams* params) { mAudioParams.pid = params->pid; mAudioParams.audioCodec = params->audioCodec; mAudioParams.nChannels = params->nChannels; mAudioParams.nSampleRate = params->nSampleRate; memcpy(mAudioParams.extraData, params->extraData, sizeof(mAudioParams.extraData)); mAudioParams.extraDataSize = params->extraDataSize; mAudioParams.secureLevel = params->secureLevel; MLOGI("setAudioParams apid: 0x%x, fmt: %s", params->pid, mpCodecId2Str(params->audioCodec)); #if 1 // This commit config the secure level 2. if (mAudioParams.secureLevel == AML_MP_DEMUX_MEM_SEC_NONE && mCreateParams.drmMode != AML_MP_INPUT_STREAM_NORMAL) { mAudioParams.secureLevel = DEFAULT_DEMUX_MEM_SEC_LEVEL; MLOGI("change audio secure level to %d", mAudioParams.secureLevel); } #endif return 0; } int AmlMpPlayerImpl::setSubtitleParams(const Aml_MP_SubtitleParams* params) { if (AmlMpConfig::instance().mDisableSubtitle) { MLOGI("subtitle disabled!"); return 0; } std::unique_lock _l(mLock); if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) != AML_MP_DECODING_STATE_STOPPED) { MLOGE("subtitle started already!"); return -1; } return setSubtitleParams_l(params); } int AmlMpPlayerImpl::setSubtitleParams_l(const Aml_MP_SubtitleParams* params) { memcpy(&mSubtitleParams, params, sizeof(Aml_MP_SubtitleParams)); MLOGI("setSubtitleParams spid: 0x%x, channelId:%d, fmt:%s", params->pid, params->channelId, mpCodecId2Str(params->subtitleCodec)); return 0; } int AmlMpPlayerImpl::setADParams(Aml_MP_AudioParams* params) { std::unique_lock _l(mLock); if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) != AML_MP_DECODING_STATE_STOPPED) { MLOGE("AD started already!"); return -1; } mADParams.pid = params->pid; mADParams.audioCodec = params->audioCodec; mADParams.nChannels = params->nChannels; mADParams.nSampleRate = params->nSampleRate; memcpy(mADParams.extraData, params->extraData, sizeof(mADParams.extraData)); mADParams.extraDataSize = params->extraDataSize; mADParams.secureLevel = params->secureLevel; MLOGI("setADParams apid: 0x%x, fmt:%s", params->pid, mpCodecId2Str(params->audioCodec)); #if 1 // This commit config the secure level 2. if (mADParams.secureLevel == AML_MP_DEMUX_MEM_SEC_NONE && mCreateParams.drmMode != AML_MP_INPUT_STREAM_NORMAL) { mADParams.secureLevel = DEFAULT_DEMUX_MEM_SEC_LEVEL; MLOGI("change ad secure level to %d", mADParams.secureLevel); } #endif return 0; } int AmlMpPlayerImpl::setCasSession(AML_MP_CASSESSION casSession) { AML_MP_TRACE(10); std::unique_lock _l(mLock); MLOG(); #ifdef BUILD_AMP_SERVER MLOGE("server interface, not here."); #else sptr casBase = aml_handle_cast(casSession); RETURN_IF(-1, casBase == nullptr); if (casBase->serviceType() < AML_MP_CAS_SERVICE_TYPE_IPTV) { MLOGE("do not support bind DVB caseSession!"); } else if (casBase->serviceType() == AML_MP_CAS_SERVICE_VERIMATRIX_WEB) { MLOGW("verimatrix web casSession don't need bind!"); } else if (casBase->serviceType() == AML_MP_CAS_SERVICE_NAGRA_WEB) { MLOGW("nagra web casSession don't need bind!"); } mCasHandle = casBase; #ifndef __ANDROID_RECOVERY__ casBase->getEcmPids(mEcmPids); #endif mIsStandaloneCas = true; #endif return 0; } int AmlMpPlayerImpl::setIptvCASParams(Aml_MP_CASServiceType serviceType, const Aml_MP_IptvCASParams* params) { std::unique_lock _l(mLock); MLOG(); #ifndef BUILD_AMP_SERVER mCasServiceType = serviceType; mIptvCasParams = *params; #endif return 0; } int AmlMpPlayerImpl::start() { std::unique_lock _l(mLock); MLOG(); return start_l(); } int AmlMpPlayerImpl::start_l() { MLOGI("AmlMpPlayerImpl start_l\n"); if (mState == STATE_IDLE) { if (prepare_l() < 0) { MLOGE("prepare failed!"); return -1; } } if (mState == STATE_PREPARING) { setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_START_PENDING); return 0; } // dvr play case need set secure level to tsplayer if (mVideoParams.pid != AML_MP_INVALID_PID || mCreateParams.options & AML_MP_OPTION_DVR_PLAYBACK) { mPlayer->setVideoParams(&mVideoParams); } if (mAudioParams.pid != AML_MP_INVALID_PID || mCreateParams.options & AML_MP_OPTION_DVR_PLAYBACK) { mPlayer->setAudioParams(&mAudioParams); setAudioCoreParameters_l(); } if (mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { mPlayer->setSubtitleParams(&mSubtitleParams); } int ret = 0; if (mVideoParams.pid != AML_MP_INVALID_PID || mAudioParams.pid != AML_MP_INVALID_PID || mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { ret = mPlayer->start(); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return ret; } } setState_l(STATE_RUNNING); //CHECK: assume start always be success if param exist if (mAudioParams.pid != AML_MP_INVALID_PID) { setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STARTED); } if (mVideoParams.pid != AML_MP_INVALID_PID) { setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_STARTED); } if (mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STARTED); } startADDecoding_l(); MLOGI("<<<< AmlMpPlayerImpl start_l\n"); MLOG("end"); return ret; } int AmlMpPlayerImpl::stop() { std::unique_lock lock(mLock); MLOG(); RETURN_IF(-1, mPlayer == nullptr); return stop_l(lock); } int AmlMpPlayerImpl::stop_l(std::unique_lock& lock, bool clearCasSession) { if (mState == STATE_RUNNING || mState == STATE_PAUSED) { if (mPlayer) { mPlayer->stop(); Aml_MP_AudioParams dummyAudioParam; memset(&dummyAudioParam, 0, sizeof(dummyAudioParam)); dummyAudioParam.pid = AML_MP_INVALID_PID; dummyAudioParam.audioCodec = AML_MP_CODEC_UNKNOWN; mPlayer->setAudioParams(&dummyAudioParam); Aml_MP_AudioParams &dummyADParam = dummyAudioParam; mPlayer->setADParams(&dummyADParam, false); } } // ensure stream stopped if mState isn't running or paused setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STOPPED); setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_STOPPED); setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_STOPPED); setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STOPPED); int ret = resetIfNeeded_l(lock, clearCasSession); MLOG("end"); return ret; } int AmlMpPlayerImpl::pause() { std::unique_lock _l(mLock); MLOG(); return pause_l(); } int AmlMpPlayerImpl::pause_l() { if (mState != STATE_RUNNING) { return 0; } RETURN_IF(-1, mPlayer == nullptr); if (mPlayer->pause() < 0) { return -1; } setState_l(STATE_PAUSED); if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_STARTED) { setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_PAUSED); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_STARTED) { setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_PAUSED); } if (getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) == AML_MP_DECODING_STATE_STARTED) { setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_PAUSED); } if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) == AML_MP_DECODING_STATE_STARTED) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_PAUSED); } return 0; } int AmlMpPlayerImpl::resume() { std::unique_lock _l(mLock); return resume_l(); } int AmlMpPlayerImpl::resume_l() { if (mState != STATE_PAUSED) { return 0; } RETURN_IF(-1, mPlayer == nullptr); int ret = 0; // video state if (getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) == AML_MP_DECODING_STATE_PAUSED) { ret += mPlayer->resumeVideoDecoding(); setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_STARTED); } // audio state if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_PAUSED) { ret += mPlayer->resumeAudioDecoding(); setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STARTED); } else if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_STOPPED && mAudioStoppedInSwitching) { ret += startAudioDecoding_l(); } // ad state if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_PAUSED) { setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_STARTED); } // subtitle state if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) == AML_MP_DECODING_STATE_PAUSED) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STARTED); } if (ret < 0) { return -1; } setState_l(STATE_RUNNING); return 0; } int AmlMpPlayerImpl::flush() { std::unique_lock _l(mLock); MLOG(); RETURN_IF(-1, mPlayer == nullptr); if (mState != STATE_RUNNING && mState != STATE_PAUSED) { MLOGI("State is %s, can't call flush when not play", stateString(mState)); return 0; } int ret; #ifdef CONFIG_AMP_SERVER mCallingFlush = true; #endif ret = mPlayer->flush(); if (ret != AML_MP_ERROR_DEAD_OBJECT) { return ret; } ret = mPlayer->stop(); if (ret < 0) { MLOGI("[%s, %d] stop play fail ret: %d", __FUNCTION__, __LINE__, ret); } if (getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) == AML_MP_DECODING_STATE_STARTED || getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) == AML_MP_DECODING_STATE_PAUSED) { mPlayer->setVideoParams(&mVideoParams); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_STARTED || getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_PAUSED) { mPlayer->setAudioParams(&mAudioParams); setAudioCoreParameters_l(); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_STARTED || getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_PAUSED) { mPlayer->setADParams(&mADParams, true); } if (tryWaitEcm_l()) { setState_l(STATE_PREPARING); setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_START_PENDING); setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_START_PENDING); return ret; } ret = mPlayer->start(); if (ret < 0) { MLOGI("[%s, %d] start play fail ret: %d", __FUNCTION__, __LINE__, ret); } if (mState == STATE_PAUSED) { ret = mPlayer->pause(); } return ret; } // Smooth playback between 0 and 2x speed (0 < speed <= 2), audio will be resample with play speed // I-frmae playback when speed > 2 or speed < 0, audio will not be processed when I-frmae playback int AmlMpPlayerImpl::setPlaybackRate(float rate) { std::unique_lock lock(mLock); MLOG("rate:%f", rate); Aml_MP_VideoDecodeMode newDecodeMode; //newDecodeMode = (mPlaybackRate > FAST_PLAY_THRESHOLD)?AML_MP_VIDEO_DECODE_MODE_IONLY:AML_MP_VIDEO_DECODE_MODE_NONE; if (rate > FAST_PLAY_THRESHOLD || rate < 0) { newDecodeMode = (mCreateParams.sourceType == AML_MP_INPUT_SOURCE_ES_MEMORY) ? AML_MP_VIDEO_DECODE_MODE_IONLY : AML_MP_VIDEO_DECODE_MODE_PAUSE_NEXT; } else { newDecodeMode = AML_MP_VIDEO_DECODE_MODE_NONE; } return setPlaybackRate_l(rate, newDecodeMode, lock); } int AmlMpPlayerImpl::setPlaybackRate2(float rate, Aml_MP_VideoDecodeMode decodeMode) { std::unique_lock lock(mLock); MLOG("rate: %f mode: %d", rate, decodeMode); return setPlaybackRate_l(rate, decodeMode, lock); } int AmlMpPlayerImpl::setPlaybackRate_l(float rate, Aml_MP_VideoDecodeMode decodeMode, std::unique_lock& lock) { int ret = 0; bool decodeModeChanged = false; mPlaybackRate = rate; decodeModeChanged = (decodeMode != mVideoDecodeMode); if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); if (mPlaybackRate == 0.0f) { ret = pause_l(); return ret; } if (mState == STATE_PAUSED) { resume_l(); } if (decodeModeChanged) { switchDecodeMode_l(decodeMode, lock); } ret = mPlayer->setPlaybackRate(rate); } return ret; } int AmlMpPlayerImpl::getPlaybackRate(float* rate) { std::unique_lock _l(mLock); if (rate == nullptr) { return AML_MP_ERROR; } int ret = mPlayer->getPlaybackRate(rate); if (ret != AML_MP_OK) { *rate = mPlaybackRate; } //MLOG("rate: %f, mPlaybackRate: %f", *rate, mPlaybackRate); return ret; } int AmlMpPlayerImpl::switchAudioTrack(const Aml_MP_AudioParams* params) { std::unique_lock _l(mLock); MLOG("new apid: 0x%x, fmt:%s", params->pid, mpCodecId2Str(params->audioCodec)); int ret = -1; setAudioParams_l(params); if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); ret = mPlayer->switchAudioTrack(params); if (ret != AML_MP_ERROR_DEAD_OBJECT) { return ret; } ret = mPlayer->stopAudioDecoding(); setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STOPPED); if (mState == STATE_RUNNING) { ret = startAudioDecoding_l(); } else { mAudioStoppedInSwitching = true; } } return ret; } int AmlMpPlayerImpl::switchSubtitleTrack(const Aml_MP_SubtitleParams* params) { std::unique_lock _l(mLock); MLOG("new spid: 0x%x, channelId:%d, fmt:%s", params->pid, params->channelId, mpCodecId2Str(params->subtitleCodec)); int ret = 0; setSubtitleParams_l(params); if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); ret = mPlayer->switchSubtitleTrack(params); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return -1; } if (mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STARTED); } } return ret; } #ifdef CONFIG_AMP_SERVER void AmlMpPlayerImpl::NotifyEcmData(bool async, int32_t pid, const uint8_t *data, int32_t len) { if (data == nullptr || len <= 0) { return; } Amp_Mp_Player_Notify_EcmData ecmEventData; ecmEventData.async = async; ecmEventData.pid = pid; ecmEventData.data = data; ecmEventData.len = len; notifyListener((Aml_MP_PlayerEventType)AML_MP_PLAYER_EVENT_ECM_NOTIFY, (uint64_t)&ecmEventData); } void AmlMpPlayerImpl::freeBuffs() { if (!mBufPoolHasInit) { return; } if (mWriteThread != 0) { mWriteThreadExit = true; pthread_join(mWriteThread, NULL); mWriteThread = 0; } if (mBufPoolBufs != nullptr) { free(mBufPoolBufs); mBufPoolBufs = nullptr; } if (mBufPoolPtr != nullptr) { munmap(mBufPoolPtr, mBufPoolBufCnt * mBufPoolBufOne); mBufPoolPtr = nullptr; } if (mBufPoolFd >= 0) { close(mBufPoolFd); mBufPoolFd = -1; } if (mBufPoolDataMq != nullptr) { delete mBufPoolDataMq; mBufPoolDataMq = nullptr; } if (mBufPoolFreeMq != nullptr) { delete mBufPoolFreeMq; mBufPoolFreeMq = nullptr; } mBufPoolHasInit = false; } void AmlMpPlayerImpl::setEcmPids(const std::vector& ecmPids) { std::unique_lock lock(mLock); mEcmPids = ecmPids; mWaitingEcmByServer = true; std::string dump; for (auto pid : mEcmPids) { dump += std::to_string(pid) + " "; } MLOGI("client set ecm pids:%s", dump.c_str()); } int32_t AmlMpPlayerImpl::setBuffs(int32_t fd, int32_t bufPoolBufCnt, int32_t bufPoolBufOne, DataQueueMQ *bufPoolDataMq, FreeQueueMQ *bufPoolFreeMq) { std::unique_lock lock(mLock); MLOGI("setbuffs, cnt:%d, size:%d, fd:%d", bufPoolBufCnt, bufPoolBufOne, fd); if (mBufPoolHasInit) { MLOGE("why setbuffs again???"); return -1; } mBufPoolDataMq = bufPoolDataMq; mBufPoolFreeMq = bufPoolFreeMq; BufPoolNode *bufs = (BufPoolNode *)malloc(sizeof(BufPoolNode) * bufPoolBufCnt); if (bufs == nullptr) { freeBuffs(); MLOGE("malloc fail"); return -1; } void* ptr = mmap(NULL, bufPoolBufCnt * bufPoolBufOne, PROT_READ, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { freeBuffs(); return -1; } mBufPoolFd = fd; mBufPoolPtr = ptr; mBufPoolBufCnt = bufPoolBufCnt; mBufPoolBufOne = bufPoolBufOne; mBufPoolBufs = bufs; for (int i = 0; i < mBufPoolBufCnt; i++) { mBufPoolBufs[i].ptr = (uint8_t *)ptr + i * mBufPoolBufOne; mBufPoolBufs[i].size = mBufPoolBufOne; mBufPoolFreeMq->write(&i); MLOGI("set free buf:%d", i); } mBufPoolHasInit = true; if (pthread_create(&mWriteThread, NULL, writeDataThread, this) != 0) { MLOGE("create encoder output thread fail"); freeBuffs(); return -1; } MLOGI("setbuffer ok, fd:%d, cnt:%d, oneSize:%d, ptr:%p this:%p", mBufPoolFd, mBufPoolBufCnt, mBufPoolBufOne, mBufPoolPtr, this); return 0; } void* AmlMpPlayerImpl::writeDataThread(void *arg) { AmlMpPlayerImpl *player = (AmlMpPlayerImpl *)arg; if (player == nullptr) { return nullptr; } char mName[50] = { 0 }; snprintf(mName, sizeof(mName), "%s", player->mName); MLOGI("enter write data thread"); size_t needFlushDataCnt = 0; FILE *dumpFile = nullptr; while (!player->mWriteThreadExit) { if (player->mCallingFlush) { needFlushDataCnt = player->mBufPoolDataMq->availableToRead(); MLOGI("calling flush, need clear buf:%d", needFlushDataCnt); player->mCallingFlush = false; } AmlMpBufPoolDataPacket aidlPkt = {}; //BufPoolDataPacket if (!player->mBufPoolDataMq->read(&aidlPkt)) { usleep(10 * 1000); continue; } if (needFlushDataCnt > 0) { player->mBufPoolFreeMq->write(&aidlPkt.index); needFlushDataCnt--; continue; } uint8_t* ptr = player->mBufPoolBufs[aidlPkt.index].ptr; uint32_t len = aidlPkt.size; uint32_t send = 0; int retry = 0; while (len > 0 && !player->mWriteThreadExit) { int32_t ret = 0; { std::unique_lock lock(player->mLock); if (player->mCallingFlush) { break; } //MLOGI("will write, idx:%d, size:%d, send:%d, left:%d", aidlPkt.index, aidlPkt.size, send, len); if (player->mPlayer != nullptr && player->mState != STATE_STOPPED) { if (aidlPkt.isTsData) { ret = player->writeData_l(lock, ptr + send, len); } else { ret = player->writeEsData((Aml_MP_StreamType)aidlPkt.streamType, ptr + send, len, aidlPkt.pts); } } } if (ret <= 0) { usleep(10 * 1000); if (++retry > 200) { MLOGE("write timeout, maybe player is full or player is null, ret:%d", ret); retry = 0; } continue; } //AmpMpPlayerDumpFile(mName, &dumpFile, ptr + send, len); retry = 0; len -= ret; send += ret; //MLOGI("write ok, idx:%d, size:%d, send:%d, left:%d ret:%d, dump:%p", aidlPkt.index, aidlPkt.size, send, len, ret, dumpFile); } player->mBufPoolFreeMq->write(&aidlPkt.index); } if (dumpFile != nullptr) { fclose(dumpFile); dumpFile = nullptr; } return nullptr; } #endif int AmlMpPlayerImpl::writeData(const uint8_t* buffer, size_t size) { std::unique_lock lock(mLock); RETURN_IF(-1, mPlayer == nullptr); return writeData_l(lock, buffer, size); } int AmlMpPlayerImpl::writeData_l(std::unique_lock& lock, const uint8_t* buffer, size_t size) { int written = 0; bool needBuffering = false; if ((mCasHandle || mWaitingEcmByServer) && mCreateParams.drmMode == AML_MP_INPUT_STREAM_ENCRYPTED && mWaitingEcmMode == kWaitingEcmSynchronous && !mFirstEcmWritten) { size_t ecmOffset = size; size_t ecmSize = 188; //coverity[value_overwrite] ecmOffset = findEcmPacket(buffer, size, mEcmPids, &ecmSize); if (ecmSize > 0) { #ifdef BUILD_AMP_SERVER NotifyEcmData(false, 0, buffer + ecmOffset, ecmSize); #else mCasHandle->processEcm(false, 0, buffer + ecmOffset, ecmSize); #endif mFirstEcmWritten = true; MLOGI("first ECM written, offset:%zu", mTsBuffer.size() + ecmOffset); } else { needBuffering = true; } } if (mState == STATE_PREPARING || needBuffering) { //is waiting for start_delay, writeData into mTsBuffer if (mTsBuffer.space() < size) { MLOGW("mTsBuffer full!"); return -1; } written = mTsBuffer.put(buffer, size); //TODO: check buffer overflow if (mParser != nullptr) { written = mParser->writeData(buffer, size); } } else { //already start, need move data from mTsBuffer to player if (!mTsBuffer.empty() || mWriteBuffer->size() != 0) { if (drainDataFromBuffer_l(lock) != 0) { return -1; } } written = doWriteData_l(buffer, size, lock); } if (written == 0) { written = -1; } if (written > 0) { statisticWriteDataRate_l(written); } return written; } int AmlMpPlayerImpl::drainDataFromBuffer_l(std::unique_lock& lock) { int written = 0; int retry = 0; do { if (mWriteBuffer->size() == 0) { size_t readSize = mTsBuffer.get(mWriteBuffer->base(), mWriteBuffer->capacity()); mWriteBuffer->setRange(0, readSize); } written = doWriteData_l(mWriteBuffer->data(), mWriteBuffer->size(), lock); if (written > 0) { //coverity[overflow_const] mWriteBuffer->setRange(mWriteBuffer->offset()+written, mWriteBuffer->size()-written); } else { if (retry >= 4) { break; } retry++; usleep(50 * 1000); } } while (!mTsBuffer.empty() || mWriteBuffer->size() != 0); if (mTsBuffer.empty() && mWriteBuffer->size() == 0) { MLOGI("writeData from buffer done"); return 0; } return -EAGAIN; } int AmlMpPlayerImpl::doWriteData_l(const uint8_t* buffer, size_t size, std::unique_lock& lock) { int written = 0; if (mCreateParams.drmMode == AML_MP_INPUT_STREAM_ENCRYPTED) { if ((mCasHandle == nullptr && !mWaitingEcmByServer) || mWaitingEcmMode == kWaitingEcmASynchronous) { lock.unlock(); written = mPlayer->writeData(buffer, size); lock.lock(); } else { size_t totalSize = size; size_t ecmOffset = size; size_t ecmSize = 188; int ecmCount = 0; while (size) { //coverity[value_overwrite] ecmOffset = findEcmPacket(buffer, size, mEcmPids, &ecmSize); ecmCount += ecmSize != 0; size_t partialSize = ecmOffset; int ret = 0; int retryCount = 0; while (partialSize) { lock.unlock(); ret = mPlayer->writeData(buffer, partialSize); lock.lock(); if (ret <= 0) { if (written == 0) { goto exit; } usleep(50 * 1000); ++retryCount; if (retryCount%40 == 0) { MLOGI("writeData %d/%zu(%zu), ecmOffset:%zu(%d), return:%d", written, totalSize, size, ecmOffset, ecmCount, ret); } } else { buffer += ret; partialSize -= ret; written += ret; size -= ret; } }; if (ecmSize > 0) { #ifdef BUILD_AMP_SERVER NotifyEcmData(false, 0, buffer, ecmSize); #else mCasHandle->processEcm(false, 0, buffer, ecmSize); #endif buffer += ecmSize; written += ecmSize; size -= ecmSize; } } } } else if (mCreateParams.drmMode == AML_MP_INPUT_STREAM_SECURE_MEMORY) { lock.unlock(); written = mPlayer->writeData(buffer, size); lock.lock(); } else { //normal stream lock.unlock(); written = mPlayer->writeData(buffer, size); lock.lock(); } exit: return written; } int AmlMpPlayerImpl::writeEsData(Aml_MP_StreamType type, const uint8_t* buffer, size_t size, int64_t pts) { MLOGD("[%s_%s] buffer:%p, size:%zu, pts:%#" PRIx64 "(%.3fs)", __FUNCTION__, mpStreamType2Str(type), buffer, size, pts, pts/9e4); //audio isn`t support non-blocking mode, must different threads to write av es //std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->writeEsData(type, buffer, size, pts); } int AmlMpPlayerImpl::getCurrentPts(Aml_MP_StreamType streamType, int64_t* pts) { std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->getCurrentPts(streamType, pts); } int AmlMpPlayerImpl::getFirstPts(Aml_MP_StreamType streamType, int64_t* pts) { std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->getFirstPts(streamType, pts); } int AmlMpPlayerImpl::getBufferStat(Aml_MP_BufferStat* bufferStat) { std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->getBufferStat(bufferStat); } int AmlMpPlayerImpl::setANativeWindow(ANativeWindow* nativeWindow) { AML_MP_UNUSED(nativeWindow); std::unique_lock _l(mLock); #ifdef ANDROID #ifndef __ANDROID_RECOVERY__ MLOGI("setAnativeWindow: %p, mNativewindow: %p", nativeWindow, mNativeWindow.get()); mNativeWindow = nativeWindow; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); mPlayer->setANativeWindow(mNativeWindow.get()); setSidebandIfNeeded_l(); } #endif #endif return 0; } int AmlMpPlayerImpl::setSidebandIfNeeded_l() { #ifdef ANDROID #ifndef __ANDROID_RECOVERY__ if (mNativeWindow == nullptr) { return 0; } if (AmlMpConfig::instance().mTsPlayerNonTunnel || mCreateParams.sourceType == AML_MP_INPUT_SOURCE_ES_MEMORY) { if (AmlMpConfig::instance().mUseVideoTunnel == 1) { if (mNativeWindowHelper.setSidebandNonTunnelMode(mNativeWindow.get(), &mVideoTunnelId) == 0) { MLOGI("allocated video tunnel id:%d", mVideoTunnelId); } } } else { mNativeWindowHelper.setSidebandTunnelMode(mNativeWindow.get()); } #endif #endif return 0; } int AmlMpPlayerImpl::setVideoWindow(int x, int y, int width, int height) { AML_MP_TRACE(10); std::unique_lock _l(mLock); if (width < 0 || height < 0) { MLOGI("Invalid windowsize: %dx%d, return fail", width, height); return -1; } #ifdef ANDROID #ifndef __ANDROID_VNDK__ #ifndef __ANDROID_RECOVERY__ if (mNativeWindow == nullptr) { MLOGI("Nativewindow is null, create it"); mComposerClient = new android::SurfaceComposerClient; mComposerClient->initCheck(); mSurfaceControl = mComposerClient->createSurface(android::String8("AmlMpPlayer"), width, height, android::PIXEL_FORMAT_RGB_565, 0); if (mSurfaceControl->isValid()) { mSurface = mSurfaceControl->getSurface(); android::SurfaceComposerClient::Transaction() .setFlags(mSurfaceControl, android::layer_state_t::eLayerOpaque, android::layer_state_t::eLayerOpaque) .show(mSurfaceControl) .apply(); } mNativeWindow = mSurface; } if (mSurfaceControl != nullptr) { MLOGI("Set video window size: x %d, y %d, width: %d, height: %d", x, y, width, height); auto transcation = android::SurfaceComposerClient::Transaction(); if (x >= 0 && y >= 0) { transcation.setPosition(mSurfaceControl, x, y); } transcation.setSize(mSurfaceControl, width, height); #if ANDROID_PLATFORM_SDK_VERSION >= 31 transcation.setCrop(mSurfaceControl, android::Rect(width, height)); #elif ANDROID_PLATFORM_SDK_VERSION >= 29 transcation.setCrop_legacy(mSurfaceControl, android::Rect(width, height)); #endif transcation.setLayer(mSurfaceControl, mZorder); transcation.apply(); // setVideoWindow is used for create surface now, don't need to call the underlying implementation. return 0; } #endif #endif #endif mVideoWindow = {x, y, width, height}; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); if (mVideoWindow.width >= 0 && mVideoWindow.height >= 0) { mPlayer->setVideoWindow(x, y, width, height); } } return 0; } int AmlMpPlayerImpl::setVolume(float volume) { std::unique_lock _l(mLock); int ret = 0; if (volume < 0) { MLOGI("volume is %f, set to 0.0", volume); volume = 0.0; } mVolume = volume; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); ret = mPlayer->setVolume(volume); } return ret; } int AmlMpPlayerImpl::getVolume(float* volume) { std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->getVolume(volume); } int AmlMpPlayerImpl::showVideo() { MLOG(); std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); mVideoShowState = true; return mPlayer->showVideo(); } int AmlMpPlayerImpl::hideVideo() { MLOG(); std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); mVideoShowState = false; return mPlayer->hideVideo(); } int AmlMpPlayerImpl::showSubtitle() { MLOG(); std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->showSubtitle(); } int AmlMpPlayerImpl::hideSubtitle() { MLOG(); std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->hideSubtitle(); } int AmlMpPlayerImpl::setParameter(Aml_MP_PlayerParameterKey key, void* parameter) { AML_MP_TRACE(10); std::unique_lock lock(mLock); return setParameter_l(key, parameter, lock); } int AmlMpPlayerImpl::setParameter_l(Aml_MP_PlayerParameterKey key, void* parameter, std::unique_lock& lock) { int ret = 0; switch (key) { case AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE: RETURN_IF(-1, parameter == nullptr); mVideoDisplayMode = *(Aml_MP_VideoDisplayMode*)parameter; break; case AML_MP_PLAYER_PARAMETER_BLACK_OUT: RETURN_IF(-1, parameter == nullptr); mBlackOut = *(bool*)parameter?1:0; break; case AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_MODE: { RETURN_IF(-1, parameter == nullptr); Aml_MP_VideoDecodeMode decodeMode = *(Aml_MP_VideoDecodeMode*)parameter; switchDecodeMode_l(decodeMode, lock); break; } case AML_MP_PLAYER_PARAMETER_VIDEO_PTS_OFFSET: RETURN_IF(-1, parameter == nullptr); mVideoPtsOffset = *(int*)parameter; break; case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE: RETURN_IF(-1, parameter == nullptr); mAudioOutputMode = *(Aml_MP_AudioOutputMode*)parameter; break; case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_DEVICE: RETURN_IF(-1, parameter == nullptr); mAudioOutputDevice = *(Aml_MP_AudioOutputDevice*)parameter; break; case AML_MP_PLAYER_PARAMETER_AUDIO_PTS_OFFSET: RETURN_IF(-1, parameter == nullptr); mAudioPtsOffset = *(int*)parameter; break; case AML_MP_PLAYER_PARAMETER_AUDIO_BALANCE: RETURN_IF(-1, parameter == nullptr); mAudioBalance = *(Aml_MP_AudioBalance*)parameter; break; case AML_MP_PLAYER_PARAMETER_AUDIO_MUTE: RETURN_IF(-1, parameter == nullptr); mAudioMute = *(bool*)parameter; break; case AML_MP_PLAYER_PARAMETER_NETWORK_JITTER: RETURN_IF(-1, parameter == nullptr); mNetworkJitter = *(int*)parameter; break; case AML_MP_PLAYER_PARAMETER_AD_STATE: { RETURN_IF(-1, parameter == nullptr); int ADState = *(int*)parameter; if (ADState) { startADDecoding_l(); } else { stopADDecoding_l(lock); } return 0; } case AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL: RETURN_IF(-1, parameter == nullptr); mADMixLevel = *(Aml_MP_ADVolume*)parameter; break; case AML_MP_PLAYER_PARAMETER_WORK_MODE: { mWorkMode = *(Aml_MP_PlayerWorkMode*)parameter; MLOGI("Set work mode: %s", mpPlayerWorkMode2Str(mWorkMode)); } break; case AML_MP_PLAYER_PARAMETER_VIDEO_WINDOW_ZORDER: { mZorder = *(int*)parameter; MLOGI("Set zorder: %d", mZorder); #ifdef ANDROID #ifndef __ANDROID_VNDK__ #ifndef __ANDROID_RECOVERY__ if (mSurfaceControl != nullptr) { auto transcation = android::SurfaceComposerClient::Transaction(); transcation.setLayer(mSurfaceControl, mZorder); transcation.apply(); } #endif #endif #endif } break; case AML_MP_PLAYER_PARAMETER_CREATE_PARAMS: { RETURN_IF(-1, parameter == nullptr); Aml_MP_PlayerCreateParams* createParams = (Aml_MP_PlayerCreateParams*)parameter; size_t checkSize = offsetof(Aml_MP_PlayerCreateParams, reserved); if (memcmp(createParams, &mCreateParams, checkSize)) { mCreateParams = *createParams; mNeedRecreatePlayer = true; } else { mNeedRecreatePlayer = false; } MLOGI("Set mCreateParams drmmode:%s, options:%#" PRIx64 ", mNeedRecreatePlayer:%d", mpInputStreamType2Str(mCreateParams.drmMode), mCreateParams.options, mNeedRecreatePlayer); return 0; } break; case AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID: { RETURN_IF(-1, parameter == nullptr); mVideoTunnelId = *(int*)parameter; } break; case AML_MP_PLAYER_PARAMETER_SURFACE_HANDLE: { RETURN_IF(-1, parameter == nullptr); MLOGI("set surface handle: %p", parameter); mSurfaceHandle = parameter; } break; case AML_MP_PLAYER_PARAMETER_AUDIO_PRESENTATION_ID: { RETURN_IF(-1, parameter == nullptr); mAudioPresentationId = *(int*)parameter; } break; case AML_MP_PLAYER_PARAMETER_USE_TIF: { RETURN_IF(-1, parameter == nullptr); mUseTif = *(bool*)parameter; } break; case AML_MP_PLAYER_PARAMETER_TELETEXT_CONTROL: { RETURN_IF(-1, parameter == nullptr); mTeletextCtrlParam = *(AML_MP_TeletextCtrlParam*)parameter; MLOGW("ttx key: %s", mpPlayerParameterKey2Str(key)); } break; case AML_MP_PLAYER_PARAMETER_SPDIF_PROTECTION: { RETURN_IF(-1, parameter == nullptr); mSPDIFStatus = *(int*)parameter; } break; case AML_MP_PLAYER_PARAMETER_VIDEO_CROP: { Aml_MP_Rect videoCrop = *(Aml_MP_Rect*)parameter; mVideoCrop = videoCrop; MLOGI("set source crop:[%d, %d, %d, %d]", mVideoCrop.left, mVideoCrop.top, mVideoCrop.right, mVideoCrop.bottom); } break; case AML_MP_PLAYER_PARAMETER_VIDEO_ERROR_RECOVERY_MODE: { mVideoErrorRecoveryMode = *(Aml_MP_VideoErrorRecoveryMode*)parameter; MLOGI("Set error recovery mode: %s", mpVideoErrorRecoveryMode2Str(mVideoErrorRecoveryMode)); } break; case AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE: { RETURN_IF(-1, parameter == nullptr); int ret = 0; mVideoAFDAspectMode = *(Aml_MP_VideoAFDAspectMode*)parameter; MLOGI("Set video AFD aspect mode: %s", mpVideoAFDAspectMode2Str(mVideoAFDAspectMode)); if (mState == STATE_RUNNING || mState == STATE_PAUSED) { ret = setVideoAFDAspectMode_l(mVideoAFDAspectMode); } return ret; } break; case AML_MP_PLAYER_PARAMETER_AUDIO_LANGUAGE: { RETURN_IF(-1, parameter == nullptr); mAudioLanguage = *(Aml_MP_AudioLanguage*)parameter; MLOGI("set audio language:[%#x, %#x]", mAudioLanguage.firstLanguage, mAudioLanguage.secondLanguage); break; } case AML_MP_PLAYER_PARAMETER_AUDIO_BLOCK_ALIGN: { RETURN_IF(-1, parameter == nullptr); mAudioBlockAlign = *(int*)parameter; MLOGI("set audio block_align:%d", mAudioBlockAlign); break; } case AML_MP_PLAYER_PARAMETER_AUDIO_PATCH_ADDRESS: { RETURN_IF(-1, parameter == nullptr); mAudioPatchAddress = *(int*)parameter; MLOGI("set audio patch address:%d", mAudioPatchAddress); break; } default: MLOGW("unhandled key: %s", mpPlayerParameterKey2Str(key)); return ret; } if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); ret = mPlayer->setParameter(key, parameter); } return ret; } int AmlMpPlayerImpl::getParameter(Aml_MP_PlayerParameterKey key, void* parameter) { AML_MP_TRACE(10); bool locked = false; //allow call getParameter in event callback. pid_t eventCbTid = mEventCbTid.load(std::memory_order_relaxed); if (eventCbTid == -1 || eventCbTid != gettid()) { mLock.lock(); locked = true; } else { MLOGW("don't acquire lock for inner event cb thread!"); } int ret = -1; if (mPlayer != nullptr) { ret = mPlayer->getParameter(key, parameter); } if (ret != AML_MP_OK) { switch (key) { case AML_MP_PLAYER_PARAMETER_VIDEO_SHOW_STATE: { *static_cast(parameter) = mVideoShowState; ret = AML_MP_OK; break; } case AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID: { *static_cast(parameter) = mVideoTunnelId; ret = AML_MP_OK; break; } case AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE: { *static_cast(parameter) = mVideoAFDAspectMode; ret = AML_MP_OK; break; } default: break; } } if (locked) { mLock.unlock(); } return ret; } int AmlMpPlayerImpl::setAVSyncSource(Aml_MP_AVSyncSource syncSource) { MLOGI("%s ! mSyncSource %d", __FUNCTION__, syncSource); std::unique_lock _l(mLock); mSyncSource = syncSource; return 0; } int AmlMpPlayerImpl::setPcrPid(int pid) { MLOGI("%s ! setPcrPid %d", __FUNCTION__, pid); std::unique_lock _l(mLock); mPcrPid = pid; return 0; } int AmlMpPlayerImpl::startVideoDecoding() { std::unique_lock _l(mLock); return startVideoDecoding_l(); } int AmlMpPlayerImpl::startVideoDecoding_l() { MLOG(); if (mState == STATE_IDLE) { if (prepare_l() < 0) { MLOGE("prepare failed!"); return -1; } } if (mState == STATE_PREPARING) { setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_START_PENDING); return 0; } if (mVideoParams.pid != AML_MP_INVALID_PID) { mPlayer->setVideoParams(&mVideoParams); } int ret = mPlayer->startVideoDecoding(); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return -1; } setState_l(STATE_RUNNING); if (mVideoParams.pid != AML_MP_INVALID_PID) { setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_STARTED); } MLOG("end"); return ret; } int AmlMpPlayerImpl::stopVideoDecoding() { std::unique_lock lock(mLock); MLOG(); RETURN_IF(-1, mPlayer == nullptr); MLOGI("stopVideoDecoding\n"); if (mState == STATE_RUNNING || mState == STATE_PAUSED) { if (mPlayer) { mPlayer->stopVideoDecoding(); } } // ensure stream stopped if mState isn't running or paused setDecodingState_l(AML_MP_STREAM_TYPE_VIDEO, AML_MP_DECODING_STATE_STOPPED); int ret = resetIfNeeded_l(lock); MLOG("end"); return ret; } int AmlMpPlayerImpl::startAudioDecoding() { std::unique_lock _l(mLock); MLOGI("startAudioDecoding\n"); return startAudioDecoding_l(); } int AmlMpPlayerImpl::startAudioDecoding_l() { MLOG(); int ret; if (mState == STATE_IDLE) { if (prepare_l() < 0) { MLOGE("prepare failed!"); return -1; } } if (mState == STATE_PREPARING) { setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_START_PENDING); return 0; } if (mAudioParams.pid == AML_MP_INVALID_PID) { return 0; } if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_STARTED) { resetADCodec_l(false); } mPlayer->setAudioParams(&mAudioParams); setAudioCoreParameters_l(); ret = mPlayer->startAudioDecoding(); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return -1; } setState_l(STATE_RUNNING); setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STARTED); MLOG("end"); return ret; } int AmlMpPlayerImpl::stopAudioDecoding() { std::unique_lock lock(mLock); return stopAudioDecoding_l(lock); } int AmlMpPlayerImpl::stopAudioDecoding_l(std::unique_lock& lock) { MLOG(); int ret; RETURN_IF(-1, mPlayer == nullptr); mAudioPresentationId = -1; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { if (mPlayer) { mPlayer->stopAudioDecoding(); Aml_MP_AudioParams dummyAudioParam; memset(&dummyAudioParam, 0, sizeof(dummyAudioParam)); dummyAudioParam.pid = AML_MP_INVALID_PID; dummyAudioParam.audioCodec = AML_MP_CODEC_UNKNOWN; mPlayer->setAudioParams(&dummyAudioParam); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_STARTED) { resetADCodec_l(true); } } // ensure stream stopped if mState isn't running or paused setDecodingState_l(AML_MP_STREAM_TYPE_AUDIO, AML_MP_DECODING_STATE_STOPPED); mAudioStoppedInSwitching = false; ret = resetIfNeeded_l(lock); MLOG("end"); return ret; } int AmlMpPlayerImpl::startADDecoding() { std::unique_lock _l(mLock); return startADDecoding_l(); } int AmlMpPlayerImpl::startADDecoding_l() { MLOG(); int ret; if (mState == STATE_IDLE) { if (prepare_l() < 0) { MLOGE("prepare failed!"); return -1; } } if (mState == STATE_PREPARING) { setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_START_PENDING); return 0; } if (mADParams.pid == AML_MP_INVALID_PID) { return 0; } if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_STARTED) { resetAudioCodec_l(false); } mPlayer->setADParams(&mADParams, true); ret = mPlayer->startADDecoding(); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return -1; } setState_l(STATE_RUNNING); setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_STARTED); MLOG("end"); return ret; } int AmlMpPlayerImpl::stopADDecoding() { std::unique_lock lock(mLock); return stopADDecoding_l(lock); } int AmlMpPlayerImpl::stopADDecoding_l(std::unique_lock& lock) { MLOG(); RETURN_IF(-1, mPlayer == nullptr); int ret; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { if (mPlayer) { mPlayer->stopADDecoding(); Aml_MP_AudioParams dummyADParam; memset(&dummyADParam, 0, sizeof(dummyADParam)); dummyADParam.pid = AML_MP_INVALID_PID; dummyADParam.audioCodec = AML_MP_CODEC_UNKNOWN; mPlayer->setADParams(&dummyADParam, false); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_STARTED) { resetAudioCodec_l(true); } } // ensure stream stopped if mState isn't running or paused setDecodingState_l(AML_MP_STREAM_TYPE_AD, AML_MP_DECODING_STATE_STOPPED); ret = resetIfNeeded_l(lock); MLOG("end"); return ret; } int AmlMpPlayerImpl::startSubtitleDecoding() { std::unique_lock _l(mLock); return startSubtitleDecoding_l(); } int AmlMpPlayerImpl::startSubtitleDecoding_l() { MLOG(); RETURN_IF(-1, mPlayer == nullptr); if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) == AML_MP_DECODING_STATE_STARTED) { MLOGE("subtitle already started!"); return 0; } if (mState == STATE_IDLE) { if (prepare_l() < 0) { MLOGE("prepare failed!"); return -1; } } if (mState == STATE_PREPARING) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_START_PENDING); return 0; } if (mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { mPlayer->setSubtitleParams(&mSubtitleParams); } int ret = mPlayer->startSubtitleDecoding(); if (ret < 0) { MLOGE("%s failed!", __FUNCTION__); return -1; } setState_l(STATE_RUNNING); if (mSubtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) { setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STARTED); } MLOG("end"); return ret; } int AmlMpPlayerImpl::stopSubtitleDecoding() { std::unique_lock lock(mLock); return stopSubtitleDecoding_l(lock); } int AmlMpPlayerImpl::stopSubtitleDecoding_l(std::unique_lock& lock) { MLOG(); RETURN_IF(-1, mPlayer == nullptr); if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) == AML_MP_DECODING_STATE_STOPPED) { MLOGE("subtitle already stopped!"); return 0; } if (mState == STATE_RUNNING || mState == STATE_PAUSED) { if (mPlayer) { mPlayer->stopSubtitleDecoding(); } } // ensure stream stopped if mState isn't running or paused setDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE, AML_MP_DECODING_STATE_STOPPED); int ret = resetIfNeeded_l(lock); MLOG("end"); return ret; } int AmlMpPlayerImpl::setSubtitleWindow(int x, int y, int width, int height) { std::unique_lock _l(mLock); MLOG("subtitle window:(%d %d %d %d)", x, y, width, height); mSubtitleWindow = {x, y, width, height}; int ret = 0; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { ret = mPlayer->setSubtitleWindow(x, y, width, height); } return ret; } //internal function int AmlMpPlayerImpl::startDescrambling_l() { int ret = -1; if (mCasServiceType == AML_MP_CAS_SERVICE_TYPE_INVALID) { MLOGE("unknown cas type!"); return -1; } #ifndef BUILD_AMP_SERVER #ifndef __ANDROID_RECOVERY__ if (mCasHandle == nullptr) { mCasHandle = AmlCasBase::create(mCasServiceType); } #endif if (mCasHandle == nullptr) { MLOGE("create CAS handle failed!"); return -1; } ret = mCasHandle->startDescrambling(&mIptvCasParams); #ifndef __ANDROID_RECOVERY__ mCasHandle->getEcmPids(mEcmPids); #endif #endif return ret; } //internal function int AmlMpPlayerImpl::stopDescrambling_l() { #ifndef BUILD_AMP_SERVER if (mCasHandle) { mCasHandle->stopDescrambling(); mCasHandle.clear(); } #endif return 0; } /////////////////////////////////////////////////////////////////////////////// const char* AmlMpPlayerImpl::stateString(State state) { switch (state) { case STATE_IDLE: return "STATE_IDLE"; case STATE_PREPARING: return "STATE_PREPARING"; case STATE_PREPARED: return "STATE_PREPARED"; case STATE_RUNNING: return "STATE_RUNNING"; case STATE_PAUSED: return "STATE_PAUSED"; case STATE_STOPPED: return "STATE_STOPPED"; default: break; } return "STATE_IDLE"; } std::string AmlMpPlayerImpl::decodingStateString(uint32_t streamState) { AML_MP_UNUSED(streamState); std::stringstream ss; bool hasValue = false; for (size_t i = 0; i < AML_MP_STREAM_TYPE_NB; ++i) { int value = (mStreamState >> i*kStreamStateBits) & kStreamStateMask; if (value != AML_MP_DECODING_STATE_STOPPED) { if (hasValue) ss << "|"; ss << mpStreamType2Str((Aml_MP_StreamType)i); switch (value) { case AML_MP_DECODING_STATE_START_PENDING: ss << "_START_PENDING"; break; case AML_MP_DECODING_STATE_STARTED: ss << "_STARTED"; break; case AML_MP_DECODING_STATE_PAUSED: ss << "_PAUSED"; break; //coverity[dead_error_begin] default: break; } hasValue = true; } } return ss.str(); } void AmlMpPlayerImpl::setState_l(State state) { if (mState != state) { MLOGI("state: %s -> %s", stateString(mState), stateString(state)); mLastState = mState; mState = state; } } void AmlMpPlayerImpl::setDecodingState_l(Aml_MP_StreamType streamType, int state) { unsigned int offset = streamType * kStreamStateBits; if (offset >= sizeof(mStreamState) * 8) { MLOGE("streamType(%s) is overflow!", mpStreamType2Str(streamType)); return; } mStreamState &= ~(kStreamStateMask<> offset) & kStreamStateMask); } int AmlMpPlayerImpl::prepare_l() { MLOG(); if (mCreateParams.drmMode != AML_MP_INPUT_STREAM_NORMAL) { if (!mIsStandaloneCas) { startDescrambling_l(); } // in trick mode play, ecm may not match ts packets well // if use asynchronous wait ecm mode, // because inject speed is faster than normal play, // so force change to synchronous mode here. if (mVideoDecodeMode == AML_MP_VIDEO_DECODE_MODE_IONLY) { mWaitingEcmMode = kWaitingEcmSynchronous; } else { mWaitingEcmMode = mUserWaitingEcmMode; } } if (mPlayer == nullptr || mNeedRecreatePlayer) { mPlayer.clear(); mPlayer = AmlPlayerBase::create(&mCreateParams, mInstanceId); if (mPlayer == nullptr) { MLOGE("AmlPlayerBase create failed!"); return -1; } } if (mPlayer->initCheck() != AML_MP_OK) { MLOGE("AmlPlayerBase initCheck failed!"); return -1; } mNeedRecreatePlayer = false; //coverity[unsigned_compare] if (mWorkMode >= 0) { MLOGI("mWorkMode: %s", mpPlayerWorkMode2Str(mWorkMode)); mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_WORK_MODE, &mWorkMode); } mPlayer->registerEventCallback([](void* userData, Aml_MP_PlayerEventType event, int64_t param) { AmlMpPlayerImpl* thiz = static_cast(userData); return thiz->notifyListener(event, param); }, this); tryMonitorPidChange_l(); bool ret1 = tryWaitCodecId_l(); bool ret2 = tryWaitEcm_l(); if (ret1 || ret2) { setState_l(STATE_PREPARING); return 0; } applyParameters_l(); setState_l(STATE_PREPARED); return 0; } void AmlMpPlayerImpl::openParser_l() { if (mParser == nullptr) { mParser = new Parser(mCreateParams.demuxId, mCreateParams.sourceType == AML_MP_INPUT_SOURCE_TS_DEMOD, AML_MP_DEMUX_TYPE_HARDWARE, mCreateParams.drmMode == AML_MP_INPUT_STREAM_SECURE_MEMORY); mParser->open(); mParser->selectProgram(mVideoParams.pid, mAudioParams.pid); mParser->setEventCallback([this] (Parser::ProgramEventType event, int param1, int param2, void* data) { return programEventCallback(event, param1, param2, data); }); } } bool AmlMpPlayerImpl::tryWaitEcm_l() { bool isNeedWaitEcm = false; if (mCreateParams.sourceType == AML_MP_INPUT_SOURCE_TS_MEMORY && mCreateParams.drmMode == AML_MP_INPUT_STREAM_ENCRYPTED && (mCasHandle || mWaitingEcmByServer)) { for (size_t i = 0; i < mEcmPids.size(); ++i) { int ecmPid = mEcmPids[i]; if (ecmPid > 0 && ecmPid < AML_MP_INVALID_PID) { isNeedWaitEcm = true; break; } } } if (!isNeedWaitEcm) { return false; } resetDrmVariables_l(); if (mWaitingEcmMode != kWaitingEcmASynchronous) { return false; } openParser_l(); int lastEcmPid = AML_MP_INVALID_PID; for (size_t i = 0; i < mEcmPids.size(); ++i) { int ecmPid = mEcmPids[i]; if (ecmPid <= 0 ||ecmPid >= AML_MP_INVALID_PID) { continue; } if (ecmPid != lastEcmPid) { mParser->removeSectionFilter(ecmPid); mParser->addSectionFilter(ecmPid, [] (int pid, size_t size, const uint8_t* data, void* userData) -> int { AmlMpPlayerImpl* playerImpl = (AmlMpPlayerImpl*)userData; if (playerImpl) { playerImpl->programEventCallback(Parser::ProgramEventType::EVENT_ECM_DATA_PARSED, pid, size, (void*)data); } return 0; }, this, false); lastEcmPid = ecmPid; } } if (lastEcmPid == AML_MP_INVALID_PID) { MLOGE("no valid ecm pid!"); } mPrepareWaitingType |= kPrepareWaitingEcm; return true; } bool AmlMpPlayerImpl::tryWaitCodecId_l() { if (mCreateParams.sourceType != AML_MP_INPUT_SOURCE_ES_MEMORY && ((mVideoParams.videoCodec == AML_MP_CODEC_UNKNOWN && mVideoParams.pid != AML_MP_INVALID_PID) || (mAudioParams.audioCodec == AML_MP_CODEC_UNKNOWN && mAudioParams.pid != AML_MP_INVALID_PID) || (mADParams.audioCodec == AML_MP_CODEC_UNKNOWN && mADParams.pid != AML_MP_INVALID_PID))) { openParser_l(); mParser->parseProgramInfoAsync(); mPrepareWaitingType |= kPrepareWaitingCodecId; return true; } return false; } bool AmlMpPlayerImpl::tryMonitorPidChange_l() { if (mCreateParams.options & AML_MP_OPTION_MONITOR_PID_CHANGE) { openParser_l(); mParser->parseProgramInfoAsync(); return true; } return false; } void AmlMpPlayerImpl::programEventCallback(Parser::ProgramEventType event, int param1, int param2, void* data) { AML_MP_UNUSED(param1); switch (event) { case Parser::ProgramEventType::EVENT_PROGRAM_PARSED: { ProgramInfo* programInfo = (ProgramInfo*)data; MLOGI("programEventCallback: program(programNumber=%d,pid= 0x%x) parsed", programInfo->programNumber, programInfo->pmtPid); programInfo->debugLog(); std::lock_guard _l(mLock); for (auto it : programInfo->videoStreams) { if (it.pid == mVideoParams.pid) { mVideoParams.videoCodec = it.codecId; } } for (auto it : programInfo->audioStreams) { if (it.pid == mAudioParams.pid) { mAudioParams.audioCodec = it.codecId; } } mPrepareWaitingType &= ~kPrepareWaitingCodecId; finishPreparingIfNeeded_l(); break; } case Parser::ProgramEventType::EVENT_AV_PID_CHANGED: { Aml_MP_PlayerEventPidChangeInfo* info = (Aml_MP_PlayerEventPidChangeInfo*)data; MLOGI("programEventCallback: program(programNumber=%d,pid= 0x%x) pidchangeInfo: oldPid: 0x%x --> newPid: 0x%x", info->programNumber, info->programPid, info->oldStreamPid, info->newStreamPid); notifyListener(AML_MP_PLAYER_EVENT_PID_CHANGED, (uint64_t)data); break; } case Parser::ProgramEventType::EVENT_ECM_DATA_PARSED: { MLOGI("programEventCallback: ecmData parsed, size:%d", param2); uint8_t* ecmData = (uint8_t*)data; std::string ecmDataStr; char hex[3]; for (int i = 0; i < param2; i++) { snprintf(hex, sizeof(hex), "%02X", ecmData[i]); ecmDataStr.append(hex); ecmDataStr.append(" "); } MLOGI("programEventCallback: ecmPid: %d, ecmData: size:%d, hexStr:%s", param1, param2, ecmDataStr.c_str()); { std::unique_lock _l(mLock); if ((mCasHandle || mWaitingEcmByServer) && mWaitingEcmMode == kWaitingEcmASynchronous) { #ifdef BUILD_AMP_SERVER NotifyEcmData(true, param1, ecmData, param2); #else mCasHandle->processEcm(true, param1, ecmData, param2); #endif } mPrepareWaitingType &= ~kPrepareWaitingEcm; finishPreparingIfNeeded_l(); } break; } default: break; } } int AmlMpPlayerImpl::finishPreparingIfNeeded_l() { if (mState != STATE_PREPARING || mPrepareWaitingType != kPrepareWaitingNone) { return 0; } bool needPause = (mLastState == STATE_PAUSED); applyParameters_l(); setState_l(STATE_PREPARED); if (getDecodingState_l(AML_MP_STREAM_TYPE_VIDEO) == AML_MP_DECODING_STATE_START_PENDING) { startVideoDecoding_l(); } if (getDecodingState_l(AML_MP_STREAM_TYPE_AUDIO) == AML_MP_DECODING_STATE_START_PENDING) { startAudioDecoding_l(); } if (getDecodingState_l(AML_MP_STREAM_TYPE_SUBTITLE) == AML_MP_DECODING_STATE_START_PENDING) { startSubtitleDecoding_l(); if (mSubtitleParams.subtitleCodec == AML_MP_SUBTITLE_CODEC_TELETEXT && mTeletextCtrlParam.event != AML_MP_TT_EVENT_INVALID) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_TELETEXT_CONTROL, &mTeletextCtrlParam); } } if (getDecodingState_l(AML_MP_STREAM_TYPE_AD) == AML_MP_DECODING_STATE_START_PENDING) { startADDecoding_l(); } if (needPause) { pause_l(); } return 0; } int AmlMpPlayerImpl::resetIfNeeded_l(std::unique_lock& lock, bool clearCasSession) { if (mStreamState == 0) { setState_l(STATE_STOPPED); } else { MLOGI("current decodingState:%s", decodingStateString(mStreamState).c_str()); } if (mState == STATE_STOPPED) { reset_l(lock, clearCasSession); } return 0; } int AmlMpPlayerImpl::reset_l(std::unique_lock& lock, bool clearCasSession) { MLOG(); if (mParser) { lock.unlock(); mParser->close(); lock.lock(); } mParser.clear(); if (!(mCreateParams.options & AML_MP_OPTION_RETAIN_RESOURCE_IN_STOP)) { mPlayer.clear(); } else { MLOGI("retain mPlayer handle!"); } if (!mIsStandaloneCas) { stopDescrambling_l(); } if (clearCasSession) { mIsStandaloneCas = false; #ifndef BUILD_AMP_SERVER mCasHandle.clear(); #endif } resetVariables_l(); setState_l(STATE_IDLE); return 0; } int AmlMpPlayerImpl::applyParameters_l() { MLOG(); if ((mSubtitleWindow.width >= 0) && (mSubtitleWindow.height >= 0)) { mPlayer->setSubtitleWindow(mSubtitleWindow.x, mSubtitleWindow.y, mSubtitleWindow.width, mSubtitleWindow.height); } if (mSurfaceHandle != nullptr) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_SURFACE_HANDLE, mSurfaceHandle); } #ifdef ANDROID #ifndef __ANDROID_RECOVERY__ MLOGI("mNativeWindow:%p", mNativeWindow.get()); if (mNativeWindow != nullptr) { mPlayer->setANativeWindow(mNativeWindow.get()); setSidebandIfNeeded_l(); } #endif #endif if (mVideoWindow.width >= 0 && mVideoWindow.height >= 0) { mPlayer->setVideoWindow(mVideoWindow.x, mVideoWindow.y, mVideoWindow.width, mVideoWindow.height); } if (mVideoTunnelId >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID, &mVideoTunnelId); } if (mSyncSource == AML_MP_AVSYNC_SOURCE_DEFAULT) { mSyncSource = AML_MP_AVSYNC_SOURCE_PCR; } Aml_MP_AVSyncSource tmpSyncSource = mSyncSource; //If the middleware only calls the setparameter(decodeMode) interface during speed playback, //we need to put tsplayerrender in freerun state if (mVideoDecodeMode == AML_MP_VIDEO_DECODE_MODE_IONLY) { tmpSyncSource = AML_MP_AVSYNC_SOURCE_NOSYNC; } else if (mVideoDecodeMode == AML_MP_VIDEO_DECODE_MODE_IONLY_SYNC) { tmpSyncSource = AML_MP_AVSYNC_SOURCE_VIDEO; } mPlayer->setAVSyncSource(tmpSyncSource); if (mSyncSource == AML_MP_AVSYNC_SOURCE_PCR && mPcrPid != AML_MP_INVALID_PID) { mPlayer->setPcrPid(mPcrPid); } mPlayer->setPlaybackRate(mPlaybackRate); if (mVolume >= 0) { mPlayer->setVolume(mVolume); } if (mADVolume >= 0) { mPlayer->setADVolume(mADVolume); } if (mVideoAFDAspectMode >= 0) { setVideoAFDAspectMode_l(mVideoAFDAspectMode); } mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_MODE, &mVideoDecodeMode); //coverity[unsigned_compare] if (mVideoDisplayMode >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE, &mVideoDisplayMode); } if (mBlackOut >= 0) { bool param = (0 == mBlackOut)?false:true; mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_BLACK_OUT, ¶m); } if (mVideoPtsOffset >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_PTS_OFFSET, &mVideoPtsOffset); } //coverity[unsigned_compare] if (mAudioOutputMode >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE, &mAudioOutputMode); } //coverity[unsigned_compare] if (mAudioOutputDevice >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_DEVICE, &mAudioOutputDevice); } if (mAudioPtsOffset >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_PTS_OFFSET, &mAudioPtsOffset); } //coverity[unsigned_compare] if (mAudioBalance >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_BALANCE, &mAudioBalance); } if (mAudioMute >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_MUTE, &mAudioMute); } if (mNetworkJitter >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_NETWORK_JITTER, &mNetworkJitter); } //coverity[unsigned_compare] if (mVideoErrorRecoveryMode >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_ERROR_RECOVERY_MODE, &mVideoErrorRecoveryMode); } if (mADMixLevel.masterVolume >= 0 && mADMixLevel.slaveVolume >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL, &mADMixLevel); } if (mUseTif != -1) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_USE_TIF, &mUseTif); } if (mVideoCrop.right >= 0 && mVideoCrop.bottom >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_VIDEO_CROP, &mVideoCrop); } if (mAudioLanguage.firstLanguage != 0 || mAudioLanguage.secondLanguage != 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_LANGUAGE, &mAudioLanguage); } return 0; } void AmlMpPlayerImpl::setAudioCoreParameters_l() { if (mAudioPresentationId >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_PRESENTATION_ID, &mAudioPresentationId); } if (mSPDIFStatus != -1) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_SPDIF_PROTECTION, &mSPDIFStatus); } if (mAudioBlockAlign > 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_BLOCK_ALIGN, &mAudioBlockAlign); } if (mAudioPatchAddress >= 0) { mPlayer->setParameter(AML_MP_PLAYER_PARAMETER_AUDIO_PATCH_ADDRESS, &mAudioPatchAddress); } } void AmlMpPlayerImpl::notifyListener(Aml_MP_PlayerEventType eventType, int64_t param) { std::unique_lock _l(mEventLock); mEventCbTid = gettid(); if (mEventCb) { mEventCb(mUserData, eventType, param); } else { MLOGW("mEventCb is NULL, eventType: %s, param:%" PRId64, mpPlayerEventType2Str(eventType), param); } mEventCbTid = -1; } int AmlMpPlayerImpl::resetADCodec_l(bool callStart) { int ret = 0; MLOG("callStart:%d", callStart); ret = mPlayer->stopADDecoding(); if (ret < 0) { MLOGW("stopADDecoding failed while resetADCodec"); } if (mADParams.pid != AML_MP_INVALID_PID) { mPlayer->setADParams(&mADParams, true); } if (callStart) { ret = mPlayer->startADDecoding(); } return ret; } int AmlMpPlayerImpl::resetAudioCodec_l(bool callStart) { int ret = 0; MLOG("callStart:%d", callStart); ret = mPlayer->stopAudioDecoding(); if (ret < 0) { MLOGW("stopAudioDecoding failed while resetAudioCodec"); } if (mAudioParams.pid != AML_MP_INVALID_PID) { mPlayer->setAudioParams(&mAudioParams); setAudioCoreParameters_l(); } if (callStart) { ret = mPlayer->startAudioDecoding(); } return ret; } int AmlMpPlayerImpl::switchDecodeMode_l(Aml_MP_VideoDecodeMode decodeMode, std::unique_lock& lock) { int ret = 0; MLOG("decodeMode: %s", mpVideoDecodeMode2Str(decodeMode)); if (mVideoDecodeMode == decodeMode) { MLOGI("Decode mode not change, no need do process"); return 0; } mVideoDecodeMode = decodeMode; if (mState != STATE_RUNNING) { MLOGI("Now not in play, no Need to do process"); return 0; } //Not clear cas session while switch decode mode stop_l(lock, false); //When start video decoding will set work mode to player, no need to set here if (AML_MP_VIDEO_DECODE_MODE_NONE != mVideoDecodeMode) { ret = startVideoDecoding_l(); } else { ret = start_l(); } return ret; } void AmlMpPlayerImpl::statisticWriteDataRate_l(size_t size) { mLastBytesWritten += size; int64_t nowUs = AmlMpEventLooper::GetNowUs(); if (mLastWrittenTimeUs == 0) { mLastWrittenTimeUs = nowUs; } else { int64_t diffUs = nowUs - mLastWrittenTimeUs; if (diffUs > 2 * 1000000ll) { int64_t bitrate = mLastBytesWritten * 1000000 / diffUs; MLOGI("writeData rate:%.2fKB/s", bitrate/1024.0); mLastWrittenTimeUs = nowUs; mLastBytesWritten = 0; collectBuffingInfos_l(); } } } void AmlMpPlayerImpl::collectBuffingInfos_l() { //coverity[var_decl] Aml_MP_BufferStat bufferStat; mPlayer->getBufferStat(&bufferStat); int64_t vpts = 0, apts = 0; mPlayer->getCurrentPts(AML_MP_STREAM_TYPE_VIDEO, &vpts); mPlayer->getCurrentPts(AML_MP_STREAM_TYPE_AUDIO, &apts); if (mVideoParams.pid != AML_MP_INVALID_PID) { MLOGI("Video(%#x) buffer stat:%d/%d, %.2fms, pts:%f", mVideoParams.pid, bufferStat.videoBuffer.dataLen, bufferStat.videoBuffer.size, bufferStat.videoBuffer.bufferedMs*1.0, vpts/9e4); } if (mAudioParams.pid != AML_MP_INVALID_PID) { MLOGI("Audio(%#x) buffer stat:%d/%d, %.2fms, pts:%f", mAudioParams.pid, bufferStat.audioBuffer.dataLen, bufferStat.audioBuffer.size, bufferStat.audioBuffer.bufferedMs*1.0, apts/9e4); } } void AmlMpPlayerImpl::resetVariables_l() { mLastBytesWritten = 0; mLastWrittenTimeUs = 0; mAudioStoppedInSwitching = false; resetDrmVariables_l(); } void AmlMpPlayerImpl::resetDrmVariables_l() { mFirstEcmWritten = false; mTsBuffer.reset(); mWriteBuffer->setRange(0, 0); } int AmlMpPlayerImpl::getDecodingState(Aml_MP_StreamType streamType, AML_MP_DecodingState* streamState) { std::unique_lock _l(mLock); *streamState = getDecodingState_l(streamType); return AML_MP_OK; } void AmlMpPlayerImpl::increaseDmxSecMemSize() { MLOGI("supportPIP=%d supportFCC=%d secMemSize=%d isCasProject=%d", AmlMpConfig::instance().mCasPipSupport, AmlMpConfig::instance().mCasFCCSupport, AmlMpConfig::instance().mSecMemSize, AmlMpConfig::instance().mCasType != "none"); if (AmlMpConfig::instance().mCasType == "none") { return ; } if (AmlMpConfig::instance().mCasFCCSupport) { if (AmlMpConfig::instance().mSecMemSize < FCC_DEMUX_MEM_SEC_SIZE) AmlMpConfig::instance().mSecMemSize = FCC_DEMUX_MEM_SEC_SIZE; } else if (AmlMpConfig::instance().mCasPipSupport) { if (AmlMpConfig::instance().mSecMemSize < PIP_DEMUX_MEM_SEC_SIZE) AmlMpConfig::instance().mSecMemSize = PIP_DEMUX_MEM_SEC_SIZE; } else { return ; } char valuebuf[64] = {0}; sprintf(valuebuf, "%d %d", DEFAULT_DEMUX_MEM_SEC_LEVEL>>10, AmlMpConfig::instance().mSecMemSize); int ret = amsysfs_set_sysfs_str("/sys/class/stb/dmc_mem", valuebuf); MLOGI("dmc mem ret=%d level=%d value=%d", ret, DEFAULT_DEMUX_MEM_SEC_LEVEL, AmlMpConfig::instance().mSecMemSize); return; } void AmlMpPlayerImpl::recoverDmxSecMemSize() { if (AmlMpConfig::instance().mCasType != "none" && (AmlMpConfig::instance().mCasFCCSupport || AmlMpConfig::instance().mCasPipSupport)) { char valuebuf[64] = {0}; sprintf(valuebuf, "%d %d", DEFAULT_DEMUX_MEM_SEC_LEVEL>>10, DEFAULT_DEMUX_MEM_SEC_SIZE); int ret = amsysfs_set_sysfs_str("/sys/class/stb/dmc_mem", valuebuf); MLOGI("recover dmc mem ret=%d level=%d value=%d", ret, DEFAULT_DEMUX_MEM_SEC_LEVEL, DEFAULT_DEMUX_MEM_SEC_SIZE); } } int AmlMpPlayerImpl::setADVolume(float volume) { std::unique_lock _l(mLock); int ret = 0; if (volume < 0) { MLOGI("volume is %f, set to 0.0", volume); volume = 0.0; } else if (volume > 100) { MLOGI("volume is %f, set to 100.0", volume); volume = 100.0; } mADVolume = volume; if (mState == STATE_RUNNING || mState == STATE_PAUSED) { RETURN_IF(-1, mPlayer == nullptr); ret = mPlayer->setADVolume(volume); } return ret; } int AmlMpPlayerImpl::getADVolume(float* volume) { std::unique_lock _l(mLock); RETURN_IF(-1, mPlayer == nullptr); return mPlayer->getADVolume(volume); } int AmlMpPlayerImpl::enableAFD_l(bool enable) { MLOGI("[%s] enable: %d", __FUNCTION__, enable); int ret = 0; char enableParam[64] = {0}; if (enable) { RETURN_IF(-1, mPlayer == nullptr); sprintf(enableParam, "%d %d %d", 0, mPlayer->getPlayerId(), 1); } else { sprintf(enableParam, "%d %d %d", 0, 0, 0); } ret = amsysfs_set_sysfs_str("/sys/class/afd_module/enable", enableParam); return ret; } int AmlMpPlayerImpl::setVideoAFDAspectMode_l(Aml_MP_VideoAFDAspectMode aspectMode) { int ret = 0; char aspectModeParam[64] = {0}; if (aspectMode >= AML_MP_VIDEO_AFD_ASPECT_MODE_AUTO && aspectMode < AML_MP_VIDEO_AFD_ASPECT_MODE_MAX) { ret = enableAFD_l(true); sprintf(aspectModeParam, "%d %d", 0, aspectMode); } else { MLOGE("[%s] Invalid aspect mode: %d", __FUNCTION__, aspectMode); ret = enableAFD_l(false); sprintf(aspectModeParam, "%d %d", 0, AML_MP_VIDEO_AFD_ASPECT_MODE_NONE); } ret += amsysfs_set_sysfs_str("/sys/class/afd_module/aspect_mode", aspectModeParam); return ret; } /////////////////////////////////////////////////////////////////////////////// }