1e0e9324cSopenharmony_ci/* 2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License. 5e0e9324cSopenharmony_ci * You may obtain a copy of the License at 6e0e9324cSopenharmony_ci * 7e0e9324cSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0e9324cSopenharmony_ci * 9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and 13e0e9324cSopenharmony_ci * limitations under the License. 14e0e9324cSopenharmony_ci */ 15e0e9324cSopenharmony_ci 16e0e9324cSopenharmony_ci#include "media_controller.h" 17e0e9324cSopenharmony_ci#include <chrono> 18e0e9324cSopenharmony_ci#include "common/common_macro.h" 19e0e9324cSopenharmony_ci#include "common/const_def.h" 20e0e9324cSopenharmony_ci#include "common/event_comm.h" 21e0e9324cSopenharmony_ci#include "common/media_log.h" 22e0e9324cSopenharmony_ci#include "configuration/include/config.h" 23e0e9324cSopenharmony_ci#include "magic_enum.hpp" 24e0e9324cSopenharmony_ci#include "media_channel.h" 25e0e9324cSopenharmony_ci#include "protocol/frame/h264_frame.h" 26e0e9324cSopenharmony_ci#include "utils/data_buffer.h" 27e0e9324cSopenharmony_ci 28e0e9324cSopenharmony_cinamespace OHOS { 29e0e9324cSopenharmony_cinamespace Sharing { 30e0e9324cSopenharmony_ci 31e0e9324cSopenharmony_ciMediaController::MediaController(uint32_t mediaChannelId) 32e0e9324cSopenharmony_ci{ 33e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 34e0e9324cSopenharmony_ci mediachannelId_ = mediaChannelId; 35e0e9324cSopenharmony_ci} 36e0e9324cSopenharmony_ci 37e0e9324cSopenharmony_ciMediaController::~MediaController() 38e0e9324cSopenharmony_ci{ 39e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 40e0e9324cSopenharmony_ci Release(); 41e0e9324cSopenharmony_ci SHARING_LOGD("delete media controller, mediachannelId: %{public}u.", mediachannelId_); 42e0e9324cSopenharmony_ci} 43e0e9324cSopenharmony_ci 44e0e9324cSopenharmony_cibool MediaController::Init(AudioTrack audioTrack, VideoTrack videoTrack) 45e0e9324cSopenharmony_ci{ 46e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 47e0e9324cSopenharmony_ci audioTrack_ = audioTrack; 48e0e9324cSopenharmony_ci videoTrack_ = videoTrack; 49e0e9324cSopenharmony_ci if (CODEC_NONE == audioTrack_.codecId && CODEC_NONE == videoTrack_.codecId) { 50e0e9324cSopenharmony_ci SHARING_LOGW("no need to play."); 51e0e9324cSopenharmony_ci return false; 52e0e9324cSopenharmony_ci } 53e0e9324cSopenharmony_ci 54e0e9324cSopenharmony_ci if (CODEC_NONE != audioTrack_.codecId) { 55e0e9324cSopenharmony_ci audioPlayController_ = std::make_shared<AudioPlayController>(mediachannelId_); 56e0e9324cSopenharmony_ci if (!audioPlayController_->Init(audioTrack_)) { 57e0e9324cSopenharmony_ci SHARING_LOGE("audio play init error."); 58e0e9324cSopenharmony_ci return false; 59e0e9324cSopenharmony_ci } 60e0e9324cSopenharmony_ci } 61e0e9324cSopenharmony_ci 62e0e9324cSopenharmony_ci return true; 63e0e9324cSopenharmony_ci} 64e0e9324cSopenharmony_ci 65e0e9324cSopenharmony_civoid MediaController::Start() 66e0e9324cSopenharmony_ci{ 67e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 68e0e9324cSopenharmony_ci auto mediaChannel = mediaChannel_.lock(); 69e0e9324cSopenharmony_ci RETURN_IF_NULL(mediaChannel); 70e0e9324cSopenharmony_ci SHARING_LOGI("media play start, mediachannelId: %{public}u.", mediachannelId_); 71e0e9324cSopenharmony_ci if (nullptr == audioPlayController_ && 0 == videoPlayerMap_.size()) { 72e0e9324cSopenharmony_ci SHARING_LOGE("start must be after init."); 73e0e9324cSopenharmony_ci return; 74e0e9324cSopenharmony_ci } 75e0e9324cSopenharmony_ci 76e0e9324cSopenharmony_ci auto dispatcher = mediaChannel->GetDispatcher(); 77e0e9324cSopenharmony_ci RETURN_IF_NULL(dispatcher); 78e0e9324cSopenharmony_ci { 79e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playAudioMutex_); 80e0e9324cSopenharmony_ci if (nullptr != audioPlayController_) { 81e0e9324cSopenharmony_ci if (audioPlayController_->Start(dispatcher)) { 82e0e9324cSopenharmony_ci isPlaying_ = true; 83e0e9324cSopenharmony_ci } 84e0e9324cSopenharmony_ci } 85e0e9324cSopenharmony_ci } 86e0e9324cSopenharmony_ci 87e0e9324cSopenharmony_ci if (videoPlayerMap_.size() > 0) { 88e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 89e0e9324cSopenharmony_ci for (auto &item : videoPlayerMap_) { 90e0e9324cSopenharmony_ci if (item.second->Start(dispatcher)) { 91e0e9324cSopenharmony_ci isPlaying_ = true; 92e0e9324cSopenharmony_ci } 93e0e9324cSopenharmony_ci } 94e0e9324cSopenharmony_ci } 95e0e9324cSopenharmony_ci 96e0e9324cSopenharmony_ci SHARING_LOGI("media play start done, mediachannelId: %{public}u.", mediachannelId_); 97e0e9324cSopenharmony_ci} 98e0e9324cSopenharmony_ci 99e0e9324cSopenharmony_civoid MediaController::Stop() 100e0e9324cSopenharmony_ci{ 101e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 102e0e9324cSopenharmony_ci auto mediaChannel = mediaChannel_.lock(); 103e0e9324cSopenharmony_ci RETURN_IF_NULL(mediaChannel); 104e0e9324cSopenharmony_ci SHARING_LOGI("media play stop, mediachannelId: %{public}u.", mediachannelId_); 105e0e9324cSopenharmony_ci auto dispatcher = mediaChannel->GetDispatcher(); 106e0e9324cSopenharmony_ci RETURN_IF_NULL(dispatcher); 107e0e9324cSopenharmony_ci { 108e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playAudioMutex_); 109e0e9324cSopenharmony_ci if (isPlaying_ && (nullptr != audioPlayController_)) { 110e0e9324cSopenharmony_ci audioPlayController_->Stop(dispatcher); 111e0e9324cSopenharmony_ci } 112e0e9324cSopenharmony_ci } 113e0e9324cSopenharmony_ci 114e0e9324cSopenharmony_ci { 115e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 116e0e9324cSopenharmony_ci if (isPlaying_) { 117e0e9324cSopenharmony_ci for (auto &item : videoPlayerMap_) { 118e0e9324cSopenharmony_ci item.second->Stop(dispatcher); 119e0e9324cSopenharmony_ci } 120e0e9324cSopenharmony_ci } 121e0e9324cSopenharmony_ci } 122e0e9324cSopenharmony_ci 123e0e9324cSopenharmony_ci isPlaying_ = false; 124e0e9324cSopenharmony_ci SHARING_LOGI("media play stop done, mediachannelId: %{public}u.", mediachannelId_); 125e0e9324cSopenharmony_ci} 126e0e9324cSopenharmony_ci 127e0e9324cSopenharmony_civoid MediaController::Release() 128e0e9324cSopenharmony_ci{ 129e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 130e0e9324cSopenharmony_ci if (nullptr != audioPlayController_) { 131e0e9324cSopenharmony_ci audioPlayController_->Release(); 132e0e9324cSopenharmony_ci audioPlayController_.reset(); 133e0e9324cSopenharmony_ci } 134e0e9324cSopenharmony_ci 135e0e9324cSopenharmony_ci { 136e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 137e0e9324cSopenharmony_ci for (auto &item : videoPlayerMap_) { 138e0e9324cSopenharmony_ci item.second->Release(); 139e0e9324cSopenharmony_ci } 140e0e9324cSopenharmony_ci videoPlayerMap_.clear(); 141e0e9324cSopenharmony_ci } 142e0e9324cSopenharmony_ci 143e0e9324cSopenharmony_ci SHARING_LOGI("media play release done, mediachannelId: %{public}u.", mediachannelId_); 144e0e9324cSopenharmony_ci} 145e0e9324cSopenharmony_ci 146e0e9324cSopenharmony_cibool MediaController::AppendSurface(sptr<Surface> surface, SceneType sceneType) 147e0e9324cSopenharmony_ci{ 148e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 149e0e9324cSopenharmony_ci RETURN_FALSE_IF_NULL(surface); 150e0e9324cSopenharmony_ci if (CODEC_NONE == videoTrack_.codecId) { 151e0e9324cSopenharmony_ci SHARING_LOGW("no need to play video."); 152e0e9324cSopenharmony_ci return false; 153e0e9324cSopenharmony_ci } 154e0e9324cSopenharmony_ci 155e0e9324cSopenharmony_ci auto videoPlayController = std::make_shared<VideoPlayController>(mediachannelId_); 156e0e9324cSopenharmony_ci uint64_t surfaceId = surface->GetUniqueId(); 157e0e9324cSopenharmony_ci { 158e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 159e0e9324cSopenharmony_ci if (videoPlayerMap_.count(surfaceId)) { 160e0e9324cSopenharmony_ci SHARING_LOGE("surface is in use, %{public}" PRIx64 ".", surfaceId); 161e0e9324cSopenharmony_ci return false; 162e0e9324cSopenharmony_ci } 163e0e9324cSopenharmony_ci 164e0e9324cSopenharmony_ci bool keyFrame = sceneType == SceneType::BACKGROUND ? true : false; 165e0e9324cSopenharmony_ci if (videoPlayController->Init(videoTrack_) && videoPlayController->SetSurface(surface, keyFrame)) { 166e0e9324cSopenharmony_ci videoPlayerMap_.emplace(surfaceId, videoPlayController); 167e0e9324cSopenharmony_ci } else { 168e0e9324cSopenharmony_ci SHARING_LOGD("videoPlayController init failed, mediachannelId: %{public}u.", mediachannelId_); 169e0e9324cSopenharmony_ci return false; 170e0e9324cSopenharmony_ci } 171e0e9324cSopenharmony_ci 172e0e9324cSopenharmony_ci if (isPlaying_) { 173e0e9324cSopenharmony_ci auto mediaChannel = mediaChannel_.lock(); 174e0e9324cSopenharmony_ci auto dispatcher = mediaChannel->GetDispatcher(); 175e0e9324cSopenharmony_ci videoPlayController->Start(dispatcher); 176e0e9324cSopenharmony_ci } 177e0e9324cSopenharmony_ci 178e0e9324cSopenharmony_ci videoPlayController->SetMediaController(shared_from_this()); 179e0e9324cSopenharmony_ci SHARING_LOGI("media play append surface done, mediachannelId: %{public}u.", mediachannelId_); 180e0e9324cSopenharmony_ci } 181e0e9324cSopenharmony_ci 182e0e9324cSopenharmony_ci return true; 183e0e9324cSopenharmony_ci} 184e0e9324cSopenharmony_ci 185e0e9324cSopenharmony_civoid MediaController::RemoveSurface(uint64_t surfaceId) 186e0e9324cSopenharmony_ci{ 187e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 188e0e9324cSopenharmony_ci { 189e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 190e0e9324cSopenharmony_ci auto videoPlayController = videoPlayerMap_.find(surfaceId); 191e0e9324cSopenharmony_ci if (videoPlayController != videoPlayerMap_.end()) { 192e0e9324cSopenharmony_ci auto mediaChannel = mediaChannel_.lock(); 193e0e9324cSopenharmony_ci auto dispatcher = mediaChannel->GetDispatcher(); 194e0e9324cSopenharmony_ci videoPlayController->second->Stop(dispatcher); 195e0e9324cSopenharmony_ci videoPlayController->second->Release(); 196e0e9324cSopenharmony_ci videoPlayerMap_.erase(surfaceId); 197e0e9324cSopenharmony_ci } 198e0e9324cSopenharmony_ci SHARING_LOGI("media play remove surface done, mediachannelId: %{public}u.", mediachannelId_); 199e0e9324cSopenharmony_ci } 200e0e9324cSopenharmony_ci} 201e0e9324cSopenharmony_ci 202e0e9324cSopenharmony_civoid MediaController::SetVolume(float volume) 203e0e9324cSopenharmony_ci{ 204e0e9324cSopenharmony_ci SHARING_LOGD("Volume: %{public}f.", volume); 205e0e9324cSopenharmony_ci if (audioPlayController_) { 206e0e9324cSopenharmony_ci audioPlayController_->SetVolume(volume); 207e0e9324cSopenharmony_ci } 208e0e9324cSopenharmony_ci} 209e0e9324cSopenharmony_ci 210e0e9324cSopenharmony_civoid MediaController::SetKeyMode(uint64_t surfaceId, bool mode) 211e0e9324cSopenharmony_ci{ 212e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 213e0e9324cSopenharmony_ci { 214e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 215e0e9324cSopenharmony_ci auto videoPlayController = videoPlayerMap_.find(surfaceId); 216e0e9324cSopenharmony_ci if (videoPlayController != videoPlayerMap_.end()) { 217e0e9324cSopenharmony_ci videoPlayController->second->SetKeyMode(mode); 218e0e9324cSopenharmony_ci } 219e0e9324cSopenharmony_ci SHARING_LOGI("media play set key mode done, mediachannelId: %{public}u.", mediachannelId_); 220e0e9324cSopenharmony_ci } 221e0e9324cSopenharmony_ci} 222e0e9324cSopenharmony_ci 223e0e9324cSopenharmony_civoid MediaController::SetKeyRedirect(uint64_t surfaceId, bool keyRedirect) 224e0e9324cSopenharmony_ci{ 225e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 226e0e9324cSopenharmony_ci { 227e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(playVideoMutex_); 228e0e9324cSopenharmony_ci auto videoPlayController = videoPlayerMap_.find(surfaceId); 229e0e9324cSopenharmony_ci if (videoPlayController != videoPlayerMap_.end()) { 230e0e9324cSopenharmony_ci videoPlayController->second->SetKeyRedirect(keyRedirect); 231e0e9324cSopenharmony_ci } 232e0e9324cSopenharmony_ci SHARING_LOGI("media play set key redirect done, mediachannelId: %{public}u.", mediachannelId_); 233e0e9324cSopenharmony_ci } 234e0e9324cSopenharmony_ci} 235e0e9324cSopenharmony_ci 236e0e9324cSopenharmony_civoid MediaController::OnPlayControllerNotify(ProsumerStatusMsg::Ptr &statusMsg) 237e0e9324cSopenharmony_ci{ 238e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 239e0e9324cSopenharmony_ci RETURN_IF_NULL(statusMsg); 240e0e9324cSopenharmony_ci auto mediaChannel = mediaChannel_.lock(); 241e0e9324cSopenharmony_ci RETURN_IF_NULL(mediaChannel); 242e0e9324cSopenharmony_ci 243e0e9324cSopenharmony_ci statusMsg->agentId = mediaChannel->GetSinkAgentId(); 244e0e9324cSopenharmony_ci mediaChannel->OnMediaControllerNotify(statusMsg); 245e0e9324cSopenharmony_ci} 246e0e9324cSopenharmony_ci 247e0e9324cSopenharmony_ci} // namespace Sharing 248e0e9324cSopenharmony_ci} // namespace OHOS