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::sManager;
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 sManager = nullptr;
35 }
36
getInstance()37 VideoManager* VideoManager::getInstance()
38 {
39 if (sManager == nullptr)
40 {
41 sManager = new VideoManager();
42 }
43
44 return sManager;
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 if (sManager == nullptr)
265 {
266 return;
267 }
268
269 switch (event)
270 {
271 case kVideoOpenSession:
272 {
273 EventParamOpenSession* param = reinterpret_cast<EventParamOpenSession*>(paramA);
274
275 if (param != nullptr)
276 {
277 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(param->mConfig);
278 result = sManager->openSession(
279 static_cast<int>(sessionId), param->rtpFd, param->rtcpFd, pConfig);
280
281 if (result == RESULT_SUCCESS)
282 {
283 ImsMediaEventHandler::SendEvent(
284 "VIDEO_RESPONSE_EVENT", kVideoOpenSessionSuccess, sessionId);
285 }
286 else
287 {
288 ImsMediaEventHandler::SendEvent(
289 "VIDEO_RESPONSE_EVENT", kVideoOpenSessionFailure, sessionId, result);
290 }
291
292 delete param;
293
294 if (pConfig != nullptr)
295 {
296 delete pConfig;
297 }
298 }
299 else
300 {
301 ImsMediaEventHandler::SendEvent("VIDEO_RESPONSE_EVENT", kVideoOpenSessionFailure,
302 sessionId, RESULT_INVALID_PARAM);
303 }
304 }
305 break;
306 case kVideoCloseSession:
307 if (sManager->closeSession(static_cast<int>(sessionId)) == RESULT_SUCCESS)
308 {
309 ImsMediaEventHandler::SendEvent(
310 "VIDEO_RESPONSE_EVENT", kVideoSessionClosed, sessionId, 0, 0);
311 }
312 break;
313 case kVideoSetPreviewSurface:
314 sManager->setPreviewSurfaceToSession(
315 static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
316 break;
317 case kVideoSetDisplaySurface:
318 sManager->setDisplaySurfaceToSession(
319 static_cast<int>(sessionId), reinterpret_cast<ANativeWindow*>(paramA));
320 break;
321 case kVideoModifySession:
322 {
323 VideoConfig* config = reinterpret_cast<VideoConfig*>(paramA);
324 result = sManager->modifySession(static_cast<int>(sessionId), config);
325 ImsMediaEventHandler::SendEvent(
326 "VIDEO_RESPONSE_EVENT", kVideoModifySessionResponse, sessionId, result, paramA);
327 }
328 break;
329 case kVideoSendRtpHeaderExtension:
330 /** TODO: add implementation */
331 break;
332 case kVideoSetMediaQualityThreshold:
333 {
334 MediaQualityThreshold* threshold = reinterpret_cast<MediaQualityThreshold*>(paramA);
335
336 if (threshold != nullptr)
337 {
338 sManager->setMediaQualityThreshold(static_cast<int>(sessionId), threshold);
339 delete threshold;
340 }
341 }
342 break;
343 case kRequestVideoCvoUpdate:
344 case kRequestVideoBitrateChange:
345 case kRequestVideoIdrFrame:
346 case kRequestVideoSendNack:
347 case kRequestVideoSendPictureLost:
348 case kRequestVideoSendTmmbr:
349 case kRequestVideoSendTmmbn:
350 case kRequestRoundTripTimeDelayUpdate:
351 sManager->SendInternalEvent(event, sessionId, paramA, paramB);
352 break;
353 default:
354 break;
355 }
356 }
357
processEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)358 void VideoManager::ResponseHandler::processEvent(
359 uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
360 {
361 IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
362 paramA, paramB);
363
364 if (sManager == nullptr)
365 {
366 return;
367 }
368
369 android::Parcel parcel;
370
371 switch (event)
372 {
373 case kVideoOpenSessionSuccess:
374 case kVideoOpenSessionFailure:
375 parcel.writeInt32(event);
376 parcel.writeInt32(static_cast<int>(sessionId));
377
378 if (event == kVideoOpenSessionFailure)
379 {
380 // fail reason
381 parcel.writeInt32(static_cast<int>(paramA));
382 }
383
384 sManager->sendResponse(sessionId, parcel);
385 break;
386 case kVideoModifySessionResponse: // fall through
387 {
388 parcel.writeInt32(event);
389 parcel.writeInt32(static_cast<int>(paramA)); // result
390 VideoConfig* config = reinterpret_cast<VideoConfig*>(paramB);
391
392 if (config != nullptr)
393 {
394 config->writeToParcel(&parcel);
395 sManager->sendResponse(sessionId, parcel);
396 delete config;
397 }
398 }
399 break;
400 case kVideoFirstMediaPacketInd:
401 parcel.writeInt32(event);
402 sManager->sendResponse(sessionId, parcel);
403 break;
404 case kVideoPeerDimensionChanged:
405 parcel.writeInt32(event);
406 parcel.writeInt32(static_cast<int>(paramA));
407 parcel.writeInt32(static_cast<int>(paramB));
408 sManager->sendResponse(sessionId, parcel);
409 break;
410 case kVideoRtpHeaderExtensionInd:
411 // TODO : add implementation
412 break;
413 case kVideoMediaInactivityInd:
414 case kVideoBitrateInd:
415 parcel.writeInt32(event);
416 parcel.writeInt32(static_cast<int>(paramA));
417 sManager->sendResponse(sessionId, parcel);
418 break;
419 case kVideoDataUsageInd:
420 parcel.writeInt32(event);
421 parcel.writeInt64(static_cast<int>(paramA));
422 sManager->sendResponse(sessionId, parcel);
423 break;
424 case kVideoSessionClosed:
425 parcel.writeInt32(event);
426 parcel.writeInt32(static_cast<int>(sessionId));
427 sManager->sendResponse(sessionId, parcel);
428 break;
429 default:
430 break;
431 }
432 }
433