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