/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2019. All rights reserved. * Description: bootvideo player */ #include "BootvideoPlayer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BootvideoConfiger.h" #include "BootvideoDftevent.h" #undef LOG_TAG #define LOG_TAG "BootVideo" namespace android { using std::string; // player state control Mutex g_mtxPlayerCtr; Condition g_mCdtPlayerCtr; // client msg control Mutex g_mtxClientCtr; Condition g_mCdtClientCtr; BootvideoClient::BootvideoClient() : isPrepared(false), isFirstFrame(false), isComplete(false), isError(false), isForceStop(false) { } BootvideoClient::~BootvideoClient() { } bool BootvideoClient::WaitForPrepared() const { Mutex::Autolock autoLock(g_mtxClientCtr); while (!isPrepared) { if (isError || isForceStop) { break; } g_mCdtClientCtr.wait(g_mtxClientCtr); } if (isPrepared) { return true; } return false; } bool BootvideoClient::WaitForFirstFrame() const { Mutex::Autolock autoLock(g_mtxClientCtr); while (!isFirstFrame) { if (isError || isForceStop) { break; } g_mCdtClientCtr.wait(g_mtxClientCtr); } if (isFirstFrame) { return true; } return false; } bool BootvideoClient::IsComplete() const { return isComplete; } bool BootvideoClient::IsError() const { return isError; } void BootvideoClient::ForceStop() { Mutex::Autolock autoLock(g_mtxClientCtr); isForceStop = true; g_mCdtClientCtr.signal(); } void BootvideoClient::notify(int msg, int ext1 __unused, int ext2 __unused, const Parcel *obj __unused) { ALOGD("BootvideoClient notify: msg = %d, ext1 = %d", msg, ext1); Mutex::Autolock autoLock(g_mtxClientCtr); if (msg == MEDIA_ERROR) { // media error, msg is 100 isError = true; g_mCdtClientCtr.signal(); } if (msg == MEDIA_PREPARED) { // media preared suc, msg is 1 isPrepared = true; g_mCdtClientCtr.signal(); } if (msg == MEDIA_PLAYBACK_COMPLETE) { // media play complete, msg is 2 isComplete = true; g_mCdtClientCtr.signal(); } if (msg == MEDIA_INFO) { // media info, msg is 200 switch (ext1) { case MEDIA_INFO_RENDERING_START: // first video frame, ext1 is 3 case MEDIA_INFO_FIRST_AUDIO_FRAME: // fisrt audio frame, ext1 is 5011 ALOGD("BootvideoClient notify: first video or audio frame"); isFirstFrame = true; g_mCdtClientCtr.signal(); break; case MEDIA_INFO_NOT_SUPPORT: // player not support, ext1 is 1004 ALOGE("BootvideoClient notify: player not support"); isError = true; g_mCdtClientCtr.signal(); break; case MEDIA_INFO_PLAY_VIDEO_ERROR: // Video streaming abnormal, ext1 is 805 ALOGE("BootvideoClient notify: video can not be played"); isError = true; g_mCdtClientCtr.signal(); break; case MEDIA_INFO_PLAY_AUDIO_ERROR: // Audio streaming abnormal, ext1 is 804 ALOGD("BootvideoClient notify: audio can not be played"); break; default: break; } } } BootvideoPlayer::BootvideoPlayer() : fd(-1), client(nullptr), player(nullptr) { sp proc(ProcessState::self()); ProcessState::self()->startThreadPool(); } BootvideoPlayer::~BootvideoPlayer() { StopPlay(); } bool BootvideoPlayer::IsPlayEnd() const { if (client == nullptr) { ALOGE("IsPlayEnd: video client is NULL"); return false; } return client->IsComplete(); } bool BootvideoPlayer::IsPlayFail() const { if (client == nullptr) { ALOGE("IsPlayFail: video client is NULL"); return false; } return client->IsError(); } // set player volume, the volume range is 0 to 100 bool BootvideoPlayer::SetVolume(int mute, int volume) const { const float percentConvert = 100.0; // IMediaPlayer volume convert if (player == nullptr) { ALOGE("setVolume: video player is NULL"); return false; } if (mute) { volume = 0; // if mute state, set player volume 0 ALOGD("setVolume: set video mute state"); } float percentVol = volume / percentConvert; if (player->setVolume(percentVol, percentVol) == NO_ERROR) { ALOGD("setVolume: set video volume %f is success", percentVol); return true; } else { ALOGD("setVolume: set video volume %f is failure", percentVol); return false; } } bool BootvideoPlayer::SetDataSource(std::string path) { if (player == nullptr) { ALOGE("SetDataSource: video player is NULL"); return false; } char trustPath[PATH_MAX] = {0}; this->bootvideoPath = path; if (realpath(path.c_str(), trustPath) == NULL) { BootvideoDfteventReport(E_955050800, "SetDataSource", "StartPlayBootvideo", path); ALOGE("path is not canonical %s", path.c_str()); return false; } fd = open(trustPath, O_RDONLY); if (fd == -1) { switch (errno) { case ENOENT: ALOGE("SetDataSource: open %s failure, no such file or directory", trustPath); break; case EACCES: ALOGE("SetDataSource: open %s failure, no has ermission denied", trustPath); break; default: ALOGE("SetDataSource: open %s failure, err=%d", trustPath, errno); break; } BootvideoDfteventReport(E_955050800, "SetDataSource", "StartPlayBootvideo", path); return false; } ALOGD("BootvideoPlayer: path %s\n", trustPath); if (player->setDataSource(fd, 0, 0x7fffffffffLL) == NO_ERROR) { ALOGD("SetDataSource: set video path is success"); return true; } else { BootvideoDfteventReport(E_955050801, "SetDataSource", "StartPlayBootvideo", path); ALOGD("SetDataSource: set video path is failure"); return false; } } bool BootvideoPlayer::SetSideBand(const sp& bufferProducer) const { if (player == nullptr) { ALOGE("SetSideBand: video player is NULL"); return false; } if (bufferProducer == nullptr) { ALOGE("SetSideBand: bufferProducer is NULL"); return false; } int ret = player->setVideoSurfaceTexture(bufferProducer); if (ret == NO_ERROR) { ALOGD("SetSideBand: set video surface texture is success"); return true; } else { ALOGD("SetSideBand: set video surface texture is failure(%d)", ret); return false; } } bool BootvideoPlayer::GetPlayTimeInfo(int& currentMsec, int& durationMsec) const { if (player == nullptr) { ALOGE("GetPlayTimeInfo: video player is NULL"); return false; } int tempCurrent = -1; int tempDuration = -1; player->getCurrentPosition(&tempCurrent); player->getDuration(&tempDuration); if (tempCurrent < 0 || tempDuration < 0) { ALOGE("GetPlayTimeInfo: msec is error"); return false; } else { // unit is ms currentMsec = tempCurrent; durationMsec = tempDuration; return true; } } bool BootvideoPlayer::InitPlay() { sp sm = nullptr; sp binder = nullptr; sp service = nullptr; const int checkServiceCount = 5; // try to get service 5 count const int checkServiceDelay = 10000; // delay is 10ms for (int retry = 0; retry < checkServiceCount; retry++) { if (sm == nullptr) { sm = defaultServiceManager(); } if (sm == nullptr) { ALOGD("InitPlay: IServiceManager is NULL, retry is %d", retry); usleep(checkServiceDelay); continue; } if (binder == nullptr) { binder = sm->getService(String16("media.player")); } if (binder == nullptr) { ALOGD("InitPlay: IBinder is NULL, retry is %d", retry); usleep(checkServiceDelay); continue; } else { service = interface_cast(binder); break; } } if (service == nullptr) { ALOGE("InitPlay: IMediaPlayerService is NULL"); return false; } else { ALOGE("InitPlay: IMediaPlayerService is success"); } client = new BootvideoClient(); player = service->create(client, AUDIO_SESSION_ALLOCATE); if (player == nullptr) { ALOGE("InitPlay: player is NULL"); return false; } return true; } bool BootvideoPlayer::StartPlay(int volume) { if (client == nullptr) { ALOGE("StartPlay: video client is NULL"); return false; } if (player == nullptr) { ALOGE("StartPlay: video player is NULL"); return false; } if (player->prepareAsync() != NO_ERROR) { BootvideoDfteventReport(E_955050801, "prepareAsync", "StartPlay", this->bootvideoPath); ALOGE("StartPlay: video player prepareAsync failure"); return false; } if (!client->WaitForPrepared()) { BootvideoDfteventReport(E_955050801, "WaitForPrepared", "StartPlay", this->bootvideoPath); ALOGE("StartPlay: Wait preparing has error"); return false; } SetVolume(0, volume); // init player volume and Ban on mute if (player->start() != NO_ERROR) { BootvideoDfteventReport(E_955050801, "start", "StartPlay", this->bootvideoPath); ALOGE("StartPlay: video player start failure"); return false; } if (!client->WaitForFirstFrame()) { BootvideoDfteventReport(E_955050801, "WaitForFirstFrame", "StartPlay", this->bootvideoPath); ALOGE("StartPlay: Wait first frame has error"); return false; } return true; } bool BootvideoPlayer::StopPlay() { if (fd != -1) { close(fd); fd = -1; } if (client != nullptr) { client->ForceStop(); client = nullptr; } if (player != nullptr) { player->stop(); player->disconnect(); player = nullptr; } return true; } } // namespace android