Listing 1

application.onAppStart = function()
{
	trace("Begin sharing text");

	// Get the server shared object 'users_so'
	application.users_so = SharedObject.get("users_so", false);
}

application.onConnect = function(client, name, identifier)
{
	client.identifier = identifier;
	application.users_so.setProperty(identifier, name);
	application.acceptConnection(client);
}


application.onDisconnect = function(client)
{
	trace("disconnect: " + client.identifier);
	application.users_so.setProperty(client.identifier, null);
}

Listing 2

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns="*"
	initialize="haveCamera = ( Camera.getCamera() != null )"
	layout="vertical">
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			
			[Bindable]
			private var haveCamera:Boolean;
			
			[Bindable]
			public var nc:NetConnection;
			
			public var users_so:SharedObject;
			[Bindable]
			public var dpUsers:ArrayCollection;
			
			public function createConnection():void
			{
				if( txtName.text.length > 0 ) {
					nc = new NetConnection();
					nc.objectEncoding = ObjectEncoding.AMF0;
					nc.addEventListener( NetStatusEvent.NET_STATUS, netStatusHandler );
					var identifier:String = txtName.text;
					while( identifier.search( " " ) > 0 )
						identifier = identifier.replace( " ", "_" );
					nc.connect( "rtmp:/flex_videoconference/", txtName.text, identifier );
				} else {
					Alert.show( "Please provide a name for the video chat connection!" );
				}
			}
			
			public function netStatusHandler( event:NetStatusEvent ):void
			{
				switch( event.info.code ) {
					case "NetConnection.Connect.Success":
						connectComponents();
						vsMain.selectedChild = pnlVideo;
					break;
				}

			}

			public function connectComponents():void
			{
				SharedObject.defaultObjectEncoding  = flash.net.ObjectEncoding.AMF0;
				users_so = SharedObject.getRemote("users_so", nc.uri, false);
				users_so.addEventListener( SyncEvent.SYNC, usersSyncHandler );
				users_so.connect( nc );
			}

			public function usersSyncHandler( event:SyncEvent ):void
			{
				var results:Object = event.target.data;
				var usersArray:Array = new Array();
				for( var a:String in results ) {
					var obj:Object = new Object();
					obj.name = results[ a ];
					obj.identifier = a;
					usersArray.push( obj );
				}
				dpUsers = new ArrayCollection( usersArray );
			}

			public function logout():void
			{
				users_so.close();
				nc.close();
				dpUsers = null;
				users_so = null;
				nc = null;
				vsMain.selectedChild = pnlLogin;
			}
			
		]]>
	</mx:Script>

	<mx:ViewStack
		id="vsMain"
		width="100%" height="100%">
		<!-- Login Panel -->
		<mx:Panel id="pnlLogin">
			<mx:Form>
				<mx:FormItem label="Name:">
					<mx:TextInput 
						id="txtName"
						enabled="{ haveCamera }" />
				</mx:FormItem>
				<mx:Button label="Submit"
					click="createConnection()"
					enabled="{ haveCamera }" />
				<mx:Label text="{ ( haveCamera ) ? '':'Now camera is found!' }" />
			</mx:Form>
		</mx:Panel>
		<!-- Video Panel -->
		<mx:Panel id="pnlVideo"
			width="100%" height="100%"
			title="Welcome { txtName.text }!"
			layout="vertical">

			<mx:Tile height="100%" width="100%">
				<mx:Repeater id="rpUsers"
					dataProvider="{ dpUsers }">
					<VideoPod 
						nc="{ nc }"
						isSender="{ rpUsers.currentItem.name == txtName.text }"
						userItem="{ rpUsers.currentItem }" />
				</mx:Repeater>
			</mx:Tile>
			<mx:ControlBar>
				<mx:Button label="Logout"
					click="logout()"/>
			</mx:ControlBar>
		</mx:Panel>
		
	</mx:ViewStack>

</mx:Application>

Listing 3

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns="*"
	title="{ userItem.name } Pod"
	creationComplete="init()"
	layout="vertical" width="200" height="220">
	<mx:Script>
		<![CDATA[
			import flash.media.Video;

			private var microphone:Microphone;
			private var camera:Camera;
			private var video:Video;
			
			[Bindable]
			public var userItem:Object;
			public var nc:NetConnection;
			private var ns:NetStream;
			
			[Bindable]
			public var isSender:Boolean;
			
			private function init():void
			{
				ns = new NetStream( nc );
		        video = new Video( 180, 180 );
	        
				if( isSender ) {
					camera = Camera.getCamera();
					//Number(objConfig.quality)
					camera.setQuality( 16384, 0 );
					camera.setMode( 180, 180, 15, false );
					// Set loopback as compressed
					camera.setLoopback( true );
					video.attachCamera( camera );
					ns.attachCamera( camera );
					microphone = Microphone.getMicrophone();
					ns.attachAudio( microphone );
					ns.publish( userItem.identifier );				
				} else {
			        video.attachNetStream( ns );
	        		ns.play( userItem.identifier );
				}
				videoDisplay.video = video;
				
			}
		]]>
	</mx:Script>
	<VideoContainer
		id="videoDisplay"
		width="180" height="180" />
</mx:Panel>

Listing 4

package
{
	import mx.core.UIComponent;
	import flash.events.Event;
	import flash.media.Video;
	
	public class VideoContainer extends UIComponent
	{
        private var _video:Video;
        
		public function VideoContainer()
		{
			super();
			addEventListener(Event.RESIZE, resizeHandler);
			
		}

        public function set video(video:Video):void
        {
            if (_video != null)
            {
                removeChild(_video);
            }

			_video = video;

           	if (_video != null)
            {
	            _video.width = width;
                _video.height = height;
                addChild(_video);
            }
        }

        private function resizeHandler(event:Event):void
        {
            if (_video != null)
            {
               _video.width = width;
               _video.height = height;
            }
        }
	
	}
}