Expand my Community achievements bar.

Exclude local camera (spacing) in webCamSubscriber

Avatar

Level 1

Hi,

I'm working with peer to peer video for two people and would like to display only the remote client's webcam on one end, not both (local and remote).

I'm using webCamSubscriber without the webCamPublisher attribute specified which does not show the local camera, but it still leaves space for the local camera in the display.

Is there a way to have the webCamSubscriber use all available space for the remote camera?

Thanks

Kyle

8 Replies

Avatar

Former Community Member

Hi,

You are seeing the blank image because you are actually subscribing to

all streams, but since your subscriber doesn't have the publisher, you

are seeing that part as black( as the stream's size etc is there but the

video isn't). So, this isn't the right way.

The way to go about this is use publisherIDs property in

WebcamSubscriber. In your case, for the subscriber, you should set that

array to one element i.e. to the publisherID of the other user. In this

way, you won't see yours and only see the other user's camera stream in

Subscriber.

If you need some reference on publisherIDs property, you can take a look

at the WebCamera example under sampleApps.

Hope this helps

Thanks

Hironmay Basu

Avatar

Level 1

Thanks for the quick response, Hironmay!  I'm now stuck on another issue.

There are two different AIR clients for this application:  End Users and Attendants.  The end user (largeCam) app will provide the end user with a large camera view of the attendant, while the attendant app provides a small view of *both* cameras.

I need to automatically publish the camera of the attendant to the large cam when the attendant connects to the room (the end user is already connected and waiting).

In the samples I've included below, everything works fine except for programmatically setting the sharedProperty.  The non-functioning line I've tried is line 194 of smallCams.mxml (first file below).

Any insight you can give me would be greatly appreciated.

Kyle

smallCams.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                            xmlns:s="library://ns.adobe.com/flex/spark"
                            xmlns:mx="library://ns.adobe.com/flex/mx"
                            xmlns:rtc="http://ns.adobe.com/rtc">
     <fx:Script>
          <![CDATA[
               import com.adobe.rtc.sharedManagers.descriptors.UserDescriptor;
               import com.adobe.rtc.messaging.UserRoles;
               import com.adobe.rtc.events.ConnectSessionEvent;
               import mx.controls.Button;
               import com.adobe.coreUI.controls.CameraUserBar;
               import mx.core.UITextField;
               import mx.controls.LinkButton;
               import com.adobe.rtc.events.SharedPropertyEvent;
               import com.adobe.rtc.sharedModel.SharedProperty;
               import com.adobe.rtc.collaboration.WebcamSubscriber;
               import mx.containers.VBox;
               import com.adobe.rtc.events.UserEvent;
               import com.adobe.rtc.sharedManagers.StreamManager ;
               import com.adobe.rtc.sharedManagers.descriptors.StreamDescriptor ;
               
               private var currentSubscriber:WebcamSubscriber ;
               private var sharedProperty:SharedProperty ;
               
               /**********************************************************
                * This example shows how the camera component can be used with a publisher and a
                * number of subscribers. The publisher has a big view while subscribers have a small view.
                * A shared property is used to pass the stream to the publisher's user interface.
                * Every user is provided with play and pause handlers.
                * *********************************/
               
               /**********************************************************
                * ADOBE SYSTEMS INCORPORATED
                * Copyright [2007-2010] Adobe Systems Incorporated
                * All Rights Reserved.
                * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the
                * terms of the Adobe license agreement accompanying it.If you have received this file from a
                * source other than Adobe, then your use, modification, or distribution of it requires the prior
                * written permission of Adobe.
                * *********************************/
               
               private function onCreationComplete():void
               {
                    cSession.roomManager.autoPromote = true ;
                    cSession.roomManager.guestsHaveToKnock = false ;
                    
                    sharedProperty = new SharedProperty();
                    sharedProperty.isSessionDependent = true ;
                    sharedProperty.sharedID = "webcamShare2" ;
                    sharedProperty.connectSession = cSession ;
                    sharedProperty.subscribe();
                    // NO EVENT LISTENER NEEDED, SINCE LARGE STREAM IS NOT DISPLAYED
                    //sharedProperty.addEventListener(SharedPropertyEvent.CHANGE,onChange);
                    cSession.userManager.addEventListener(UserEvent.USER_REMOVE,onUserRemove)
               }
               
               /**
                * @private
                */
               protected function onUserRemove(p_event:UserEvent):void
               {
                    if ( sharedProperty.value && p_event.userDescriptor.userID == sharedProperty.value[0]) {
                         sharedProperty.value = [] ;
                    }
               }
               
               /**************
                * When the main big stream changes, all users can view it via the sharedProperty.
                *
                *
                * THIS FUNCTION IS NOT CALLED IN THIS VERSION
                *
                *
                *********************/
               private function onChange(p_evt:SharedPropertyEvent):void
               {
                    //if ( currentSubscriber != null ) {
                    //     clickedContainer.removeChild(currentSubscriber);
                    //     currentSubscriber.close();
                    //     currentSubscriber = null ;
                    //}
                    //
                    //if ( sharedProperty.value == null || sharedProperty.value.length == 0 ) {
                    //     return ;
                    //}
                    
                    
                    //currentSubscriber = new WebcamSubscriber();
                    //currentSubscriber.connectSession = cSession ;
                    //currentSubscriber.subscribe();
                    //currentSubscriber.webcamPublisher = webCamPub ;
                    //currentSubscriber.publisherIDs = sharedProperty.value ;
                    //currentSubscriber.addEventListener(UserEvent.USER_BOOTED,onCleared);
                    //currentSubscriber.addEventListener(UserEvent.STREAM_CHANGE,onCameraPause);
                    //clickedContainer.addChild(currentSubscriber);
                    //invalidateDisplayList();
                    
               }
               
               /************************
                * If the big image is stopped, clear it.
                *
                ********/
               private function onCleared(p_evt:UserEvent):void
               {
                    if ( cSession.userManager.myUserRole == UserRoles.OWNER ) {
                         sharedProperty.value = [] ;
                    }
               }
               
               /***********
                * Clicking on the small image below makes it large.
                *****/
               private function onClick(p_evt:MouseEvent):void
               {
                    
                    if ( (p_evt.currentTarget is WebcamSubscriber) &&  !(p_evt.target.parent is CameraUserBar)) {
                         sharedProperty.value = (p_evt.currentTarget as WebcamSubscriber).publisherIDs;
                    }
               }
               
               
               override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
               {
                    super.updateDisplayList(unscaledWidth,unscaledHeight);
                    
                    if ( currentSubscriber ) {
                         currentSubscriber.percentWidth = 100 ;
                         currentSubscriber.percentHeight = 100 ;
                    }
               }
               
               /****
                * Handler for a user stopping the camera.
                */
               private function onBooted(p_evt:UserEvent):void
               {
                    if ( (p_evt.currentTarget is  WebcamSubscriber) && (p_evt.userDescriptor.userID == cSession.userManager.myUserID || cSession.userManager.myUserRole == UserRoles.OWNER)) {
                         webCamPub.stop();
                         
                         if ( (p_evt.currentTarget.parent as VBox).getChildAt(1) is Button ){
                              ((p_evt.currentTarget.parent as VBox).getChildAt(1) as Button).label = "Start" ;
                         }
                         
                         if ( sharedProperty.value && (sharedProperty.value as Array)[0] == p_evt.userDescriptor.userID ) {
                              sharedProperty.value = [] ;
                         }
                    }
               }
               
               /**
                * Handler for a user pausing the camera.
                */
               protected function onCameraPause(p_evt:UserEvent):void
               {
                    var userStreams:Array = cSession.streamManager.getStreamsForPublisher(p_evt.userDescriptor.userID,StreamManager.CAMERA_STREAM);
                    
                    if (userStreams.length == 0) {
                         trace("onCameraPause: no userStreams");
                         return;
                    }
                    
                    for (var i:int = 0; i< userStreams.length ; i++ ) {
                         if (userStreams[i].type == StreamManager.CAMERA_STREAM ) {
                              break;
                         }
                    }
                    
                    var streamDescriptor:StreamDescriptor = userStreams[i];
                    if ( streamDescriptor.streamPublisherID == cSession.userManager.myUserID ) {
                         cSession.streamManager.pauseStream(StreamManager.CAMERA_STREAM,!streamDescriptor.pause,streamDescriptor.streamPublisherID);
                    }
               }
               
               /*****
                * Handler for the stop and start buttons.
                *******/
               private function onBtnClick(p_evt:MouseEvent):void
               {
                    if ( p_evt.currentTarget.label == "Start" ) {
                         webCamPub.publish();
                         p_evt.currentTarget.label = "Stop" ;
                    }else if (p_evt.currentTarget.label == "Stop" ){
                         webCamPub.stop();
                         p_evt.currentTarget.label = "Start" ;
                    }
               }

               protected function webCamPub_creationCompleteHandler(event:Event):void
               {
                    webCamPub.publish();
                    controlBtn.label = "Stop"
                    //sharedProperty.value = (event.currentTarget as WebcamSubscriber).publisherIDs;
               }
               
          ]]>
     </fx:Script>
     
     <fx:Declarations>
          <!--
          You would likely use external authentication here for a deployed application;
          you would certainly not hard code Adobe IDs here.
          -->
          <rtc:AdobeHSAuthenticator
               id="auth"
               userName="USERNAME"
               password="PASSWORD"  />
     </fx:Declarations>
     
     <rtc:ConnectSessionContainer id="cSession" authenticator="{auth}" width="100%"
                                         height="100%" roomURL="ROOMURL" >
          <mx:Panel title="Show Small Cameras" width="100%" height="100%"
                      paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" creationComplete="onCreationComplete()">
               <rtc:WebcamPublisher id="webCamPub" creationComplete="webCamPub_creationCompleteHandler(event)" width="10" height="5" resolutionFactor="5"/>
               
               <mx:VBox width="100%" height="100%" id="clickedContainer"/>
               <mx:HBox horizontalGap="10" verticalGap="15" paddingLeft="10" paddingTop="10" paddingBottom="10" paddingRight="10" width="100%" height="25%">
                    <mx:Repeater id="rp" dataProvider="{cSession.userManager.userCollection}" width="100%" height="100%" >
                         <mx:VBox width="100%" height="15%" horizontalAlign="center" horizontalGap="5">
                              <rtc:WebcamSubscriber webcamPublisher="{webCamPub}" width="100%" height="100%" publisherIDs="{[(rp.currentItem as UserDescriptor).userID]}" click="onClick(event)" userBooted="onBooted(event)" streamChange="onCameraPause(event)"/>
                              <mx:Button id="controlBtn" label="Start"  click="onBtnClick(event)"  visible="{(rp.currentItem as UserDescriptor).userID==cSession.userManager.myUserID}" />
                         </mx:VBox>
                    </mx:Repeater>   
               </mx:HBox>
               
          </mx:Panel>
     </rtc:ConnectSessionContainer>
</s:WindowedApplication>

largeCam.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                            xmlns:s="library://ns.adobe.com/flex/spark"
                            xmlns:mx="library://ns.adobe.com/flex/mx"
                            xmlns:rtc="http://ns.adobe.com/rtc">
     <fx:Script>
          <![CDATA[
               import com.adobe.coreUI.controls.CameraUserBar;
               import com.adobe.rtc.collaboration.WebcamSubscriber;
               import com.adobe.rtc.events.ConnectSessionEvent;
               import com.adobe.rtc.events.SharedPropertyEvent;
               import com.adobe.rtc.events.UserEvent;
               import com.adobe.rtc.messaging.UserRoles;
               import com.adobe.rtc.sharedManagers.StreamManager;
               import com.adobe.rtc.sharedManagers.descriptors.StreamDescriptor;
               import com.adobe.rtc.sharedManagers.descriptors.UserDescriptor;
               import com.adobe.rtc.sharedModel.SharedProperty;
               
               import mx.containers.VBox;
               import mx.controls.Button;
               import mx.controls.LinkButton;
               import mx.core.UITextField;
               
               private var currentSubscriber:WebcamSubscriber ;
               private var sharedProperty:SharedProperty ;
               
               /**********************************************************
                * This example shows how the camera component can be used with a publisher and a
                * number of subscribers. The publisher has a big view while subscribers have a small view.
                * A shared property is used to pass the stream to the publisher's user interface.
                * Every user is provided with play and pause handlers.
                * *********************************/
               
               /**********************************************************
                * ADOBE SYSTEMS INCORPORATED
                * Copyright [2007-2010] Adobe Systems Incorporated
                * All Rights Reserved.
                * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the
                * terms of the Adobe license agreement accompanying it.If you have received this file from a
                * source other than Adobe, then your use, modification, or distribution of it requires the prior
                * written permission of Adobe.
                * *********************************/
               
               private function onCreationComplete():void
               {
                    cSession.roomManager.autoPromote = true ;
                    cSession.roomManager.guestsHaveToKnock = false ;
                    
                    sharedProperty = new SharedProperty();
                    sharedProperty.isSessionDependent = true ;
                    sharedProperty.sharedID = "webcamShare2" ;
                    sharedProperty.connectSession = cSession ;
                    sharedProperty.subscribe();
                    sharedProperty.addEventListener(SharedPropertyEvent.CHANGE,onChange);
                    cSession.userManager.addEventListener(UserEvent.USER_REMOVE,onUserRemove)
               }
               
               /**
                * @private
                */
               protected function onUserRemove(p_event:UserEvent):void
               {
                    if ( sharedProperty.value && p_event.userDescriptor.userID == sharedProperty.value[0]) {
                         sharedProperty.value = [] ;
                    }
               }
               
               /**************
                * When the main big stream changes, all users can view it via the sharedProperty.
                *
                *********************/
               private function onChange(p_evt:SharedPropertyEvent):void
               {
                    if ( currentSubscriber != null ) {
                         clickedContainer.removeChild(currentSubscriber);
                         currentSubscriber.close();
                         currentSubscriber = null ;
                    }
                    
                    if ( sharedProperty.value == null || sharedProperty.value.length == 0 ) {
                         return ;
                    }
                    
                    
                    currentSubscriber = new WebcamSubscriber();
                    currentSubscriber.connectSession = cSession ;
                    currentSubscriber.subscribe();
                    currentSubscriber.webcamPublisher = webCamPub ;
                    currentSubscriber.publisherIDs = sharedProperty.value ;
                    currentSubscriber.addEventListener(UserEvent.USER_BOOTED,onCleared);
                    currentSubscriber.addEventListener(UserEvent.STREAM_CHANGE,onCameraPause);
                    clickedContainer.addChild(currentSubscriber);
                    invalidateDisplayList();
                    
               }
               
               /************************
                * If the big image is stopped, clear it.
                *
                ********/
               private function onCleared(p_evt:UserEvent):void
               {
                    if ( cSession.userManager.myUserRole == UserRoles.OWNER ) {
                         sharedProperty.value = [] ;
                    }
               }
               
               /***********
                * Clicking on the small image below makes it large.
                *****/
               private function onClick(p_evt:MouseEvent):void
               {
                    
                    if ( (p_evt.currentTarget is WebcamSubscriber) &&  !(p_evt.target.parent is CameraUserBar)) {
                         sharedProperty.value = (p_evt.currentTarget as WebcamSubscriber).publisherIDs;
                    }
               }
               
               
               override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
               {
                    super.updateDisplayList(unscaledWidth,unscaledHeight);
                    
                    if ( currentSubscriber ) {
                         currentSubscriber.percentWidth = 100 ;
                         currentSubscriber.percentHeight = 100 ;
                    }
               }
               
               /****
                * Handler for a user stopping the camera.
                */
               private function onBooted(p_evt:UserEvent):void
               {
                    if ( (p_evt.currentTarget is  WebcamSubscriber) && (p_evt.userDescriptor.userID == cSession.userManager.myUserID || cSession.userManager.myUserRole == UserRoles.OWNER)) {
                         webCamPub.stop();
                         
                         if ( (p_evt.currentTarget.parent as VBox).getChildAt(1) is Button ){
                              ((p_evt.currentTarget.parent as VBox).getChildAt(1) as Button).label = "Start" ;
                         }
                         
                         if ( sharedProperty.value && (sharedProperty.value as Array)[0] == p_evt.userDescriptor.userID ) {
                              sharedProperty.value = [] ;
                         }
                    }
               }
               
               /**
                * Handler for a user pausing the camera.
                */
               protected function onCameraPause(p_evt:UserEvent):void
               {
                    var userStreams:Array = cSession.streamManager.getStreamsForPublisher(p_evt.userDescriptor.userID,StreamManager.CAMERA_STREAM);
                    
                    if (userStreams.length == 0) {
                         trace("onCameraPause: no userStreams");
                         return;
                    }
                    
                    for (var i:int = 0; i< userStreams.length ; i++ ) {
                         if (userStreams[i].type == StreamManager.CAMERA_STREAM ) {
                              break;
                         }
                    }
                    
                    var streamDescriptor:StreamDescriptor = userStreams[i];
                    if ( streamDescriptor.streamPublisherID == cSession.userManager.myUserID ) {
                         cSession.streamManager.pauseStream(StreamManager.CAMERA_STREAM,!streamDescriptor.pause,streamDescriptor.streamPublisherID);
                    }
               }
               
               /*****
                * Handler for the stop and start buttons.
                *******/
               private function onBtnClick(p_evt:MouseEvent):void
               {
                    if ( p_evt.currentTarget.label == "Start" ) {
                         webCamPub.publish();
                         p_evt.currentTarget.label = "Stop" ;
                    }else if (p_evt.currentTarget.label == "Stop" ){
                         webCamPub.stop();
                         p_evt.currentTarget.label = "Start" ;
                    }
               }

               protected function webCamPub_creationCompleteHandler(event:Event):void
               {
                    webCamPub.publish();
               }
               
          ]]>
     </fx:Script>
     
     <fx:Declarations>
          <!--
          You would likely use external authentication here for a deployed application;
          you would certainly not hard code Adobe IDs here.
          -->
          <rtc:AdobeHSAuthenticator
               id="auth"
               userName="USERNAME"
               password="PASSWORD"  />
     </fx:Declarations>
     
     <rtc:ConnectSessionContainer id="cSession" authenticator="{auth}" width="100%"
                                         height="100%" roomURL="ROOMURL" >
          <mx:Panel title="Show Large Camera Only" width="100%" height="100%"
                      paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" creationComplete="onCreationComplete()">
               <rtc:WebcamPublisher id="webCamPub" creationComplete="webCamPub_creationCompleteHandler(event)" width="10" height="5" resolutionFactor="5"/>
               
               <mx:VBox width="100%" height="100%" id="clickedContainer"/>
               <!-- <mx:HBox horizontalGap="10" verticalGap="15" paddingLeft="10" paddingTop="10" paddingBottom="10" paddingRight="10" width="100%" height="25%">
                    <mx:Repeater id="rp" dataProvider="{cSession.userManager.userCollection}" width="100%" height="100%" >
                         <mx:VBox width="100%" height="15%" horizontalAlign="center" horizontalGap="5">
                              <rtc:WebcamSubscriber webcamPublisher="{webCamPub}" width="100%" height="100%" publisherIDs="{[(rp.currentItem as UserDescriptor).userID]}" click="onClick(event)" userBooted="onBooted(event)" streamChange="onCameraPause(event)"/>
                              <mx:Button  label="Start"  click="onBtnClick(event)"  visible="{(rp.currentItem as UserDescriptor).userID==cSession.userManager.myUserID}" />
                         </mx:VBox>
                    </mx:Repeater>   
               </mx:HBox> -->
               
          </mx:Panel>
     </rtc:ConnectSessionContainer>
</s:WindowedApplication>

Avatar

Former Community Member

I will run your files and get back. I need to look at your code before providing inputs.

Thanks

Hironmay Basu

Avatar

Level 1

Hironmay,

Both of these files are based on WebCamera.mxml in the sample apps.  If you have a diff tool, you should be able to easily see the differences.


Thanks again,

Kyle

Avatar

Level 1

Also - the "non-functioning line" I mentioned is commented out.

Kyle

Avatar

Former Community Member

Yes , I have seen that. Will get back, just looking I can't see the problem , so I need to run.

Thanks

Hironmay Basu

Avatar

Former Community Member

Hi,

I ran your code, there are some fundamental issues in your understanding I believe. You are trying to do (event.currentTarget as WebcamPublisher).publisherIDs whereas I told you that publisherIDs is a property of WebcamSubscriber and not WebcamPublisher. It gives while streams the Subscriber will play among all streams.

The example I gave had a different purpose so it was done that way, but your use case is different.

In your example, the smallCams if it has to play all streams, why do you even need multiple subscribers in a Repeater. Only one subscriber is capable of playing all streams in a grid layout.

Only in the case of largeCam, where you want to show only attendant camera stream, you might need to set the publisherIDs property in the subscriber to just have the attendent's userID.

Thanks

Hironmay Basu

Avatar

Level 1

Hironmay,

The only instance I see in the pasted code of "event.currentTarget" looks like it is WebCamSubscriber, not Publisher.  Is this perhaps another issue?

Also, I've made some of the changes you suggested (no repeater, etc.)  and I can set the sharedProperty via a mouse click, but when I try to do  it programatically, it seems the same error happens as in this sample -  the sharedProperty isn't yet defined.

What I'm trying to do is this:

1. Launch largeCam AIR application on computer 1 (this works)

2. webCam starts publishing on computer 1 (this works)

3. Launch smallCams AIR application on computer 2 (this works)

4. webCam starts publishing on computer 2 (this works)

5. computer 2 (without additional user interaction) sets sharedProperty.value to [cSession.userManager.myUserID]

6. computer 1 sees that change to sharedProperty.value and runs the onChange event (the EventListener on the sharedProperty)

I am unable to get step 5 to succeed UNLESS I do it *with* user interaction by having the computer 2 user click on the small video to publish it. It fails with an error that appears to be the sharedProperty not existing.

Kyle