/* Ċ Ġ* ĠCopyright ĠAmazon . com , ĠInc . Ġor Ġits Ġaffiliates . ĠAll ĠRights ĠReserved . Ċ Ġ* ĠSPDX - License - Identifier : ĠApache - 2 . 0 Ċ Ġ*/ Ċ Ċ package Ġcom . amazonaws . services . ch ime . sdk . meet ings . audio video . video Ċ Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . analytics . Meeting Stats Collector Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . audio video . video . gl . E gl Core Factory Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . audio video . video . gl . E gl Video Render View Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . internal . utils . Observer Utils Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . internal . video . Video Client Controller Ċ import Ġcom . amazonaws . services . ch ime . sdk . meet ings . utils . logger . Logger Ċ Ċ class ĠDefault Video Tile Controller ( ĊĠĠĠ Ġprivate Ġval Ġlogger : ĠLogger , ĊĠĠĠ Ġprivate Ġval Ġvideo Client Controller : ĠVideo Client Controller , ĊĠĠĠ Ġprivate Ġval Ġvideo Tile Factory : ĠVideo Tile Factory , ĊĠĠĠ Ġprivate Ġval Ġe gl Core Factory : ĠE gl Core Factory , ĊĠĠĠ Ġprivate Ġval Ġmeeting Stats Collector : ĠMeeting Stats Collector Ċ ) Ġ: ĠVideo Tile Controller Ġ{ ĊĠĠĠ Ġ// ĠA Ġmap Ġof Ġtile Ġid Ġto ĠVideo Tile Ġto Ġdetermine Ġif ĠVideo Tile Controller Ġis Ġadding , Ġremoving , Ġpa using , Ġor Ġrendering ĊĠĠĠ Ġprivate Ġval Ġvideo Tile Map Ġ= Ġmutable Map Of < Int , ĠVideo Tile >() ĊĠĠĠ Ġ// ĠA Ġmap Ġof ĠVideo Render View Ġto ĠVideo Tile Ġto Ġdetermine Ġif Ġusers Ġare Ġadding Ġsame Ġvideo Ġrender Ġview ĊĠĠĠ Ġprivate Ġval Ġrender View To Bound Video Tile Map Ġ= Ġmutable Map Of < Video Render View , ĠVideo Tile >() ĊĠĠĠ Ġprivate Ġval ĠTAG Ġ= Ġ" Default Video Tile Controller " ĊĊĠĠĠ Ġprivate Ġvar Ġvideo Tile Observer s Ġ= Ġmutable Set Of < Video Tile Observer >() ĊĊĠĠĠ Ġoverride Ġfun Ġon Receive Frame ( ĊĠĠĠĠĠĠĠ Ġframe : ĠVideo Frame ?, ĊĠĠĠĠĠĠĠ Ġvideo Id : ĠInt , ĊĠĠĠĠĠĠĠ Ġat tendee Id : ĠString ?, ĊĠĠĠĠĠĠĠ Ġpause State : ĠVideo Pause State ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠThere Ġare ĠFO UR Ġpossible Ġoutcomes : ĊĠĠĠĠĠĠĠĠ Ġ* Ġ 1 ) ĠCreate Ġ- ĠSome one Ġhas Ġstarted Ġsharing Ġvideo ĊĠĠĠĠĠĠĠĠ Ġ* Ġ 2 ) ĠRender Ġ/ ĠResume Ġ- ĠSome one Ġis Ġsending Ġnew Ġframes Ġfor Ġtheir Ġvideo ĊĠĠĠĠĠĠĠĠ Ġ* Ġ 3 ) ĠPause Ġ- ĠSome one Ġis Ġsending Ġa Ġpause Ġframe ĊĠĠĠĠĠĠĠĠ Ġ* Ġ 4 ) ĠStop Ġ- ĠSome one Ġhas Ġstopped Ġsharing Ġvideo ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* ĠIn Ġboth Ġpause Ġand Ġstop Ġcases , Ġthe Ġframe Ġis Ġnull Ġbut Ġthe Ġpause Type Ġdiffers ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġval Ġtile : ĠVideo Tile ? Ġ= Ġvideo Tile Map [ video Id ] ĊĊĠĠĠĠĠĠĠ Ġval Ġvideo Stream Content Width Ġ= Ġframe ?. width Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠ Ġval Ġvideo Stream Content Height Ġ= Ġframe ?. height Ġ?: Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġif Ġ( tile Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( frame Ġ== Ġnull Ġ&& Ġpause State Ġ== ĠVideo Pause State . Un paused ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Removing Ġvideo Ġtile Ġwith Ġvideo Id Ġ= Ġ$ video Id Ġ& Ġat tendee Id Ġ= Ġ$ at tendee Id " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Remove Video Tile ( video Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( frame Ġ!= Ġnull Ġ&& Ġ( video Stream Content Width Ġ!= Ġtile . state . video Stream Content Width Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvideo Stream Content Height Ġ!= Ġtile . state . video Stream Content Height )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtile . state . video Stream Content Width Ġ= Ġvideo Stream Content Width ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtile . state . video Stream Content Height Ġ= Ġvideo Stream Content Height ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Size Changed ( tile . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAccount Ġfor Ġany Ġinternally Ġchanged Ġpause Ġstates , Ġbut Ġignore Ġif Ġthe Ġtile Ġis Ġpaused Ġby ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġuser Ġsince Ġthe Ġpause Ġmight Ġnot Ġhave Ġpropag ated Ġyet ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pause State Ġ!= Ġtile . state . pause State Ġ&& Ġtile . state . pause State Ġ!= ĠVideo Pause State . Paused By UserRequest ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNote Ġthat Ġcurrently , Ġsince Ġwe Ġpre empt ively Ġmark Ġtiles Ġas ĠPause d By UserRequest Ġwhen Ġrequested Ġby Ġuser ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġpath Ġwill Ġonly Ġbe Ġhit Ġwhen Ġwe Ġare Ġeither Ġtransition ing Ġfrom Ġ. un paused Ġto ĠPause d For Po or Connection ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġor ĠPause d For Po or Connection Ġto ĠUn paused ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtile . set Pause State ( pause State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pause State Ġ== ĠVideo Pause State . Un paused ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Res umed ( tile . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Paused ( tile . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIgnore Ġany Ġframes Ġwhich Ġcome Ġto Ġan Ġalready Ġpaused Ġtile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( tile . state . pause State Ġ== ĠVideo Pause State . Un paused ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġframe ?. run Ġ{ Ġtile . on Video Frame Received ( frame ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . verbose ( TAG , Ġ" Ign oring Ġvideo Ġframe Ġreceived Ġon Ġpaused Ġtile ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( frame Ġ!= Ġnull Ġ|| Ġpause State Ġ!= ĠVideo Pause State . Un paused ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Adding Ġvideo Ġtile Ġwith Ġvideo Id Ġ= Ġ$ video Id , Ġat tendee Id Ġ= Ġ$ at tendee Id , Ġpause State Ġ= Ġ$ pause State " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Add Video Tile ( video Id , Ġat tendee Id , Ġpause State , Ġvideo Stream Content Width , Ġvideo Stream Content Height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġadd Video Tile Observer ( observer : ĠVideo Tile Observer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvideo Tile Observer s . add ( observer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġremove Video Tile Observer ( observer : ĠVideo Tile Observer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvideo Tile Observer s . remove ( observer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġpause Remote Video Tile ( tile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvideo Tile Map [ tile Id ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . state . is Local Tile ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( TAG , Ġ" Cannot Ġpause Ġlocal Ġvideo Ġtile Ġ$ tile Id !") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Pa using Ġtile Ġ$ tile Id ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvideo Client Controller . set Remote Paused ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtile Id ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDon 't Ġupdate Ġstate / ob servers Ġif Ġwe Ġhaven 't Ġchanged Ġanything ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNote Ġthat Ġthis Ġwill Ġoverwrite ĠPause d For Po or Connection Ġif Ġthat Ġis Ġthe Ġcurrent Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . state . pause State Ġ!= ĠVideo Pause State . Paused By UserRequest ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . set Pause State ( Video Pause State . Paused By UserRequest ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Paused ( it . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġresume Remote Video Tile ( tile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvideo Tile Map [ tile Id ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . state . is Local Tile ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( TAG , Ġ" Cannot Ġresume Ġlocal Ġvideo Ġtile Ġ$ tile Id !") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Res uming Ġtile Ġ$ tile Id ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvideo Client Controller . set Remote Paused ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtile Id ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOnly Ġupdate Ġstate Ġif Ġwe Ġare Ġun pa using Ġa Ġtile Ġwhich Ġwas Ġpreviously Ġpaused Ġby Ġthe Ġuser ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNote Ġthat Ġthis Ġmeans Ġres uming Ġa Ġtile Ġwith Ġstate ĠPause d For Po or Connection Ġwill Ġno - op ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . state . pause State Ġ== ĠVideo Pause State . Paused By UserRequest ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . set Pause State ( Video Pause State . Un paused ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Res umed ( it . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġbind Video View ( video View : ĠVideo Render View , Ġtile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Binding ĠVideo View Ġto ĠTile Ġwith Ġtile Id Ġ= Ġ$ tile Id ") ĊĊĠĠĠĠĠĠĠ Ġrender View To Bound Video Tile Map [ video View ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . state . tile Id Ġ== Ġtile Id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Already Ġbinding Ġwith Ġthe Ġtile ĠId Ġ$ tile Id , Ġignore ...") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( TAG , Ġ" Override Ġthe Ġbinding Ġfrom Ġ${ it . state . tile Id } Ġto Ġ$ tile Id ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove Render View From Bound Video Tile Map ( it . state . tile Id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġvideo Tile Map [ tile Id ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . video Render View ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" tile Id Ġ= Ġ$ tile Id Ġalready Ġhad Ġa Ġdifferent Ġvideo Ġview . ĠU nb ind ing Ġthe Ġold Ġone Ġand Ġassoci ating Ġthe Ġnew Ġone ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremove Render View From Bound Video Tile Map ( tile Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( video View Ġis ĠE gl Video Render View ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Initializing ĠE GL Ġstate Ġon ĠE GL Ġrender Ġview ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvideo View . init ( e gl Core Factory ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . bind ( video View ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrender View To Bound Video Tile Map [ video View ] Ġ= Ġit ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġremove Render View From Bound Video Tile Map ( tile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġrender View To Bound Video Tile Map . entries . first OrNull Ġ{ Ġit . value . state . tile Id Ġ== Ġtile Id Ġ} ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrender View Ġ= Ġit . key ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvideo Tile Ġ= Ġit . value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvideo Tile . unbind () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( render View Ġis ĠE gl Video Render View ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Re leasing ĠE GL Ġstate Ġon ĠE GL Ġrender Ġview ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrender View . release () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrender View To Bound Video Tile Map . remove ( render View ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġun bind Video View ( tile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . info ( TAG , Ġ" Un binding ĠTile Ġwith Ġtile Id Ġ= Ġ$ tile Id ") ĊĠĠĠĠĠĠĠ Ġ// ĠRemove Ġthe Ġvideo Ġfrom Ġboth Ġmappings Ġwhen Ġun bind , Ġin Ġorder Ġto Ġkeep Ġthe Ġold ĠSDK Ġbehavior ĊĠĠĠĠĠĠĠ Ġvideo Tile Map . remove ( tile Id ) ĊĠĠĠĠĠĠĠ Ġremove Render View From Bound Video Tile Map ( tile Id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġon Remove Video Tile ( tile Id : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvideo Tile Map [ tile Id ]?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Removed ( it . state ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvideo Tile Map . remove ( tile Id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġon Add Video Tile ( tile Id : ĠInt , Ġat tendee Id : ĠString ?, Ġpause State : ĠVideo Pause State , Ġvideo Stream Content Width : ĠInt , Ġvideo Stream Content Height : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġis Local Tile : ĠBoolean ĊĠĠĠĠĠĠĠ Ġval Ġthis At tendee Id : ĠString ĊĊĠĠĠĠĠĠĠ Ġif Ġ( at tendee Id Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis At tendee Id Ġ= Ġat tendee Id ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Local Tile Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis At tendee Id Ġ= Ġvideo Client Controller . getConfiguration (). credentials . at tendee Id ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Local Tile Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġtile Ġ= Ġvideo Tile Factory . make Tile ( tile Id , Ġthis At tendee Id , Ġvideo Stream Content Width , Ġvideo Stream Content Height , Ġis Local Tile ) ĊĠĠĠĠĠĠĠ Ġvideo Tile Map [ tile Id ] Ġ= Ġtile ĊĠĠĠĠĠĠĠ Ġmeeting Stats Collector . update Max Video Tile ( video Tile Map . size ) ĊĠĠĠĠĠĠĠ Ġtile . set Pause State ( pause State ) ĊĠĠĠĠĠĠĠ ĠforEach Observer Ġ{ Ġobserver Ġ-> Ġobserver . on Video Tile Added ( tile . state ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠforEach Observer ( observer Function : Ġ( observer : ĠVideo Tile Observer ) Ġ-> ĠUnit ) Ġ{ ĊĠĠĠĠĠĠĠ ĠObserver Utils . notify Observer On MainThread ( video Tile Observer s , Ġobserver Function ) ĊĠĠĠ Ġ} Ċ } Ċ