[VideoConference] Receiving video after login

Post your questions and bug-reports about our audio/video streaming add-on based on Red5 Server.

Moderators: Lapo, Bax

RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

[VideoConference] Receiving video after login

Postby RiccardoNL » 02 Apr 2013, 20:11

Hi all,

I'm playing around with RedBox's VideoConference Example. I got it thusfar working. If I click 'join conference', others can see me, and I can see others. So far, so good.
Personally, I would prefer to see others BEFORE clicking 'join conference'. Then the user can decide on it's own if it wants to be on cam or not, but it will be able to see others. A bit of the TinyChat idea ;).

How can I get this to work? This is my current code:

Code: Select all

/*
* SmartFoxServer 2X + RedBox Examples - VideoConference
* http://www.smartfoxserver.com
* (c) 2011 gotoAndPlay
*/
import com.smartfoxserver.v2.SmartFox;
import com.smartfoxserver.v2.core.SFSEvent;
import com.smartfoxserver.v2.redbox.AVCastManager;
import com.smartfoxserver.v2.redbox.data.LiveCast;
import com.smartfoxserver.v2.redbox.events.RedBoxCastEvent;
import com.smartfoxserver.v2.redbox.events.RedBoxConnectionEvent;
import com.smartfoxserver.v2.requests.CreateRoomRequest;
import com.smartfoxserver.v2.requests.RoomSettings;
import com.smartfoxserver.v2.util.ClientDisconnectionReason;

import components.CreateRoomPanel;

import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;


private var sfs:SmartFox;
private var alert:Alert;
private var createRoomPanel:CreateRoomPanel;
private var avCastMan:AVCastManager;

private function init():void
{
   // Get reference to SmartFoxServer connection
   sfs = loginPanel.connector.connection;
   sfs.addEventListener(SFSEvent.LOGIN, onLogin);
   sfs.addEventListener(SFSEvent.ROOM_JOIN, onRoomJoin);
   sfs.addEventListener(SFSEvent.CONNECTION_LOST, onConnectionLost);
   sfs.addEventListener(SFSEvent.ROOM_CREATION_ERROR, onRoomCreationError);
}

//---------------------------------
// User interaction event handlers
//---------------------------------

/**
 * Create room button click event listener.
 * Show a popup panel where user can set the room properties.
 */
private function onCreateRoomApplicationBtClick():void
{
   createRoomPanel = PopUpManager.createPopUp(this, CreateRoomPanel, true) as CreateRoomPanel;
   PopUpManager.centerPopUp(createRoomPanel);
   createRoomPanel.addEventListener(CloseEvent.CLOSE, onPopUpClosed, false, 0, true);
}

/**
 * Create room button click event listener.
 * Create a new room using the parameters entered in the create room pupup.
 */
public function onCreateRoomPopuUpBtClick():void
{
   if (createRoomPanel.ti_roomName.length > 0)
   {
      // Collect room settings
      var settings:RoomSettings = new RoomSettings(createRoomPanel.ti_roomName.text);
      settings.groupId = createRoomPanel.lb_group.text;
      settings.maxUsers = createRoomPanel.ns_maxUsers.value;
      
      // Create room
      var request:CreateRoomRequest = new CreateRoomRequest(settings, true, sfs.lastJoinedRoom);
      sfs.send(request);
      
      // Close popup
      removePopUp();
   }
}

/**
 * Join video conference
 */
public function onJoinConfBtClick():void
{
   // Retrieve live casts already available
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
   }
   
   // Publish my live cast
   try
   {
      var myStream:NetStream = avCastMan.publishLiveCast(true, true);
      
      if (myStream != null)
      {
         // Attach camera output
         myVCItem.attachCamera(Camera.getCamera());
         
         bt_joinConf.enabled = false;
         bt_leaveConf.enabled = true;
      }
   }
   catch (e:Error)
   {
      var error:String = "The following error occurred while trying to subscribe a live cast: " + e.message;
      
      // Show alert
      showAlert(error);
   }
}

/**
 * Leave video conference
 */
public function onLeaveConfBtClick():void
{
   // Stop receiveing cast publish/unpublish notification
   avCastMan.stopPublishNotification();
   
   // Retrieve live casts
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Unsubscribe cast
      avCastMan.unsubscribeLiveCast(liveCast.id);
   }
   
   // Unpublish my live cast
   avCastMan.unpublishLiveCast();
   
   // Reset video conference container
   resetVideoConference();
}

private function onAlertClosed(evt:Event):void
{
   removeAlert();
}

private function onPopUpClosed(evt:Event):void
{
   removePopUp();
}

//---------------------------------
// SmartFoxServer event handlers
//---------------------------------

/**
 * On login, show the chat view.
 */
private function onLogin(evt:SFSEvent):void
{
   // Move to chat view, and display user name
   mainView.selectedChild = view_chat;
   lb_myUserName.text = sfs.mySelf.name;
   
   
   // Initialize AVCastManager
   initializeAV();
   
}

/**
 * When leaving a room to join a new one, the currnt user also leaves the previous video conference (if any).
 * For this reason we have to reset the join/leave conference buttons and stop the camera capture.
 */
public function onRoomJoin(evt:SFSEvent):void
{
   resetVideoConference();
}

/**
 * On connection lost, go back to login panel view and display disconnection error message.
 */
private function onConnectionLost(evt:SFSEvent):void
{
   // Remove popup, if any
   removePopUp();
   
   // Remove alert, if displayed
   removeAlert();
   
   // Remove listeners added to AVCastManager instance
   if (avCastMan != null)
   {
      avCastMan.removeEventListener(RedBoxConnectionEvent.AV_CONNECTION_INITIALIZED, onAVConnectionInited);
      avCastMan.removeEventListener(RedBoxConnectionEvent.AV_CONNECTION_ERROR, onAVConnectionError);
      avCastMan.removeEventListener(RedBoxCastEvent.LIVE_CAST_PUBLISHED, onLiveCastPublished);
      avCastMan.removeEventListener(RedBoxCastEvent.LIVE_CAST_UNPUBLISHED, onLiveCastUnpublished);
      avCastMan = null;
   }
   
   // Show disconnection message, unless user chose voluntarily to close the connection
   if (evt.params.reason != ClientDisconnectionReason.MANUAL)
   {
      var msg:String = "Connection lost";
      
      switch (evt.params.reason)
      {
         case ClientDisconnectionReason.IDLE:
            msg += "\nYou have exceeded the maximum user idle time";
            break;
         
         case ClientDisconnectionReason.KICK:
            msg += "\nYou have been kicked";
            break;
         
         case ClientDisconnectionReason.BAN:
            msg += "\nYou have been banned";
            break;
         
         case ClientDisconnectionReason.UNKNOWN:
            msg += " due to unknown reason\nPlease check the server-side log";
            break;
      }
      
      loginPanel.ta_error.text = msg;
   }
   
   // Show login view
   mainView.selectedChild = view_connecting;
}

/**
 * On room creation error, show an alert.
 */
private function onRoomCreationError(evt:SFSEvent):void
{
   // Show alert
   showAlert("Unable to create room due to the following error: " + evt.params.errorMessage);
}

//---------------------------------------------------------------------
// RedBox AVCastManager event handlers
//---------------------------------------------------------------------

/**
 * Handle A/V connection initialized.
 */
public function onAVConnectionInited(evt:RedBoxConnectionEvent):void
{
   // Nothing to do. Usually we should wait this event before enabling the a/v chat related interface elements.
}

/**
 * Handle A/V connection error.
 */
public function onAVConnectionError(evt:RedBoxConnectionEvent):void
{
   var error:String = "The following error occurred while trying to establish an A/V connection: " + evt.params.errorCode;
   
   // Show alert
   showAlert(error);
}

/**
 * Handle new live cast published by user
 */
public function onLiveCastPublished(evt:RedBoxCastEvent):void
{
   var liveCast:LiveCast = evt.params.liveCast;
   
   trace ("User " + liveCast.username + " published his live cast");
   
   // Subscribe live cast and add to video container
   addLiveCast(liveCast);
}

/**
 * Handle live cast unpublished by user
 */
public function onLiveCastUnpublished(evt:RedBoxCastEvent):void
{
   var liveCast:LiveCast = evt.params.liveCast;
   
   trace ("User " + liveCast.username + " unpublished his live cast");
   
   // When a user unpublishes his live cast, the AVCastManager instance automatically unsubscribes
   // that cast for the current user, so we just have to remove his video from the stage
   
   // Remove item from video container
   videoContainer.removeChild(videoContainer.getChildByName("user_" + liveCast.userId));
}

//---------------------------------
// Other methods
//---------------------------------

/**
 * Initialize the AVChatManager instance.
 */
private function initializeAV():void
{
   // Create AVChatmanager instance
   avCastMan = new AVCastManager(sfs, sfs.currentIp, false, true);
   
   avCastMan.addEventListener(RedBoxConnectionEvent.AV_CONNECTION_INITIALIZED, onAVConnectionInited);
   avCastMan.addEventListener(RedBoxConnectionEvent.AV_CONNECTION_ERROR, onAVConnectionError);
   avCastMan.addEventListener(RedBoxCastEvent.LIVE_CAST_PUBLISHED, onLiveCastPublished);
   avCastMan.addEventListener(RedBoxCastEvent.LIVE_CAST_UNPUBLISHED, onLiveCastUnpublished);
}

/**
 * Add live cast to video container
 */
private function addLiveCast(liveCast:LiveCast):void
{
   // Subscribe cast
   var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id);
   
   if (stream != null)
   {
      // Add item to video container
      var item:VideoConferenceItem = new VideoConferenceItem();
      item.name = "user_" + liveCast.userId;
      
      videoContainer.addChild(item);
      
      // Attach stream to item
      item.setLabelText(liveCast.username);
      item.attachStream(stream);
   }
}

/**
 * Reset video conference container
 */
public function resetVideoConference():void
{
   // Retrieve live casts
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Remove item from video container
      videoContainer.removeChild(videoContainer.getChildByName("user_" + liveCast.userId));
   }
   
   // Stop camera output
   myVCItem.reset(sfs.mySelf.name + " (me)");
   
   bt_joinConf.enabled = true;
   bt_leaveConf.enabled = false;
}

private function showAlert(message:String):void
{
   // Remove previous alert, if any
   removeAlert();
   
   // Show alert
   alert = Alert.show(message, "Warning", Alert.OK, null, onAlertClosed);
}

private function removeAlert():void
{
   if (alert != null)
      PopUpManager.removePopUp(alert);
   
   alert = null;
}

private function removePopUp():void
{
   if (createRoomPanel != null)
   {
      createRoomPanel.removeEventListener(CloseEvent.CLOSE, onPopUpClosed);
      PopUpManager.removePopUp(createRoomPanel);
      createRoomPanel = null;
   }
}


I already tried a lot of things, like adding GetAvailablecasts after the login, but that didn't work either.

Thanks in advance,

Riccardo
User avatar
Bax
Site Admin
Posts: 4397
Joined: 29 Mar 2005, 09:50
Location: Italy
Contact:

Re: [VideoConference] Receiving video after login

Postby Bax » 03 Apr 2013, 08:27

In order to be able to get the list of available casts you have to be inside a Room.
You could add the code that subscribes the available casts in the ROOM JOIN event listener. So as soon as you enter the Room, you start receiving other people's casts.
You can then have a separate button which just publishes the user's own cast.
Paolo Bax
The SmartFoxServer Team
RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

Re: [VideoConference] Receiving video after login

Postby RiccardoNL » 04 Apr 2013, 17:52

Hi Bax,

Thank you for your quick reply. I tried subscribing to the cast, but unfortunately with no luck :(.
This is the code I tried:

Code: Select all

public function onRoomJoin(evt:SFSEvent):void
{
   resetVideoConference();
   showAlert("Welcome to our video chat service. Have fun!");
      // Retrieve live casts already available
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
   }
}
   


What's wrong about this? I get no Flex-Errors, but it still refuses to load anything.
RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

Re: [VideoConference] Receiving video after login

Postby RiccardoNL » 05 Apr 2013, 00:10

So I spent an another 7 hours, with a very poor result: only errors and more errors. Even subscribing to casts, as Bax suggested, didn't do any tricks, but giving me headaches.

Code: Select all

public function onRoomJoin(evt:SFSEvent):void
{
resetVideoConference;
}
   // Retrieve live casts already available
for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
{
// Subscribe live cast
var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id);
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
 }
}
Only gave me syntax 1120 error.

I'm starting to wonder: do I need to edit VideoConference.as, or AVCastManager.as? It just doesn't do anything after joining the room. I'm obliged to "join the conference", to see the others. Starting to get really desperate now.
User avatar
Bax
Site Admin
Posts: 4397
Joined: 29 Mar 2005, 09:50
Location: Italy
Contact:

Re: [VideoConference] Receiving video after login

Postby Bax » 05 Apr 2013, 07:33

I really don't get what the problem is.
I think you should start back from the original VideoConference example.
The key method is onJoinConfBtClick():

Code: Select all

public function onJoinConfBtClick():void
{
   // Retrieve live casts already available
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
   }
   
   // Publish my live cast
   try
   {
      var myStream:NetStream = avCastMan.publishLiveCast(true, true);
      
      if (myStream != null)
      {
         // Attach camera output
         myVCItem.attachCamera(Camera.getCamera());
         
         bt_joinConf.enabled = false;
         bt_leaveConf.enabled = true;
      }
   }
   catch (e:Error)
   {
      var error:String = "The following error occurred while trying to subscribe a live cast: " + e.message;
      
      // Show alert
      showAlert(error);
   }
}

First of all this method is called when you click a button in the interface, but you could remove that button and call the method as soon as the Room is joined (you already have the onRoomJoin listener available that you can modify adding a call to onJoinConfBtClick).

Then, if you don't want the current user cast to be published, but allow the user to see the other people, simply remove the second part of the method (after the "Publish my live cast" comment).

If you want the user to be able to show himself later, add a button and move the "Publish my live cast" code in its click listener.
Paolo Bax
The SmartFoxServer Team
RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

Re: [VideoConference] Receiving video after login

Postby RiccardoNL » 05 Apr 2013, 11:47

Hi Bax,

I tried exactly as you said, but unfortunately it doesn't work that easily. Of course it should work in theory, but reality shows something different.
My code:

Code: Select all

public function onRoomJoin(evt:SFSEvent):void
{
   // Retrieve live casts already available
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
   }
}


and

Code: Select all

public function onJoinConfBtClick():void
{
   // Retrieve live casts already available
   for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
   {
      // Subscribe live cast and add to video container
      addLiveCast(liveCast);
   }
   
   // Publish my live cast
   try
   {
      var myStream:NetStream = avCastMan.publishLiveCast(true, true);
      
      if (myStream != null)
      {
         // Attach camera output
         myVCItem.attachCamera(Camera.getCamera());
         
         bt_joinConf.enabled = false;
         bt_leaveConf.enabled = true;
      }
   }
   catch (e:Error)
   {
      var error:String = "The following error occurred while trying to subscribe a live cast: " + e.message;
      
      // Show alert
      showAlert(error);
   }
}


So, basically, it should retrieve and show the available casts, after joining. That's what the code says, right? Instead still nothing shows up, until I click the button.
I copy pasted it from the original ActionScript file....
RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

Re: [VideoConference] Receiving video after login

Postby RiccardoNL » 05 Apr 2013, 12:01

Hmm,

I tested it by only making a button that receive the casts, but not publish my own cast. That worked. It looks like SmartFox is having really hard times on fetching the casts IMMEDIATELY after joining the room. If I want it to show me an alert after joining the room (I tested it, just to see if SmartFox is willing to do anything), it will show me an alert. But it just can't receive camera's immediately after joining.

Update: I fixed this by showing a special alert after joining the room. When clicking on "OK", you get to see the cams from the other users, without publishing yours.

Riccardo
User avatar
Bax
Site Admin
Posts: 4397
Joined: 29 Mar 2005, 09:50
Location: Italy
Contact:

Re: [VideoConference] Receiving video after login

Postby Bax » 05 Apr 2013, 14:51

Ok, I tried this personally and actually the issue is related to how the application is designed.

In our example, due to the fact that the user joins a conference by clicking the button (which happens at least a couple of seconds after the Room is joined), we didn't care of the events sequence. But as you are modifying the application behavior, you have to!

In fact the list of available live casts can be retrieved after the AV_CONNECTION_INITIALIZED event is dispatched only. As in the original example we are not waiting for this event to be dispatched, trying to get the list of cast during the first room join has no effect.

Also, the AVCastManager itself is listening to the ROOM_JOIN event, so requesting the list of available casts in that event could lead to unpredictable behavior, because it depends on which one (between your application and the inner AVCastManager class) processes the event first: if the AVCastManager then all right; if you application then it won't work). In my test for example my application tried to retrieve the list of live casts before the AVCastManager class created it.
For this reason you have to wait a little tile (1 frame is enough) after joining a Room before the list of live casts is available.

What you need to do is:
1) connect and login (IMPORTANT: do not make the RoomList component automatically join the Lobby Room);
2) initialize the AVCastManager class and wait for the AV_CONNECTION_INITIALIZED event to be dispatched;
3) join the Lobby Room;
4) when you receive the ROOM_JOIN event, wait 1 frame and then proceed with the code which gets the list of live casts and subscribes them.

Now everything should work as expected.

I start to believe my problem is a bug in SmartFoxServer. I checked the forums and I've seen that problem has been around since 2009?

As I explained above, there's no bug; it just that you have to write your application in the appropriate way, depending on what you need to achieve.
Also I would like to know which problem is around since 2009...
Paolo Bax
The SmartFoxServer Team
RiccardoNL
Posts: 35
Joined: 01 Apr 2013, 20:53

Re: [VideoConference] Receiving video after login

Postby RiccardoNL » 05 Apr 2013, 16:31

Hi Bax,

Then that might be the problem: in my script, the user automatically joins a room. However, my alert-workaround works good for what I wanted to achieve :). Thanks for your help on the subscribing to casts part.

That problem I'm talking about, is a race-problem. You just described it aswell. In this topic (viewtopic.php?t=6076) you see a similar problem. The topicstarter wants a similar thing as I want, but he can't subscribe to a cast immediately after joining a room either.

Riccardo

Return to “RedBox 2X”

Who is online

Users browsing this forum: No registered users and 3 guests