/* * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * 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. */ #include "player_impl.h" #include #include #include #include #include "unistd.h" #include "securec.h" #include "format_type.h" #include "hi_liteplayer_err.h" #include "hi_liteplayer.h" #include "player_define.h" #include "media_log.h" extern "C" { #include "codec_interface.h" } using namespace std; using OHOS::Media::AdapterStreamCallback; namespace OHOS { namespace Media { const int32_t INVALID_MEDIA_POSITION = -1; const int32_t DEFAULT_REWIND_TIME = 0; const int32_t IDLE_QUEQUE_SLEEP_TIME_US = 5000; const float MAX_MEDIA_VOLUME = 300.0f; const int32_t POS_NOTIFY_INTERVAL_MS = 300; #define CHECK_FAILED_PRINT(value, target, printfString) \ do { \ if ((value) != (target)) { \ MEDIA_ERR_LOG("%s", printfString ? printfString : " "); \ } \ } while (0) #define CHECK_FAILED_RETURN(value, target, ret, printfString) \ do { \ if ((value) != (target)) { \ MEDIA_ERR_LOG("%s, ret:%d", printfString ? printfString : " ", ret); \ return ret; \ } \ } while (0) #define CHK_NULL_RETURN(ptr) \ do { \ if (ptr == nullptr) { \ MEDIA_ERR_LOG("ptr null"); \ return -1; \ } \ } while (0) PlayerImpl::PlayerImpl() : player_(nullptr), speed_(1.0), playerControlState_(PLAY_STATUS_IDLE), isSingleLoop_(false), currentPosition_(0), rewindPosition_(INVALID_MEDIA_POSITION), surface_(nullptr), currentState_(PLAYER_IDLE), rewindMode_(PLAYER_SEEK_PREVIOUS_SYNC), currentRewindMode_(PLAYER_SEEK_PREVIOUS_SYNC), audioStreamType_(0), callback_(nullptr), inited_ (false), released_(false), isStreamSource_(false), bufferSource_(nullptr), streamCallback_(nullptr), pauseAfterPlay_(false), extraRewind_(false) { (void)memset_s(&formatFileInfo_, sizeof(formatFileInfo_), 0, sizeof(FormatFileInfo)); formatFileInfo_.s32UsedVideoStreamIndex = -1; formatFileInfo_.s32UsedAudioStreamIndex = -1; formatFileInfo_.s64Duration = -1; buffer_.idx = -1; buffer_.flag = 0; buffer_.offset = 0; buffer_.size = 0; buffer_.timestamp = 0; (void)memset_s(&mediaAttr_, sizeof(mediaAttr_), 0, sizeof(PlayerControlStreamAttr)); } int32_t PlayerImpl::Init(void) { if (inited_ == true) { return 0; } int ret = CodecInit(); if (ret != 0) { MEDIA_ERR_LOG("PlayerImpl::Init CodecInit err\n"); return ret; } if (memset_s(&buffer_, sizeof(QueBuffer), 0, sizeof(QueBuffer)) != EOK) { MEDIA_ERR_LOG("PlayerImpl::Init memset err\n"); } buffer_.idx = -1; inited_ = true; MEDIA_INFO_LOG("process success"); return 0; } int32_t PlayerImpl::DeInit(void) { if (inited_ != true) { return 0; } if (released_ == false) { Release(); } inited_ = false; return 0; } PlayerImpl::~PlayerImpl() { DeInit(); player_ = nullptr; MEDIA_INFO_LOG("~PlayerImpl process"); } int32_t PlayerImpl::SetSource(const Source &source) { Init(); std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ != PLAYER_IDLE) { MEDIA_ERR_LOG("failed, current state is:%u", currentState_); return -1; } SourceType sType = source.GetSourceType(); if (sType == SourceType::SOURCE_TYPE_FD) { MEDIA_ERR_LOG("not support fdSource now"); return -1; } GetPlayer(); CHK_NULL_RETURN(player_); int32_t ret = -1; if (sType == SourceType::SOURCE_TYPE_URI) { ret = SetUriSource(source); } else if (sType == SourceType::SOURCE_TYPE_STREAM) { ret = SetStreamSource(source); } else { MEDIA_ERR_LOG("SetSource failed, source type is %d", static_cast(sType)); } if (ret != 0) { ResetInner(); } return ret; } static void ShowFileInfo(const FormatFileInfo *fileInfo) { for (int i = 0; i < HI_DEMUXER_RESOLUTION_CNT; i++) { const StreamResolution *resolution = &fileInfo->stSteamResolution[i]; if (resolution->u32Width == 0 || resolution->u32Height == 0) { break; } MEDIA_INFO_LOG("video[%d],w=%u,h=%u,index=%d ", i, resolution->u32Width, resolution->u32Height, resolution->s32VideoStreamIndex); } MEDIA_INFO_LOG("audio channel_cnt=%u,sampleRate=%u,AudioStreamIndex=%d videoIndex:%d", fileInfo->u32AudioChannelCnt, fileInfo->u32SampleRate, fileInfo->s32UsedAudioStreamIndex, fileInfo->s32UsedVideoStreamIndex); } void PlayerImpl::UpdateState(PlayerImpl *curPlayer, PlayerStatus state) { if (curPlayer == nullptr) { return; } curPlayer->playerControlState_ = state; MEDIA_INFO_LOG("player UpdateState, state:%d", state); } void PlayerImpl::PlayerControlEventCb(void* pPlayer, PlayerControlEvent enEvent, const void* pData) { PlayerControlError subErr = PLAYERCONTROL_ERROR_BUTT; PlayerImpl *curPlayer = (PlayerImpl *)pPlayer; if (curPlayer == nullptr) { MEDIA_ERR_LOG("the handle is error"); return; } switch (enEvent) { case PLAYERCONTROL_EVENT_STATE_CHANGED: if (pData == nullptr) { return; } curPlayer->UpdateState(curPlayer, *reinterpret_cast(pData)); break; case PLAYERCONTROL_EVENT_EOF: MEDIA_INFO_LOG("end of file"); curPlayer->NotifyPlaybackComplete(curPlayer); break; case PLAYERCONTROL_EVENT_SOF: MEDIA_INFO_LOG("start of file"); break; case PLAYERCONTROL_EVENT_ERROR: if (pData == nullptr) { return; } subErr = *reinterpret_cast(pData); MEDIA_ERR_LOG("error: %d", subErr); if (curPlayer->callback_ != nullptr) { curPlayer->callback_->OnError(0, subErr); } break; case PLAYERCONTROL_EVENT_PROGRESS: if (pData == nullptr) { return; } curPlayer->currentPosition_ = *reinterpret_cast(pData); break; case PLAYERCONTROL_EVENT_SEEK_END: if (pData == nullptr) { return; } MEDIA_INFO_LOG("seek action end, time is %lld", *reinterpret_cast(pData)); curPlayer->NotifySeekComplete(curPlayer, *reinterpret_cast(pData)); break; case PLAYERCONTROL_FIRST_VIDEO_FRAME: MEDIA_INFO_LOG("render FirstVideoFrame"); if (curPlayer->pauseAfterPlay_) { curPlayer->player_->Pause(); } break; case PLAYERCONTROL_FIRST_AUDIO_FRAME: if (curPlayer->pauseAfterPlay_ && curPlayer->formatFileInfo_.s32UsedVideoStreamIndex == -1) { curPlayer->player_->Pause(); } break; default: break; } } void PlayerImpl::ReportVideoSizeChange(void) { for (int i = 0; i < HI_DEMUXER_RESOLUTION_CNT; i++) { if (formatFileInfo_.stSteamResolution[i].s32VideoStreamIndex == formatFileInfo_.s32UsedVideoStreamIndex) { if (callback_ != nullptr) { callback_->OnVideoSizeChanged(formatFileInfo_.stSteamResolution[i].u32Width, formatFileInfo_.stSteamResolution[i].u32Height); } break; } } } int32_t PlayerImpl::Prepare() { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); CHK_NULL_RETURN(player_); if (currentState_ == PLAYER_PREPARED) { MEDIA_ERR_LOG("have operated prepare before"); return 0; } if (currentState_ != PLAYER_INITIALIZED) { MEDIA_ERR_LOG("Can not Prepare, currentState_ is %u", currentState_); return -1; } PlayerCtrlCallbackParam param; param.player = this; param.callbackFun = PlayerControlEventCb; int ret = player_->RegCallback(param); if (ret != 0) { MEDIA_ERR_LOG("RegCallback exec failed "); return -1; } currentState_ = PLAYER_PREPARING; ret = player_->Prepare(); if (ret != 0) { MEDIA_ERR_LOG("Prepare exec failed"); currentState_ = PLAYER_INITIALIZED; return -1; } currentState_ = PLAYER_PREPARED; (void)player_->SetAudioStreamType(audioStreamType_); ret = player_->GetFileInfo(formatFileInfo_); if (ret != 0) { MEDIA_ERR_LOG("GetFileInfo failed"); return ret; } ShowFileInfo(&formatFileInfo_); if (formatFileInfo_.s32UsedVideoStreamIndex == -1) { MEDIA_INFO_LOG("process out"); return 0; } /* report video solution */ ReportVideoSizeChange(); MEDIA_INFO_LOG("process out"); return 0; } int32_t PlayerImpl::SetMediaStream(void) { int32_t ret; mediaAttr_.s32VidStreamId = formatFileInfo_.s32UsedVideoStreamIndex; mediaAttr_.s32AudStreamId = formatFileInfo_.s32UsedAudioStreamIndex; ret = player_->SetMedia(mediaAttr_); if (ret != 0) { MEDIA_ERR_LOG("SetMedia exec failed"); return ret; } for (int i = 0; i < HI_DEMUXER_RESOLUTION_CNT; i++) { StreamResolution *resolution = &formatFileInfo_.stSteamResolution[i]; if (resolution->s32VideoStreamIndex == mediaAttr_.s32VidStreamId) { MEDIA_INFO_LOG("used video w=%u,h=%u,index=%d", resolution->u32Width, resolution->u32Height, mediaAttr_.s32VidStreamId); break; } } return 0; } int32_t PlayerImpl::Play() { std::lock_guard valueLock(lock_); int ret; MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); CHK_NULL_RETURN(player_); if (currentState_ == PLAYER_STARTED) { MEDIA_INFO_LOG("no need to repeat operation"); return 0; } if (currentState_ != PLAYER_PREPARED && currentState_ != PLAYER_PAUSED) { MEDIA_ERR_LOG("Can not Play, currentState is %u", currentState_); return -1; } if (currentState_ == PLAYER_PAUSED) { goto play; } ret = SetMediaStream(); CHECK_FAILED_RETURN(ret, 0, ret, "SetMeidaStream failed"); play: ret = player_->Play(); if (ret != 0) { MEDIA_ERR_LOG("Play exec failed %x", ret); return -1; } currentState_ = PLAYER_STARTED; MEDIA_INFO_LOG("process out"); return 0; } bool PlayerImpl::IsPlaying() { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, 0, "have released or not create"); bool isPlaying = false; if (player_ != nullptr) { isPlaying = (currentState_ != PLAYER_STARTED) ? false : true; } return isPlaying; } int32_t PlayerImpl::Pause() { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); CHK_NULL_RETURN(player_); if (currentState_ == PLAYER_PAUSED) { MEDIA_ERR_LOG("currentState_ is %d", currentState_); return 0; } if (speed_ != 1.0) { MEDIA_ERR_LOG("failed, currentState_ speed is %f", speed_); return -1; } if (pauseAfterPlay_ && currentState_ == PLAYER_PREPARED) { int32_t ret; ret = SetMediaStream(); CHECK_FAILED_RETURN(ret, 0, ret, "SetMeidaStream failed"); ret = player_->Play(); CHECK_FAILED_RETURN(ret, 0, ret, "Play failed"); currentState_ = PLAYER_PAUSED; return 0; } if (currentState_ != PLAYER_STARTED) { MEDIA_ERR_LOG("Can not Pause, currentState_ is %u", currentState_); return -1; } player_->Pause(); currentState_ = PLAYER_PAUSED; return 0; } int32_t PlayerImpl::Stop() { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ == PLAYER_STOPPED) { return 0; } if ((currentState_ != PLAYER_STARTED) && (currentState_ != PLAYER_PAUSED) && (currentState_ != PLAYER_PLAYBACK_COMPLETE) && (currentState_ != PLAYER_STATE_ERROR)) { MEDIA_INFO_LOG("current state: %u, no need to do stop", currentState_); return -1; } if (player_ != nullptr) { int32_t ret = player_->Stop(); if (ret != 0) { MEDIA_ERR_LOG("Stop failed, ret is %d", ret); } } currentState_ = PLAYER_STOPPED; MEDIA_INFO_LOG("process out"); return 0; } int32_t PlayerImpl::RewindInner(int64_t mSeconds, PlayerSeekMode mode) { MEDIA_INFO_LOG("process in"); CHK_NULL_RETURN(player_); if (mSeconds < DEFAULT_REWIND_TIME) { MEDIA_WARNING_LOG("Attempt to rewind to invalid position %lld", mSeconds); mSeconds = DEFAULT_REWIND_TIME; } int32_t ret; int64_t durationMs = -1; GetDurationInner(durationMs); if ((durationMs > DEFAULT_REWIND_TIME) && (mSeconds > durationMs)) { MEDIA_WARNING_LOG("Attempt to rewind to past end of file, request is %lld, durationMs is %lld", mSeconds, durationMs); return -1; } currentRewindMode_ = mode; if (rewindPosition_ >= DEFAULT_REWIND_TIME) { rewindPosition_ = mSeconds; MEDIA_WARNING_LOG("is deal last rewind time:%lld", mSeconds); return 0; } rewindPosition_ = mSeconds; rewindMode_ = mode; ret = player_->Seek(mSeconds); if (ret != 0) { MEDIA_ERR_LOG("do seek failed, ret is %d", ret); } MEDIA_INFO_LOG("process out"); return ret; } bool PlayerImpl::IsValidRewindMode(PlayerSeekMode mode) { switch (mode) { case PLAYER_SEEK_PREVIOUS_SYNC: case PLAYER_SEEK_NEXT_SYNC: case PLAYER_SEEK_CLOSEST_SYNC: case PLAYER_SEEK_CLOSEST: break; default: MEDIA_ERR_LOG("Unknown rewind mode %d", mode); return false; } return true; } int32_t PlayerImpl::Rewind(int64_t mSeconds, int32_t mode) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ != PLAYER_STARTED && currentState_ != PLAYER_PAUSED && currentState_ != PLAYER_PREPARED) { MEDIA_ERR_LOG("Can not Rewind, currentState_ is %u", currentState_); return -1; } if (speed_ != 1.0) { MEDIA_ERR_LOG("Can not Rewind, currentState_ speed is %f", speed_); return -1; } if (IsValidRewindMode((PlayerSeekMode)mode) != true) { MEDIA_ERR_LOG("Rewind failed, msec is %lld, mode is %d", mSeconds, mode); return -1; } if (isStreamSource_ == true) { MEDIA_ERR_LOG("Failed, streamsource not support Rewind"); return -1; } std::lock_guard rewindLock(rewindLock_); int32_t ret = RewindInner(mSeconds, (PlayerSeekMode)mode); if (ret != 0) { MEDIA_ERR_LOG("ReWind failed, ret is %d", ret); } else { currentPosition_ = mSeconds; extraRewind_ = true; } MEDIA_INFO_LOG("process out"); return ret; } int32_t PlayerImpl::SetVolume(float leftVolume, float rightVolume) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); VolumeAttr attr; CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); CHK_NULL_RETURN(player_); if ((currentState_ != PLAYER_STARTED) && (currentState_ != PLAYER_PAUSED) && (currentState_ != PLAYER_PREPARED) && (currentState_ != PLAYER_INITIALIZED)) { MEDIA_ERR_LOG("SetVolume failed, currentState_ is %u", currentState_); return -1; } if (leftVolume < 0 || leftVolume > MAX_MEDIA_VOLUME || rightVolume < 0 || rightVolume > MAX_MEDIA_VOLUME) { MEDIA_ERR_LOG("SetVolume failed, the volume should be set to a value ranging from 0 to 300"); return -1; } attr.leftVolume = leftVolume; attr.rightVolume = rightVolume; int ret = player_->SetVolume(attr); if (ret != 0) { MEDIA_ERR_LOG("SetVolume failed %x", ret); } MEDIA_INFO_LOG("process out\n"); return ret; } int32_t PlayerImpl::SetSurface(Surface *surface) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if ((currentState_ != PLAYER_PREPARED) && (currentState_ != PLAYER_INITIALIZED)) { MEDIA_ERR_LOG("SetSurface failed, currentState_ is %u", currentState_); return -1; } surface_ = surface; player_->SetSurface(surface); return 0; } bool PlayerImpl::IsSingleLooping() { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, false, "have released or not create"); bool isLoop = (player_ == nullptr) ? false : isSingleLoop_; return isLoop; } int32_t PlayerImpl::GetPlayerState(int32_t &state) { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); state = currentState_; return 0; } int32_t PlayerImpl::GetCurrentPosition(int64_t &position) { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); position = (currentPosition_ >= 0) ? currentPosition_ : 0; return 0; } void PlayerImpl::GetDurationInner(int64_t &durationMs) { durationMs = formatFileInfo_.s64Duration; } int32_t PlayerImpl::GetDuration(int64_t &durationMs) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ == PLAYER_IDLE || currentState_ == PLAYER_INITIALIZED) { durationMs = 0; return 0; } GetDurationInner(durationMs); return 0; } int32_t PlayerImpl::GetVideoWidth(int32_t &videoWidth) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); videoWidth = 0; if (currentState_ != PLAYER_PREPARED && currentState_ != PLAYER_STARTED && currentState_ != PLAYER_PAUSED && currentState_ != PLAYER_STOPPED && currentState_ != PLAYER_PLAYBACK_COMPLETE) { MEDIA_ERR_LOG("Can not GetVideoWidth, currentState_ is %u", currentState_); return -1; } if (formatFileInfo_.s32UsedVideoStreamIndex == -1) { return -1; } for (int i = 0; i < HI_DEMUXER_RESOLUTION_CNT; i++) { if (formatFileInfo_.stSteamResolution[i].s32VideoStreamIndex == formatFileInfo_.s32UsedVideoStreamIndex) { videoWidth = formatFileInfo_.stSteamResolution[i].u32Width; break; } } return 0; } int32_t PlayerImpl::GetVideoHeight(int32_t &videoHeight) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); videoHeight = 0; if (currentState_ != PLAYER_PREPARED && currentState_ != PLAYER_STARTED && currentState_ != PLAYER_PAUSED && currentState_ != PLAYER_STOPPED && currentState_ != PLAYER_PLAYBACK_COMPLETE) { MEDIA_ERR_LOG("Can not GetVideoHeight, currentState_ is %u", currentState_); return -1; } if (formatFileInfo_.s32UsedVideoStreamIndex == -1) { return -1; } for (int i = 0; i < HI_DEMUXER_RESOLUTION_CNT; i++) { if (formatFileInfo_.stSteamResolution[i].s32VideoStreamIndex == formatFileInfo_.s32UsedVideoStreamIndex) { videoHeight = formatFileInfo_.stSteamResolution[i].u32Height; break; } } return 0; } static int32_t PlayerControlCheckTPlayAttr(const float speed, TplayDirect direction) { if ((direction != TPLAY_DIRECT_BACKWARD) && (direction != TPLAY_DIRECT_FORWARD)) { return HI_FAILURE; } if (speed != PLAY_SPEED_2X_FAST && speed != PLAY_SPEED_4X_FAST && speed != PLAY_SPEED_8X_FAST && speed != PLAY_SPEED_16X_FAST && speed != PLAY_SPEED_32X_FAST && speed != PLAY_SPEED_64X_FAST && speed != PLAY_SPEED_128X_FAST) { return HI_FAILURE; } return HI_SUCCESS; } int32_t PlayerImpl::SetPlaybackSpeed(float speed) { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (speed <= 0.f) { return -1; } CHK_NULL_RETURN(player_); if (currentState_ != PLAYER_STARTED) { MEDIA_ERR_LOG("currentState_ is %u", currentState_); return -1; } if (speed == speed_) { return 0; } if ((isStreamSource_ == true) && (speed != 1.0f)) { MEDIA_ERR_LOG("Failed, streamsource not support abnormal speed"); return -1; } if (formatFileInfo_.s32UsedVideoStreamIndex == -1) { MEDIA_ERR_LOG("audio movie not support abnormal speed"); return -1; } if (speed_ > 1 && speed == 1) { // tplay ---> play CHECK_FAILED_PRINT(player_->Play(), 0, "player failed"); } else { // normal/tplay -->tplay TplayAttr tplayAttr; TplayDirect direction = (speed > 0) ? TPLAY_DIRECT_FORWARD : TPLAY_DIRECT_BACKWARD; float speedTmp = (speed > 0) ? speed : -speed; tplayAttr.direction = direction; tplayAttr.speed = speedTmp; if (PlayerControlCheckTPlayAttr(speedTmp, direction) != 0) { MEDIA_ERR_LOG("not support speed:%f", speed); return -1; } CHECK_FAILED_PRINT(player_->TPlay(tplayAttr), 0, "tplayer failed"); } if (speed == 0.f && currentState_ == PLAYER_STARTED) { currentState_ = PLAYER_PAUSED; } else if (speed != 0.f && (currentState_ == PLAYER_PREPARED || currentState_ == PLAYER_PAUSED)) { currentState_ = PLAYER_STARTED; } speed_ = speed; return 0; } int32_t PlayerImpl::GetPlaybackSpeed(float &speed) { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); speed = (currentState_ != PLAYER_PAUSED) ? speed_ : 0; return 0; } int32_t PlayerImpl::SetAudioStreamType(int32_t type) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ != PLAYER_IDLE && currentState_ != PLAYER_INITIALIZED) { MEDIA_ERR_LOG("failed, state %u,type:%d", currentState_, type); return -1; } audioStreamType_ = type; if (player_ != nullptr) { player_->SetAudioStreamType(type); } return 0; } void PlayerImpl::GetAudioStreamType(int32_t &type) { std::lock_guard valueLock(lock_); if (released_) { MEDIA_ERR_LOG("have released or not create"); return; } type = static_cast(audioStreamType_); } void PlayerImpl::ResetInner(void) { isSingleLoop_ = false; if (player_ != nullptr) { if (currentState_ != PLAYER_IDLE && currentState_ != PLAYER_STOPPED) { CHECK_FAILED_PRINT(player_->Stop(), HI_SUCCESS, "stop failed"); } (void)player_->Deinit(); player_.reset(); player_ = nullptr; } if (bufferSource_ != nullptr) { bufferSource_.reset(); bufferSource_ = nullptr; } if (streamCallback_ != nullptr) { streamCallback_.reset(); streamCallback_ = nullptr; } currentState_ = PLAYER_IDLE; currentRewindMode_ = PLAYER_SEEK_PREVIOUS_SYNC; rewindPosition_ = INVALID_MEDIA_POSITION; rewindMode_ = PLAYER_SEEK_PREVIOUS_SYNC; isSingleLoop_ = false; speed_ = 1.0; currentPosition_ = 0; pauseAfterPlay_ = false; extraRewind_ = false; playerControlState_ = PLAY_STATUS_IDLE; isStreamSource_ = false; (void)memset_s(&formatFileInfo_, sizeof(FormatFileInfo), 0, sizeof(FormatFileInfo)); formatFileInfo_.s32UsedVideoStreamIndex = -1; formatFileInfo_.s32UsedAudioStreamIndex = -1; formatFileInfo_.s64Duration = -1; (void)memset_s(&mediaAttr_, sizeof(PlayerControlStreamAttr), 0, sizeof(PlayerControlStreamAttr)); (void)memset_s(&buffer_, sizeof(QueBuffer), 0, sizeof(QueBuffer)); buffer_.idx = -1; } int32_t PlayerImpl::Reset(void) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); if (currentState_ == PLAYER_IDLE) { return 0; } ResetInner(); return 0; } int32_t PlayerImpl::Release() { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); CHECK_FAILED_RETURN(released_, false, 0, "have released or not create"); ResetInner(); if (callback_ != nullptr) { callback_.reset(); callback_ = nullptr; } currentState_ = PLAYER_STATE_ERROR; released_ = true; return 0; } int PlayerImpl::CreatePlayerParamCheck(PlayerControlParam &createParam) { if (createParam.u32PlayPosNotifyIntervalMs < MIN_NOTIFY_INTERVAL_MS && createParam.u32PlayPosNotifyIntervalMs > 0) { MEDIA_ERR_LOG("notify interval small than min value %d", MIN_NOTIFY_INTERVAL_MS); return HI_ERR_PLAYERCONTROL_ILLEGAL_PARAM; } if ((createParam.u32VideoEsBufSize < AV_ESBUF_SIZE_MIN && createParam.u32VideoEsBufSize > 0) || createParam.u32VideoEsBufSize > VIDEO_ESBUF_SIZE_LIMIT) { MEDIA_ERR_LOG("video esbuffer illegal %u", createParam.u32VideoEsBufSize); return HI_ERR_PLAYERCONTROL_ILLEGAL_PARAM; } if ((createParam.u32AudioEsBufSize < AV_ESBUF_SIZE_MIN && createParam.u32AudioEsBufSize > 0) || createParam.u32AudioEsBufSize > AUDIO_ESBUF_SIZE_LIMIT) { MEDIA_ERR_LOG("audio esbuffer illegal %u", createParam.u32VideoEsBufSize); return HI_ERR_PLAYERCONTROL_ILLEGAL_PARAM; } if ((createParam.u32VdecFrameBufCnt < VDEC_VBBUF_CONUT_MIN) && (createParam.u32VdecFrameBufCnt != 0)) { MEDIA_ERR_LOG("VDEC vb buffer count %u small than %d", createParam.u32VdecFrameBufCnt, VDEC_VBBUF_CONUT_MIN); return HI_ERR_PLAYERCONTROL_ILLEGAL_PARAM; } return 0; } int PlayerImpl::GetPlayer() { MEDIA_INFO_LOG("process in"); PlayerControlParam playerParam; if (player_ != nullptr) { return 0; } if (memset_s(&playerParam, sizeof(PlayerControlParam), 0x00, sizeof(playerParam)) != EOK) { MEDIA_INFO_LOG("memset_s playerParam failed"); return -1; } playerParam.u32PlayPosNotifyIntervalMs = POS_NOTIFY_INTERVAL_MS; if (CreatePlayerParamCheck(playerParam) != 0) { MEDIA_ERR_LOG("CreatePlayerParamCheck failed"); return -1; } player_ = std::make_shared(); if (player_ == nullptr || player_.get() == nullptr) { MEDIA_ERR_LOG("playerControl new failed"); return HI_ERR_PLAYERCONTROL_MEM_MALLOC; } if (player_->Init(playerParam) != HI_SUCCESS) { MEDIA_ERR_LOG("playerControl init failed"); return HI_ERR_PLAYERCONTROL_MEM_MALLOC; } currentState_ = PLAYER_INITIALIZED; MEDIA_INFO_LOG("GetPlayer success"); return 0; } void PlayerImpl::SetPlayerCallback(const std::shared_ptr &cb) { std::lock_guard valueLock(lock_); MEDIA_INFO_LOG("process in"); if (released_) { MEDIA_ERR_LOG("have released or not create"); return; } callback_ = cb; } void PlayerImpl::NotifyPlaybackComplete(PlayerImpl *curPlayer) { if (curPlayer == nullptr) { MEDIA_ERR_LOG("curPlayer is nullptr"); return; } if (!isSingleLoop_) { if (curPlayer->formatFileInfo_.s64Duration == -1) { curPlayer->formatFileInfo_.s64Duration = curPlayer->currentPosition_; } curPlayer->currentState_ = PLAYER_PLAYBACK_COMPLETE; MEDIA_INFO_LOG("OnPlayBackComplete, iscallbackNull:%d", (curPlayer->callback_ == nullptr)); if (curPlayer->callback_ != nullptr) { curPlayer->callback_->OnPlaybackComplete(); } return; } std::lock_guard valueLock(curPlayer->rewindLock_); (void)curPlayer->RewindInner(0, PLAYER_SEEK_PREVIOUS_SYNC); curPlayer->currentPosition_ = 0; curPlayer->extraRewind_ = false; } void PlayerImpl::NotifySeekComplete(PlayerImpl *curPlayer, int64_t seekToMs) { std::lock_guard valueLock(curPlayer->rewindLock_); if (curPlayer->rewindPosition_ != -1 && curPlayer->rewindPosition_ != seekToMs) { int64_t seekTime = curPlayer->rewindPosition_; curPlayer->rewindMode_ = PLAYER_SEEK_PREVIOUS_SYNC; curPlayer->rewindPosition_ = -1; curPlayer->RewindInner(seekTime, curPlayer->currentRewindMode_); return; } curPlayer->currentRewindMode_ = curPlayer->rewindMode_ = PLAYER_SEEK_PREVIOUS_SYNC; curPlayer->rewindPosition_ = -1; if (curPlayer->callback_ != nullptr && extraRewind_) { extraRewind_ = false; curPlayer->callback_->OnRewindToComplete(); } } int32_t PlayerImpl::SetLoop(bool loop) { std::lock_guard valueLock(lock_); CHECK_FAILED_RETURN(released_, false, -1, "have released or not create"); CHECK_FAILED_RETURN(isStreamSource_, false, -1, "stream source not support loop player"); if (currentState_ == PLAYER_STOPPED || currentState_ == PLAYER_PLAYBACK_COMPLETE || currentState_ == PLAYER_IDLE) { MEDIA_ERR_LOG("currentState_ is %u", currentState_); return -1; } isSingleLoop_ = loop; return 0; } int32_t PlayerImpl::SetUriSource(const Source &source) { MEDIA_INFO_LOG("process in"); const std::string uri = source.GetSourceUri(); if (uri.empty() || uri.c_str() == nullptr) { MEDIA_ERR_LOG("SetUriSource failed, uri source do not set uri parameter"); return -1; } char filePath[PATH_MAX]; if (realpath(uri.c_str(), filePath) == nullptr) { MEDIA_ERR_LOG("Realpath input file failed"); return -1; } if (access(filePath, R_OK) == -1) { MEDIA_ERR_LOG("No permission to read the file"); return -1; } int32_t ret = player_->SetDataSource(uri.c_str()); if (ret != 0) { MEDIA_ERR_LOG("SetSource failed, ret is %d, uri is %s", ret, uri.c_str()); return ret; } return 0; } AdapterStreamCallback::AdapterStreamCallback(std::shared_ptr &stream, std::shared_ptr &buffer) : streamProcess_(0), isRunning_(false) { streamSource_ = stream; bufferSource_ = buffer; pthread_mutex_init(&mutex_, nullptr); } AdapterStreamCallback::~AdapterStreamCallback(void) { DeInit(); MEDIA_INFO_LOG("process out"); } void *AdapterStreamCallback::IdleBufferProcess(void *arg) { int ret; QueBuffer buffer; BufferInfo info; if (memset_s(&info, sizeof(info), 0x00, sizeof(info)) != EOK) { return nullptr; } AdapterStreamCallback *process = (AdapterStreamCallback*)arg; if (process == nullptr) { return nullptr; } prctl(PR_SET_NAME, "IdlbufProc", 0, 0, 0); MEDIA_INFO_LOG("process start"); while (true) { pthread_mutex_lock(&process->mutex_); if (process->isRunning_ == false) { pthread_mutex_unlock(&process->mutex_); break; } pthread_mutex_unlock(&process->mutex_); if (process->bufferSource_ == nullptr) { MEDIA_ERR_LOG("bufferSource_ null break"); break; } if (process->bufferSource_->GetIdleQueSize() == 0) { usleep(IDLE_QUEQUE_SLEEP_TIME_US); continue; } ret = process->bufferSource_->DequeIdleBuffer(&buffer, 0); if (ret == 0) { process->bufferSource_->GetBufferInfo(buffer.idx, &info); std::shared_ptr stream = process->streamSource_.lock(); if (stream == nullptr) { MEDIA_ERR_LOG("stream not exist break"); break; } stream->OnBufferAvailable(buffer.idx, 0, info.bufLen); } }; pthread_mutex_lock(&process->mutex_); process->isRunning_ = false; pthread_mutex_unlock(&process->mutex_); MEDIA_INFO_LOG("work end"); return nullptr; } int AdapterStreamCallback::Init(void) { MEDIA_INFO_LOG("process in"); pthread_mutex_lock(&mutex_); isRunning_ = true; pthread_mutex_unlock(&mutex_); int32_t ret = pthread_create(&streamProcess_, nullptr, IdleBufferProcess, this); if (ret != 0) { MEDIA_ERR_LOG("pthread_create failed %d", ret); pthread_mutex_lock(&mutex_); isRunning_ = false; pthread_mutex_unlock(&mutex_); return -1; } return 0; } void AdapterStreamCallback::DeInit(void) { MEDIA_INFO_LOG("process in"); pthread_mutex_lock(&mutex_); isRunning_ = false; pthread_mutex_unlock(&mutex_); if (streamProcess_ != 0) { pthread_join(streamProcess_, nullptr); } pthread_mutex_destroy(&mutex_); } uint8_t *AdapterStreamCallback::GetBuffer(size_t index) { BufferInfo info; if (bufferSource_ == nullptr) { MEDIA_ERR_LOG("bufferSource null"); return nullptr; } if (bufferSource_->GetBufferInfo(index, &info) != 0) { MEDIA_ERR_LOG("GetBufferInfo failed"); return nullptr; } return (uint8_t*)info.virAddr; } void AdapterStreamCallback::QueueBuffer(size_t index, size_t offset, size_t size, int64_t timestampUs, uint32_t flags) { QueBuffer buffer; if (bufferSource_ == nullptr) { MEDIA_ERR_LOG("bufferSource null"); return; } buffer.idx = index; buffer.flag = static_cast(flags); buffer.offset = offset; buffer.size = size; buffer.timestamp = timestampUs; if (bufferSource_->QueFilledBuffer(&buffer) != 0) { MEDIA_ERR_LOG("QueFilledBuffer failed"); } } void AdapterStreamCallback::SetParameters(const Format ¶ms) { MEDIA_ERR_LOG("process, not support"); } int32_t PlayerImpl::GetReadableSize(const void *handle) { const PlayerImpl *playImpl = (const PlayerImpl*)handle; CHK_NULL_RETURN(playImpl); if (playImpl->bufferSource_ == nullptr) { MEDIA_ERR_LOG("bufferSource null"); return -1; } return playImpl->bufferSource_->GetFilledQueDataSize(); } int32_t PlayerImpl::ReadDataPro(uint8_t *data, int32_t size, DataFlags &flags) { int readLen; BufferInfo info; if (bufferSource_->GetBufferInfo(buffer_.idx, &info) != 0) { return 0; } /* read all buffer data */ if (buffer_.size <= size) { if (buffer_.size == 0 && buffer_.flag == BUFFER_FLAG_EOS) { buffer_.offset = 0; buffer_.size = info.size; bufferSource_->QueIdleBuffer(&buffer_); buffer_.idx = -1; flags = DATA_FLAG_EOS; return 0; } if (memcpy_s(data, size, (unsigned char*)(info.virAddr) + buffer_.offset, buffer_.size) != EOK) { return -1; } flags = (buffer_.flag == BUFFER_FLAG_EOS) ? DATA_FLAG_EOS : DATA_FLAG_PARTIAL_FRAME; readLen = buffer_.size; buffer_.offset = 0; buffer_.size = info.size; bufferSource_->QueIdleBuffer(&buffer_); buffer_.idx = -1; } else { if (memcpy_s(data, size, (unsigned char*)(info.virAddr) + buffer_.offset, size) != EOK) { return -1; } buffer_.offset += size; buffer_.size -= size; flags = DATA_FLAG_PARTIAL_FRAME; readLen = size; } return readLen; } int32_t PlayerImpl::ReadData(void *handle, uint8_t *data, int32_t size, int32_t timeOutMs, DataFlags *flags) { PlayerImpl *playImpl = (PlayerImpl*)handle; if (playImpl == nullptr || playImpl->bufferSource_ == nullptr) { MEDIA_ERR_LOG("bufferSource null"); return -1; } if (data == nullptr || size < 0 || flags == nullptr) { MEDIA_ERR_LOG("data null or buffer size < 0"); return -1; } if (playImpl->buffer_.idx != -1) { return playImpl->ReadDataPro(data, size, *flags); } if (playImpl->bufferSource_->GetFilledQueSize() <= 0) { return 0; } if (playImpl->bufferSource_->DequeFilledBuffer(&playImpl->buffer_, 0) != 0) { playImpl->buffer_.idx = -1; return 0; } return playImpl->ReadDataPro(data, size, *flags); } int32_t PlayerImpl::SetStreamSource(const Source &source) { MEDIA_INFO_LOG("process in"); isStreamSource_ = true; isSingleLoop_ = false; bufferSource_ = std::make_shared(); if (bufferSource_ == nullptr) { MEDIA_ERR_LOG("new BufferSource failed"); return -1; } bufferSource_->Init(); std::shared_ptr stream = source.GetSourceStream(); if (stream.get() == nullptr) { MEDIA_ERR_LOG("GetSourceStream null"); return -1; } streamCallback_ = std::make_shared(stream, bufferSource_); if (streamCallback_ == nullptr || streamCallback_.get() == nullptr) { MEDIA_ERR_LOG("new AdapterStreamCallback failed"); return -1; } streamCallback_->Init(); stream->SetStreamCallback(streamCallback_); BufferStream sourceTmp; sourceTmp.handle = this; sourceTmp.ReadData = ReadData; sourceTmp.GetReadableSize = GetReadableSize; int32_t ret = player_->SetDataSource(sourceTmp); if (ret != 0) { MEDIA_ERR_LOG("SetDataSource exec failed"); return -1; } return 0; } int32_t PlayerImpl::EnablePauseAfterPlay(bool isPauseAfterPlay) { if (currentState_ != PLAYER_IDLE && currentState_ != PLAYER_INITIALIZED) { MEDIA_ERR_LOG("currentState_ is %u", currentState_); return -1; } if (pauseAfterPlay_ == isPauseAfterPlay) { return 0; } pauseAfterPlay_ = isPauseAfterPlay; if (player_ != NULL) { return player_->Invoke(INVOKE_ENABLE_PAUSE_AFTER_PLAYER, &pauseAfterPlay_); } MEDIA_INFO_LOG("isPauseAfterPlay:%d", isPauseAfterPlay); return 0; } int32_t PlayerImpl::SetParameter(const Format ¶ms) { int32_t value; std::lock_guard valueLock(lock_); if (params.GetIntValue(PAUSE_AFTER_PLAY, value) != true) { MEDIA_ERR_LOG("get pause after play failed"); return -1; } if (value != 0 && value != 1) { MEDIA_ERR_LOG("pause after play flag error:%d", value); return -1; } return EnablePauseAfterPlay(value); } } // namespace Media } // namespace OHOS