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 videoAudioSync_ = std::make_shared<VideoAudioSync>();
62 if (nullptr != videoAudioSync_) {
63 videoAudioSync_->SetAudioPlayController(audioPlayController_);
64 }
65
66 return true;
67 }
68
Start()69 void MediaController::Start()
70 {
71 SHARING_LOGD("trace.");
72 auto mediaChannel = mediaChannel_.lock();
73 RETURN_IF_NULL(mediaChannel);
74 SHARING_LOGI("media play start, mediachannelId: %{public}u.", mediachannelId_);
75 if (nullptr == audioPlayController_ && 0 == videoPlayerMap_.size()) {
76 SHARING_LOGE("start must be after init.");
77 return;
78 }
79
80 auto dispatcher = mediaChannel->GetDispatcher();
81 RETURN_IF_NULL(dispatcher);
82 {
83 std::lock_guard<std::mutex> lock(playAudioMutex_);
84 if (nullptr != audioPlayController_) {
85 if (audioPlayController_->Start(dispatcher)) {
86 isPlaying_ = true;
87 }
88 }
89 }
90
91 if (videoPlayerMap_.size() > 0) {
92 std::lock_guard<std::mutex> lock(playVideoMutex_);
93 for (auto &item : videoPlayerMap_) {
94 if (item.second->Start(dispatcher)) {
95 isPlaying_ = true;
96 }
97 }
98 }
99
100 SHARING_LOGI("media play start done, mediachannelId: %{public}u.", mediachannelId_);
101 }
102
Stop()103 void MediaController::Stop()
104 {
105 SHARING_LOGD("trace.");
106 auto mediaChannel = mediaChannel_.lock();
107 RETURN_IF_NULL(mediaChannel);
108 SHARING_LOGI("media play stop, mediachannelId: %{public}u.", mediachannelId_);
109 auto dispatcher = mediaChannel->GetDispatcher();
110 RETURN_IF_NULL(dispatcher);
111 {
112 std::lock_guard<std::mutex> lock(playAudioMutex_);
113 if (isPlaying_ && (nullptr != audioPlayController_)) {
114 audioPlayController_->Stop(dispatcher);
115 }
116 }
117
118 {
119 std::lock_guard<std::mutex> lock(playVideoMutex_);
120 if (isPlaying_) {
121 for (auto &item : videoPlayerMap_) {
122 item.second->Stop(dispatcher);
123 }
124 }
125 }
126
127 isPlaying_ = false;
128 SHARING_LOGI("media play stop done, mediachannelId: %{public}u.", mediachannelId_);
129 }
130
Release()131 void MediaController::Release()
132 {
133 SHARING_LOGD("trace.");
134 if (nullptr != audioPlayController_) {
135 audioPlayController_->Release();
136 audioPlayController_.reset();
137 }
138
139 {
140 std::lock_guard<std::mutex> lock(playVideoMutex_);
141 for (auto &item : videoPlayerMap_) {
142 item.second->Release();
143 }
144 videoPlayerMap_.clear();
145 }
146
147 SHARING_LOGI("media play release done, mediachannelId: %{public}u.", mediachannelId_);
148 }
149
AppendSurface(sptr<Surface> surface,SceneType sceneType)150 bool MediaController::AppendSurface(sptr<Surface> surface, SceneType sceneType)
151 {
152 SHARING_LOGD("trace.");
153 RETURN_FALSE_IF_NULL(surface);
154 if (CODEC_NONE == videoTrack_.codecId) {
155 SHARING_LOGW("no need to play video.");
156 return false;
157 }
158
159 auto videoPlayController = std::make_shared<VideoPlayController>(mediachannelId_);
160 uint64_t surfaceId = surface->GetUniqueId();
161 {
162 std::lock_guard<std::mutex> lock(playVideoMutex_);
163 if (videoPlayerMap_.count(surfaceId)) {
164 SHARING_LOGE("surface is in use, %{public}" PRIx64 ".", surfaceId);
165 return false;
166 }
167
168 bool keyFrame = sceneType == SceneType::BACKGROUND ? true : false;
169 if (videoPlayController->Init(videoTrack_) && videoPlayController->SetSurface(surface, keyFrame)) {
170 videoPlayController->SetVideoAudioSync(videoAudioSync_);
171 videoPlayerMap_.emplace(surfaceId, videoPlayController);
172 } else {
173 SHARING_LOGD("videoPlayController init failed, mediachannelId: %{public}u.", mediachannelId_);
174 return false;
175 }
176
177 if (isPlaying_) {
178 auto mediaChannel = mediaChannel_.lock();
179 auto dispatcher = mediaChannel->GetDispatcher();
180 videoPlayController->Start(dispatcher);
181 }
182
183 videoPlayController->SetMediaController(shared_from_this());
184 SHARING_LOGI("media play append surface done, mediachannelId: %{public}u.", mediachannelId_);
185 }
186
187 return true;
188 }
189
RemoveSurface(uint64_t surfaceId)190 void MediaController::RemoveSurface(uint64_t surfaceId)
191 {
192 SHARING_LOGD("trace.");
193 {
194 std::lock_guard<std::mutex> lock(playVideoMutex_);
195 auto videoPlayController = videoPlayerMap_.find(surfaceId);
196 if (videoPlayController != videoPlayerMap_.end()) {
197 auto mediaChannel = mediaChannel_.lock();
198 auto dispatcher = mediaChannel->GetDispatcher();
199 videoPlayController->second->Stop(dispatcher);
200 videoPlayController->second->Release();
201 videoPlayerMap_.erase(surfaceId);
202 }
203 SHARING_LOGI("media play remove surface done, mediachannelId: %{public}u.", mediachannelId_);
204 }
205 }
206
SetVolume(float volume)207 void MediaController::SetVolume(float volume)
208 {
209 SHARING_LOGD("Volume: %{public}f.", volume);
210 if (audioPlayController_) {
211 audioPlayController_->SetVolume(volume);
212 }
213 }
214
SetKeyMode(uint64_t surfaceId,bool mode)215 void MediaController::SetKeyMode(uint64_t surfaceId, bool mode)
216 {
217 SHARING_LOGD("trace.");
218 {
219 std::lock_guard<std::mutex> lock(playVideoMutex_);
220 auto videoPlayController = videoPlayerMap_.find(surfaceId);
221 if (videoPlayController != videoPlayerMap_.end()) {
222 videoPlayController->second->SetKeyMode(mode);
223 }
224 SHARING_LOGI("media play set key mode done, mediachannelId: %{public}u.", mediachannelId_);
225 }
226 }
227
SetKeyRedirect(uint64_t surfaceId,bool keyRedirect)228 void MediaController::SetKeyRedirect(uint64_t surfaceId, bool keyRedirect)
229 {
230 SHARING_LOGD("trace.");
231 {
232 std::lock_guard<std::mutex> lock(playVideoMutex_);
233 auto videoPlayController = videoPlayerMap_.find(surfaceId);
234 if (videoPlayController != videoPlayerMap_.end()) {
235 videoPlayController->second->SetKeyRedirect(keyRedirect);
236 }
237 SHARING_LOGI("media play set key redirect done, mediachannelId: %{public}u.", mediachannelId_);
238 }
239 }
240
OnPlayControllerNotify(ProsumerStatusMsg::Ptr & statusMsg)241 void MediaController::OnPlayControllerNotify(ProsumerStatusMsg::Ptr &statusMsg)
242 {
243 SHARING_LOGD("trace.");
244 RETURN_IF_NULL(statusMsg);
245 auto mediaChannel = mediaChannel_.lock();
246 RETURN_IF_NULL(mediaChannel);
247
248 statusMsg->agentId = mediaChannel->GetSinkAgentId();
249 mediaChannel->OnMediaControllerNotify(statusMsg);
250 }
251
252 } // namespace Sharing
253 } // namespace OHOS