1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <VideoManager.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaNetworkUtil.h>
20
21 using namespace android;
22 VideoManager* VideoManager::manager;
23
VideoManager()24 VideoManager::VideoManager()
25 {
26 mRequestHandler.Init("VIDEO_REQUEST_EVENT");
27 mResponseHandler.Init("VIDEO_RESPONSE_EVENT");
28 }
29
~VideoManager()30 VideoManager::~VideoManager()
31 {
32 mRequestHandler.Deinit();
33 mResponseHandler.Deinit();
34 manager = nullptr;
35 }
36
getInstance()37 VideoManager* VideoManager::getInstance()
38 {
39 if (manager == nullptr)
40 {
41 manager = new VideoManager();
42 }
43
44 return manager;
45 }
46
getState(int sessionId)47 int VideoManager::getState(int sessionId)
48 {
49 auto session = mSessions.find(sessionId);
50
51 if (session != mSessions.end())
52 {
53 return (session->second)->getState();
54 }
55 else
56 {
57 return kSessionStateClosed;
58 }
59 }
60
openSession(const int sessionId,const int rtpFd,const int rtcpFd,VideoConfig * config)61 ImsMediaResult VideoManager::openSession(
62 const int sessionId, const int rtpFd, const int rtcpFd, VideoConfig* config)
63 {
64 IMLOGI1("[openSession] sessionId[%d]", sessionId);
65
66 if (rtpFd == -1 || rtcpFd == -1)
67 {
68 return RESULT_INVALID_PARAM;
69 }
70
71 if (!mSessions.count(sessionId))
72 {
73 std::unique_ptr<VideoSession> session(new VideoSession());
74 session->setSessionId(sessionId);
75 session->setLocalEndPoint(rtpFd, rtcpFd);
76
77 if (session->startGraph(config) != RESULT_SUCCESS)
78 {
79 IMLOGI0("[openSession] startGraph failed");
80 }
81
82 mSessions.insert(std::make_pair(sessionId, std::move(session)));
83 }
84 else
85 {
86 return RESULT_INVALID_PARAM;
87 }
88
89 return RESULT_SUCCESS;
90 }
91
closeSession(const int sessionId)92 ImsMediaResult VideoManager::closeSession(const int sessionId)
93 {
94 IMLOGI1("[closeSession] sessionId[%d]", sessionId);
95
96 if (mSessions.count(sessionId))
97 {
98 mSessions.erase(sessionId);
99 return RESULT_SUCCESS;
100 }
101
102 return RESULT_INVALID_PARAM;
103 }
104
setPreviewSurfaceToSession(const int sessionId,ANativeWindow * surface)105 ImsMediaResult VideoManager::setPreviewSurfaceToSession(const int sessionId, ANativeWindow* surface)
106 {
107 auto session = mSessions.find(sessionId);
108 IMLOGI1("[setPreviewSurfaceToSession] sessionId[%d]", sessionId);
109
110 if (session != mSessions.end())
111 {
112 return (session->second)->setPreviewSurface(surface);
113 }
114 else
115 {
116 IMLOGE1("[setPreviewSurfaceToSession] no session id[%d]", sessionId);
117 return RESULT_INVALID_PARAM;
118 }
119 }
120
setDisplaySurfaceToSession(const int sessionId,ANativeWindow * surface)121 ImsMediaResult VideoManager::setDisplaySurfaceToSession(const int sessionId, ANativeWindow* surface)
122 {
123 auto session = mSessions.find(sessionId);
124 IMLOGI1("[setDisplaySurfaceToSession] sessionId[%d]", sessionId);
125
126 if (session != mSessions.end())
127 {
128 return (session->second)->setDisplaySurface(surface);
129 }
130 else
131 {
132 IMLOGE1("[setDisplaySurfaceToSession] no session id[%d]", sessionId);
133 return RESULT_INVALID_PARAM;
134 }
135 }
136
modifySession(const int sessionId,VideoConfig * config)137 ImsMediaResult VideoManager::modifySession(const int sessionId, VideoConfig* config)
138 {
139 auto session = mSessions.find(sessionId);
140 IMLOGI1("[modifySession] sessionId[%d]", sessionId);
141
142 if (session != mSessions.end())
143 {
144 return (session->second)->startGraph(config);
145 }
146 else
147 {
148 IMLOGE1("[modifySession] no session id[%d]", sessionId);
149 return RESULT_INVALID_PARAM;
150 }
151 }
152
setMediaQualityThreshold(const int sessionId,MediaQualityThreshold * threshold)153 void VideoManager::setMediaQualityThreshold(const int sessionId, MediaQualityThreshold* threshold)
154 {
155 auto session = mSessions.find(sessionId);
156 IMLOGI1("[setMediaQualityThreshold] sessionId[%d]", sessionId);
157
158 if (session != mSessions.end())
159 {
160 (session->second)->setMediaQualityThreshold(*threshold);
161 }
162 else
163 {
164 IMLOGE1("[setMediaQualityThreshold] no session id[%d]", sessionId);
165 }
166 }
167
sendMessage(const int sessionId,const android::Parcel & parcel)168 void VideoManager::sendMessage(const int sessionId, const android::Parcel& parcel)
169 {
170 int nMsg = parcel.readInt32();
171 status_t err = NO_ERROR;
172
173 switch (nMsg)
174 {
175 case kVideoOpenSession:
176 {
177 int rtpFd = parcel.readInt32();
178 int rtcpFd = parcel.readInt32();
179 VideoConfig* config = new VideoConfig();
180 err = config->readFromParcel(&parcel);
181
182 if (err != NO_ERROR)
183 {
184 IMLOGE1("[sendMessage] error readFromParcel[%d]", err);
185 delete config;
186 config = nullptr;
187 }
188
189 EventParamOpenSession* param = new EventParamOpenSession(rtpFd, rtcpFd, config);
190 ImsMediaEventHandler::SendEvent(
191 "VIDEO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(param));
192 }
193 break;
194 case kVideoCloseSession:
195 ImsMediaEventHandler::SendEvent("VIDEO_REQUEST_EVENT", nMsg, sessionId);
196 break;
197 case kVideoModifySession:
198 {
199 VideoConfig* config = new VideoConfig();
200 err = config->readFromParcel(&parcel);
201
202 if (err != NO_ERROR)
203 {
204 IMLOGE1("[sendMessage] error readFromParcel[%d]", err);
205 }
206
207 ImsMediaEventHandler::SendEvent(
208 "VIDEO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(config));
209 }
210 break;
211 case kVideoSendRtpHeaderExtension:
212 // TO DO
213 break;
214 case kVideoSetMediaQualityThreshold:
215 {
216 MediaQualityThreshold* threshold = new MediaQualityThreshold();
217 threshold->readFromParcel(&parcel);
218 ImsMediaEventHandler::SendEvent(
219 "VIDEO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(threshold));
220 }
221 break;
222 default:
223 break;
224 }
225 }
226
setPreviewSurface(const int sessionId,ANativeWindow * surface)227 void VideoManager::setPreviewSurface(const int sessionId, ANativeWindow* surface)
228 {
229 IMLOGI1("[setPreviewSurface] sessionId[%d]", sessionId);
230 ImsMediaEventHandler::SendEvent("VIDEO_REQUEST_EVENT", kVideoSetPreviewSurface, sessionId,
231 reinterpret_cast<uint64_t>(surface));
232 }
233
setDisplaySurface(const int sessionId,ANativeWindow * surface)234 void VideoManager::setDisplaySurface(const int sessionId, ANativeWindow* surface)
235 {
236 IMLOGI1("[setDisplaySurface] sessionId[%d]", sessionId);
237 ImsMediaEventHandler::SendEvent("VIDEO_REQUEST_EVENT", kVideoSetDisplaySurface, sessionId,
238 reinterpret_cast<uint64_t>(surface));
239 }
240
SendInternalEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)241 void VideoManager::SendInternalEvent(
242 uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
243 {
244 auto session = mSessions.find(sessionId);
245 IMLOGI1("[SendInternalEvent] sessionId[%d]", sessionId);
246
247 if (session != mSessions.end())
248 {
249 (session->second)->SendInternalEvent(event, paramA, paramB);
250 }
251 else
252 {
253 IMLOGE1("[SendInternalEvent] no session id[%d]", sessionId);
254 }
255 }
256
processEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)257 void VideoManager::RequestHandler::processEvent(
258 uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
259 {
260 IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
261 paramA, paramB);
262 ImsMediaResult result = RESULT_SUCCESS;
263
264 switch (event)
265 {
266 case kVideoOpenSession:
267 {
268 EventParamOpenSession* param = reinterpret_cast<EventParamOpenSession*>(paramA);
269
270 if (param != nullptr)
271 {
272 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(param->mConfig);
273 result = VideoManager::getInstance()->openSession(
274 static_cast<int>(sessionId), param->rtpFd, param->rtcpFd, pConfig);
275
276 if (result == RESULT_SUCCESS)
277 {
278 ImsMediaEventHandler::SendEvent(
279 "VIDEO_RESPONSE_EVENT", kVideoOpenSessionSuccess, sessionId);
280 }
281 else
282 {
283 ImsMediaEventHandler::SendEvent(
284 "VIDEO_RESPONSE_EVENT", kVideoOpenSessionFailure, sessionId, result);
285 }
286
287 delete param;
288
289 if (pConfig != nullptr)
290 {
291 delete pConfig;
292 }
293 }
294 else
295 {
296 ImsMediaEventHandler::SendEvent("VIDEO_RESPONSE_EVENT", kVideoOpenSessionFailure,
297 sessionId, RESULT_INVALID_PARAM);
298 }
299 }
300 break;
301 case kVideoCloseSession:
302 if (VideoManager::getInstance()->closeSession(static_cast<int>(sessionId)) ==
303 RESULT_SUCCESS)
304 {
305 ImsMediaEventHandler::SendEvent(
306 "VIDEO_RESPONSE_EVENT", kVideoSessionClosed, sessionId, 0, 0);
307 }
308 break;
309 case kVideoSetPreviewSurface:
310 VideoManager::getInstance()->setPreviewSurfaceToSession(
311 static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
312 break;
313 case kVideoSetDisplaySurface:
314 VideoManager::getInstance()->setDisplaySurfaceToSession(
315 static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
316 break;
317 case kVideoModifySession:
318 {
319 VideoConfig* config = reinterpret_cast<VideoConfig*>(paramA);
320 result =
321 VideoManager::getInstance()->modifySession(static_cast<int>(sessionId), config);
322 ImsMediaEventHandler::SendEvent(
323 "VIDEO_RESPONSE_EVENT", kVideoModifySessionResponse, sessionId, result, paramA);
324 }
325 break;
326 case kVideoSendRtpHeaderExtension:
327 /** TODO: add implementation */
328 break;
329 case kVideoSetMediaQualityThreshold:
330 {
331 MediaQualityThreshold* threshold = reinterpret_cast<MediaQualityThreshold*>(paramA);
332
333 if (threshold != nullptr)
334 {
335 VideoManager::getInstance()->setMediaQualityThreshold(
336 static_cast<int>(sessionId), threshold);
337 delete threshold;
338 }
339 }
340 break;
341 case kRequestVideoCvoUpdate:
342 case kRequestVideoBitrateChange:
343 case kRequestVideoIdrFrame:
344 case kRequestVideoSendNack:
345 case kRequestVideoSendPictureLost:
346 case kRequestVideoSendTmmbr:
347 case kRequestVideoSendTmmbn:
348 case kRequestRoundTripTimeDelayUpdate:
349 VideoManager::getInstance()->SendInternalEvent(event, sessionId, paramA, paramB);
350 break;
351 default:
352 break;
353 }
354 }
355
processEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)356 void VideoManager::ResponseHandler::processEvent(
357 uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
358 {
359 IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
360 paramA, paramB);
361 android::Parcel parcel;
362 switch (event)
363 {
364 case kVideoOpenSessionSuccess:
365 case kVideoOpenSessionFailure:
366 parcel.writeInt32(event);
367 parcel.writeInt32(static_cast<int>(sessionId));
368
369 if (event == kVideoOpenSessionFailure)
370 {
371 // fail reason
372 parcel.writeInt32(static_cast<int>(paramA));
373 }
374
375 VideoManager::getInstance()->sendResponse(sessionId, parcel);
376 break;
377 case kVideoModifySessionResponse: // fall through
378 {
379 parcel.writeInt32(event);
380 parcel.writeInt32(static_cast<int>(paramA)); // result
381 VideoConfig* config = reinterpret_cast<VideoConfig*>(paramB);
382
383 if (config != nullptr)
384 {
385 config->writeToParcel(&parcel);
386 VideoManager::getInstance()->sendResponse(sessionId, parcel);
387 delete config;
388 }
389 }
390 break;
391 case kVideoFirstMediaPacketInd:
392 parcel.writeInt32(event);
393 VideoManager::getInstance()->sendResponse(sessionId, parcel);
394 break;
395 case kVideoPeerDimensionChanged:
396 parcel.writeInt32(event);
397 parcel.writeInt32(static_cast<int>(paramA));
398 parcel.writeInt32(static_cast<int>(paramB));
399 VideoManager::getInstance()->sendResponse(sessionId, parcel);
400 break;
401 case kVideoRtpHeaderExtensionInd:
402 // TODO : add implementation
403 break;
404 case kVideoMediaInactivityInd:
405 case kVideoBitrateInd:
406 parcel.writeInt32(event);
407 parcel.writeInt32(static_cast<int>(paramA));
408 VideoManager::getInstance()->sendResponse(sessionId, parcel);
409 break;
410 case kVideoDataUsageInd:
411 parcel.writeInt32(event);
412 parcel.writeInt64(static_cast<int>(paramA));
413 VideoManager::getInstance()->sendResponse(sessionId, parcel);
414 break;
415 case kVideoSessionClosed:
416 parcel.writeInt32(event);
417 parcel.writeInt32(static_cast<int>(sessionId));
418 VideoManager::getInstance()->sendResponse(sessionId, parcel);
419 break;
420 default:
421 break;
422 }
423 }
424