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