flex + red5实现视频会议java摄像头监控



flex + red5实现视频会议

公司最近要在系统中加视频会议的功能,让我探索,我选择了最流行的red5来实现,网上有一对一聊天的demo,找不到多对多聊天的,也没有具体介绍系统搭建的过程,我通过自己的摸索,将实现的过程和大家一起分享。java的web项目添加flex支持在此不再详述,项目文件结构如图:


web.xml文件:

Java代码  收藏代码
  1. <?xml version=”1.0″ encoding=”UTF-8″?>
  2. <web-app
  3.    version=”2.4″
  4.    xmlns=”http://java.sun.com/xml/ns/j2ee”
  5.    xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”
  6.    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
  7. <!–
  8.     ** For use with servlet v2.5 replace the lines above with these
  9.     version=”2.5″
  10.     xmlns=”http://java.sun.com/xml/ns/javaee”
  11.     xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”
  12.    xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  13. –>
  14.     <display-name>Red5ChartRoom</display-name>
  15.     <context-param>
  16.         <param-name>globalScope</param-name>
  17.         <param-value>default</param-value>
  18.     </context-param>
  19.     <context-param>
  20.         <param-name>parentContextKey</param-name>
  21.         <param-value>default.context</param-value>
  22.     </context-param>
  23.     <context-param>
  24.         <param-name>webAppRootKey</param-name>
  25.         <param-value>@webapp.root.key@</param-value>
  26.     </context-param>
  27.     <context-param>
  28.         <param-name>contextConfigLocation</param-name>
  29.         <param-value>WEB-INF/classes/*-web.xml</param-value>
  30.     </context-param>
  31.     <listener>
  32.         <listener-class>org.red5.server.war.WarLoaderServlet</listener-class>
  33.     </listener>
  34.     <listener>
  35.         <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  36.     </listener>
  37.     <servlet>
  38.         <servlet-name>gateway</servlet-name>
  39.         <servlet-class>org.red5.server.net.servlet.AMFGatewayServlet</servlet-class>
  40.         <load-on-startup>1</load-on-startup>
  41.     </servlet>
  42.     <servlet>
  43.         <servlet-name>rtmpt</servlet-name>
  44.         <servlet-class>org.red5.server.net.rtmpt.RTMPTServlet</servlet-class>
  45.         <load-on-startup>2</load-on-startup>
  46.     </servlet>
  47.      <!– MessageBroker Servlet –>
  48.  <servlet>
  49.   <display-name>MessageBrokerServlet</display-name>
  50.   <servlet-name>MessageBrokerServlet</servlet-name>
  51.   <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
  52.   <init-param>
  53.    <param-name>services.configuration.file</param-name>
  54.    <param-value>/WEB-INF/flex/services-config.xml</param-value>
  55.   </init-param>
  56.   <load-on-startup>11</load-on-startup>
  57.  </servlet>
  58.     <servlet-mapping>
  59.         <servlet-name>gateway</servlet-name>
  60.         <url-pattern>/gateway</url-pattern>
  61.     </servlet-mapping>
  62.     <servlet-mapping>
  63.         <servlet-name>rtmpt</servlet-name>
  64.         <url-pattern>/fcs/*</url-pattern>
  65.     </servlet-mapping>
  66.     <servlet-mapping>
  67.         <servlet-name>rtmpt</servlet-name>
  68.         <url-pattern>/open/*</url-pattern>
  69.     </servlet-mapping>
  70.     <servlet-mapping>
  71.         <servlet-name>rtmpt</servlet-name>
  72.         <url-pattern>/idle/*</url-pattern>
  73.     </servlet-mapping>
  74.     <servlet-mapping>
  75.         <servlet-name>rtmpt</servlet-name>
  76.         <url-pattern>/send/*</url-pattern>
  77.     </servlet-mapping>
  78.     <servlet-mapping>
  79.         <servlet-name>rtmpt</servlet-name>
  80.         <url-pattern>/close/*</url-pattern>
  81.     </servlet-mapping>
  82.      <servlet-mapping>
  83.          <servlet-name>MessageBrokerServlet</servlet-name>
  84.         <url-pattern>/messagebroker/*</url-pattern>
  85.     </servlet-mapping>
  86.     <welcome-file-list>
  87.         <welcome-file>login.html</welcome-file>
  88.         <welcome-file>index.html</welcome-file>
  89.         <welcome-file>index.htm</welcome-file>
  90.     </welcome-file-list>
  91.     <security-constraint>
  92.         <web-resource-collection>
  93.             <web-resource-name>Forbidden</web-resource-name>
  94.             <url-pattern>/WEB-INF/*</url-pattern>
  95.         </web-resource-collection>
  96.         <auth-constraint />
  97.     </security-constraint>
  98.     <security-constraint>
  99.         <web-resource-collection>
  100.             <web-resource-name>Forbidden</web-resource-name>
  101.             <url-pattern>/persistence/*</url-pattern>
  102.         </web-resource-collection>
  103.         <auth-constraint />
  104.     </security-constraint>
  105.     <security-constraint>
  106.         <web-resource-collection>
  107.             <web-resource-name>Forbidden</web-resource-name>
  108.             <url-pattern>/streams/*</url-pattern>
  109.         </web-resource-collection>
  110.         <auth-constraint />
  111.     </security-constraint>
  112. </web-app>

red5ChartRoom-web.xml

Java代码  收藏代码
  1. <?xml version=”1.0″ encoding=”UTF-8″?>
  2. <beans xmlns=”http://www.springframework.org/schema/beans”
  3.        xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  4.        xmlns:lang=”http://www.springframework.org/schema/lang”
  5.        xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6.                            http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd”>
  7. <bean id=”web.context.chatroom” class=”org.red5.server.Context”>
  8.     <property name=”scopeResolver” ref=”red5.scopeResolver”></property>
  9.     <property name=”clientRegistry” ref=”global.clientRegistry”/>
  10.     <property name=”serviceInvoker” ref=”global.serviceInvoker”/>
  11.     <property name=”mappingStrategy” ref=”global.mappingStrategy”/>
  12. </bean>
  13. <bean id=”web.scope” class=”org.red5.server.WebScope” init-method=”register”>
  14.     <property name=”server” ref=”red5.server”/>
  15.     <property name=”parent” ref=”global.scope”/>
  16.     <property name=”context” ref=”web.context.chatroom”/>
  17.     <property name=”handler” ref=”web.handler.chatroom”/>
  18.     <property name=”contextPath” value=”/Red5ChatRoom”/>
  19.     <property name=”virtualHosts” value=”*,localhost,localhost:8080,127.0.0.1:8080″/>
  20. </bean>
  21. <bean id=”web.handler.chatroom” class=”com.chinahrt.chat.VedioChatApplication”/>
  22. </beans>

 


red5.properties

Java代码  收藏代码
  1. # Socket policy
  2. policy.host=0.0.0.0
  3. policy.port=843
  4. # HTTP
  5. http.host=0.0.0.0
  6. http.port=5080
  7. https.port=8443
  8. # RTMP
  9. rtmp.host=0.0.0.0
  10. rtmp.port=1935
  11. rtmp.io_threads=16
  12. rtmp.connect_threads=4
  13. rtmp.send_buffer_size=271360
  14. rtmp.receive_buffer_size=65536
  15. rtmp.ping_interval=1000
  16. rtmp.max_inactivity=60000
  17. rtmp.tcp_nodelay=true
  18. # RTMPS
  19. rtmps.host=0.0.0.0
  20. rtmps.port=8443
  21. rtmps.ping_interval=5000
  22. rtmps.max_inactivity=60000
  23. rtmps.max_keep_alive_requests=-1
  24. rtmps.max_threads=20
  25. rtmps.acceptor_thread_count=2
  26. rtmps.processor_cache=20
  27. # RTMPS Keystore Password
  28. rtmps.keystorepass=password
  29. # RTMPT
  30. rtmpt.host=0.0.0.0
  31. rtmpt.port=8088
  32. rtmpt.ping_interval=5000
  33. rtmpt.max_inactivity=60000
  34. rtmpt.max_keep_alive_requests=-1
  35. rtmpt.max_threads=20
  36. rtmpt.acceptor_thread_count=2
  37. rtmpt.processor_cache=20
  38. # MRTMP
  39. mrtmp.host=0.0.0.0
  40. mrtmp.server=localhost
  41. mrtmp.port=9035
  42. mrtmp.event_threads_core=4
  43. mrtmp.event_threads_max=32
  44. # event threads queue: -1 unbounded, 0 direct (no queue), n bounded queue
  45. mrtmp.event_threads_queue=0
  46. mrtmp.event_threads_keepalive=60
  47. mrtmp.send_buffer_size=271360
  48. mrtmp.receive_buffer_size=65536
  49. mrtmp.ping_interval=5000
  50. mrtmp.max_inactivity=60000
  51. mrtmp.tcp_nodelay=true
  52. # Debug proxy (needs to be activated in red5-core.xml)
  53. proxy.source_host=127.0.0.1
  54. proxy.source_port=1936
  55. proxy.destination_host=127.0.0.1
  56. proxy.destination_port=1935
  57. # JMX
  58. jmx.rmi.port.registry=9999
  59. jmx.rmi.port.remoteobjects=
  60. jmx.rmi.host=127.0.0.1
  61. jmx.rmi.ssl=false
  62. red5.config_root=red5.config_root
  63. red5.root=E\:apache-tomcat-6.0.33

 

java代码

Java代码  收藏代码
  1. package com.chinahrt.chat;
  2. import java.util.HashMap;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import org.python.antlr.PythonParser.return_stmt_return;
  8. import org.red5.server.adapter.ApplicationAdapter;
  9. import org.red5.server.api.IConnection;
  10. import org.red5.server.api.IScope;
  11. import org.red5.server.api.Red5;
  12. import org.red5.server.api.service.IServiceCapableConnection;
  13. import org.red5.server.api.so.ISharedObject;
  14. import org.red5.server.api.stream.IBroadcastStream;
  15. /**
  16.  * createBy ZYN
  17.  *
  18.  * createTime 2011-9-16 下午03:33:15
  19.  *
  20.  * desc 视频聊天服务器
  21.  *
  22.  */
  23. public class VedioChatApplication extends ApplicationAdapter {
  24.     private IScope appScope;
  25.     private String userName;
  26.     //共享存贮在线用户
  27.     private ISharedObject listSO;
  28.     private Map<String,IConnection> onlineList = new HashMap<String,IConnection> ();//在线用户表
  29.     //程序运行
  30.     //程序运行时志向
  31.     public boolean appStart(IScope app) {
  32.       if (!super.appStart(app)) {
  33.           return false;
  34.       }
  35.       appScope = app;
  36.       return true;
  37.     }
  38.     @Override
  39.     public boolean appConnect(IConnection arg0, Object[] arg1) {
  40.       /**
  41.        *  用户首次连接server 时触发,检查用户是否重复登录,将用户添加到在线用户表中
  42.        */
  43.       String userId=arg0.getClient().getId();
  44.       if(!super.appConnect(arg0, arg1)){
  45.        return false;
  46.       }
  47.       if (arg1 != null ) {
  48.        userName = (String) arg1[0];
  49.       }
  50.       if(onlineList.get(userName) != null){
  51.        rejectClient(“请不要重复登录”);
  52.        return false;
  53.       }
  54.       onlineList.put(userName, arg0);
  55.       listSO = getSharedObject(appScope, ”listSO”, false);
  56.       listSO.setAttribute(userId, userName);
  57.       System.out.println(“The user:”+userName+”,”+userName+” logined successfully”);
  58.       return true;
  59.     }
  60.     /**
  61.       * 通知所有人当前用户登录
  62.       * @param params
  63.       */
  64.     public void getOnloadUser(Object[] params) {
  65.       String clientName = params[0].toString();
  66.       if(null == clientName || ”".equals(clientName)) {
  67.          return ;
  68.        }
  69.       //给所有客户端数据
  70.        IScope scope = Red5.getConnectionLocal().getScope();
  71.        Iterator it = scope.getConnections().iterator();
  72.        for (;it.hasNext();) {
  73.         Set connections = (Set)it.next();
  74.         IConnection tempConn = (IConnection)connections.iterator().next();
  75.         if (tempConn instanceof IServiceCapableConnection) {
  76.          IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;
  77.          sc.invoke(“result_getOnloadUser”, new Object[]{clientName});
  78.         }
  79.        }
  80.     }
  81.     //聊天
  82.       public void sayToAll(Object[] params) {
  83.        IConnection conn = Red5.getConnectionLocal();
  84.        String user_id = conn.getClient().getId();
  85.        String clientName =(String) listSO.getAttribute(user_id);
  86.        System.out.println(“************发言者是:”+clientName);
  87.        String sayToName=params[0]==null?”":params[0].toString().trim();
  88.        String sayWhat=params[1]==null?”":params[1].toString().trim();
  89.        if(“”.equals(sayToName)||”All”.equals(sayToName))// 发消息给聊天室的所有人.
  90.        {
  91.         IScope scope = Red5.getConnectionLocal().getScope();
  92.         Iterator it = scope.getConnections().iterator();
  93.         for (;it.hasNext();) {
  94.           Set connections = (Set)it.next();
  95.           IConnection tempConn = (IConnection)connections.iterator().next();
  96.          if (tempConn instanceof IServiceCapableConnection) {
  97.              IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;
  98.           // 调用客户端showMessage方法。
  99.              sc.invoke(“showMessage”, new Object[]{clientName+” to All:”+sayWhat});
  100.           }
  101.        }
  102.        }else{
  103.          IConnection tempConn=onlineList.get(sayToName);
  104.          if (tempConn instanceof IServiceCapableConnection) {
  105.           IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;
  106.           sc.invoke(“showMessage”, new Object[]{clientName+” to ”+sayToName+”:”+sayWhat});
  107.           }
  108.          IServiceCapableConnection sc = (IServiceCapableConnection) conn;
  109.          sc.invoke(“showMessage”, new Object[]{clientName+” to ”+sayToName+”:”+sayWhat});
  110.        }
  111.       }
  112.     // 用户断开连接的时候触发
  113.       public void appDisconnect(IConnection conn) {
  114.        String dis_user_id = conn.getClient().getId();
  115.        String user = (String) listSO.getAttribute(dis_user_id);
  116.        // 根据ID删除对应在线纪录
  117.        onlineList.remove(user);
  118.        // 删除用户列表共享对象的对应属性
  119.        listSO.removeAttribute(dis_user_id);
  120.        IScope scope = Red5.getConnectionLocal().getScope();
  121.         Iterator it = scope.getConnections().iterator();
  122.         for (;it.hasNext();) {
  123.          Set connections = (Set)it.next();
  124.          IConnection tempConn = (IConnection)connections.iterator().next();
  125.          if (tempConn instanceof IServiceCapableConnection) {
  126.              IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;
  127.            // 服务器端调用客户端flash方法。
  128.              sc.invoke(“disconnectMessage”, new Object[]{user});
  129.           }
  130.         }
  131.       }
  132. }

flex端代码

Java代码  收藏代码
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>
  3.     <mx:Script>
  4.         <![CDATA[
  5.             import mx.collections.ArrayCollection;
  6.             import mx.containers.HBox;
  7.             import mx.controls.Alert;
  8.             private var listSO:SharedObject;
  9.             private var userArr:Array;
  10.             private var conn:NetConnection;
  11.             private var localUsername:String;
  12.             [Bindable]
  13.             private var cam:Camera;
  14.             [Bindable]
  15.             private var mic:Microphone;
  16.             [Bindable]
  17.             public var cards:ArrayCollection;
  18.             public var videoUsers:Array;
  19.             [Bindable]
  20.             public var videoControlArr:Array;
  21.             private var stm:NetStream;
  22.             [Bindable]
  23.             private var video_self:Video;
  24.             protected function login(event:MouseEvent):void
  25.             {
  26.                 localUsername = txt_name.text;
  27.                 if(localUsername== ”"){
  28.                     Alert.show(“用户名不能为空”);
  29.                 }else{
  30.                     if(conn == null){
  31.                         conn = new NetConnection();
  32.                         conn.client = this;
  33.                         conn.addEventListener(NetStatusEvent.NET_STATUS,_statusHandler);
  34.                         conn.connect(“rtmp://192.168.1.61/Red5ChatRoom”,localUsername);
  35.                     }
  36.                 }
  37.             }
  38.             //状态监听
  39.             private function _statusHandler(evt:NetStatusEvent):void
  40.             {
  41.                 if(evt.info.code == ”NetConnection.Connect.Success”){
  42.                     this.currentState = ”chat”;
  43.                     Alert.show(“连接成功”);
  44.                     video_clickHandler();
  45.                     this.showJoinInInfo(localUsername);
  46.                     _setListSO();
  47.                 }
  48.                 if(evt.info.code == ”NetConnection.Connect.Failed”){
  49.                     Alert.show(“连接失败”);
  50.                 }
  51.                 if(evt.info.code == ”NetConnection.Connect.Closed”){
  52.                     Alert.show(“连接关闭”);
  53.                 }
  54.             }
  55.             public function showJoinInInfo(message:String):void
  56.             {
  57.                 conn.call(“getOnloadUser”,null,message);
  58.             }
  59.             public function result_getOnloadUser(str:String):void{
  60.                 txt_chatmsg.text += str + ”加入聊天室” + ”\n”;
  61.             }
  62.             //创建用户列表共享对象
  63.             private function _setListSO():void
  64.             {
  65.                 listSO = SharedObject.getRemote(“listSO”,conn.uri,false);
  66.                 listSO.connect(conn);
  67.                 listSO.addEventListener(SyncEvent.SYNC,_listSOSyncHandler);
  68.             }
  69.             //用户列表共享对象被更新之后的事件
  70.             private function _listSOSyncHandler(evt:SyncEvent):void{
  71.                 _showUserList();//更新用户列表
  72.             }
  73.             private function _showUserList():void
  74.             {
  75.                 cards = new ArrayCollection(
  76.                     [{label:"All"}]
  77.                 );
  78.                 userArr = new Array();
  79.                 //用户数组更新
  80.                 for(var tmp:String in listSO.data){
  81.                     userArr.push(listSO.data[tmp]);
  82.                 }
  83.                 //添加到arrayCollection
  84.                 for(var i:int = 0; i<userArr.length;i++){
  85.                     cards.addItem({label:userArr[i]});
  86.                 }
  87.                 //将数组添加到列表数组中显示出来
  88.                 userList.dataProvider = cards;
  89.                 users.dataProvider = cards;
  90.                 addVideo(cards);
  91.             }
  92.             public function showMessage(message:String):void
  93.             {
  94.                 txt_chatmsg.text += message + ”\n”;
  95.             }
  96.             protected function sendMessage(event:MouseEvent):void
  97.             {
  98.                 var sendString:String = txt_yousay.text;
  99.                 var sendTo:String = userList.selectedItem.label;
  100.                 txt_yousay.text = ”";
  101.                 conn.call(“sayToAll”,null,sendTo,sendString);
  102.             }
  103.             //断线通知
  104.             public function disconnectMessage(disUser:String):void
  105.             {
  106.                 txt_chatmsg.text += disUser+”退出聊天室\n”;
  107.             }
  108.             //进入视频会议
  109.             public function video_clickHandler():void
  110.             {
  111.                 stm = new NetStream(conn);
  112.                 cam = Camera.getCamera();
  113.                 if(cam==null){
  114.                     Alert.show(“没有可以使用的摄像头”);
  115.                     return;
  116.                 }else{
  117.                     Security.showSettings(SecurityPanel.PRIVACY);
  118.                     cam.addEventListener(StatusEvent.STATUS,statusHandler);
  119.                     cam.addEventListener(ActivityEvent.ACTIVITY,activityHandler);
  120.                     cam.setLoopback(true);
  121.                     cam.setMotionLevel(50,100);
  122.                     cam.setMode(1280,960,15,true);
  123.                     stm.attachCamera(cam);
  124.                 }
  125.                 mic = Microphone.getMicrophone();
  126.                 mic.addEventListener(StatusEvent.STATUS,micOnstatu);
  127.                 if(mic == null){
  128.                     Alert.show(“没有可以使用的麦克风”);
  129.                 }else{
  130.                     mic.setUseEchoSuppression(true);
  131.                     stm.attachAudio(mic);
  132.                 }
  133.                 stm.play(“chinahrt-”+txt_name.text);
  134.                 stm.publish(“chinahrt-”+txt_name.text,”live”);
  135.                 video_self = new Video();
  136.                 video_self.width = 320;
  137.                 video_self.height = 240;
  138.                 video_self.attachCamera(cam);
  139.                 my_video.addChild(video_self);
  140.             }
  141.             private function micOnstatu(e:StatusEvent):void
  142.             {
  143.                 mic.setLoopBack(true);
  144.                 mic.gain = 66;
  145.                 mic.rate = 11;
  146.                 mic.setUseEchoSuppression(true);
  147.                 mic.setSilenceLevel(1,-1);
  148.             }
  149.             private function statusHandler(e:StatusEvent):void
  150.             {
  151.             }
  152.             private function activityHandler(e:ActivityEvent):void
  153.             {
  154.             }
  155.             private function addVideo(cards:ArrayCollection):void
  156.             {
  157.                 label1.text = ”我的(“+localUsername+”)”;
  158.                 myBox.removeAllChildren();
  159.                 var otherPerson:ArrayCollection = new ArrayCollection();
  160.                 for(var i:int=0;i<cards.length;i++){
  161.                     var o:Object = cards.getItemAt(i);
  162.                     if(o["label"]!=localUsername&&o["label"]!=”All”){
  163.                         otherPerson.addItem(o);
  164.                     }
  165.                 }
  166.         //      Alert.show(otherPerson.length+”");
  167.                 var yushu:int = 0;
  168.                 var yushu:int= otherPerson.length%3;
  169.                 var rowNum:int = 0;
  170.                 var rowNum:int = otherPerson.length/3;
  171.                 if(yushu!=0){
  172.                     rowNum += 1;
  173.                 }
  174.                 if(yushu==0){
  175.                     for(var i:int=0;i<rowNum;i++){
  176.                         var hbox:HBox = new HBox();
  177.                         myBox.addChild(hbox);
  178.                         for(var ii:int=0;ii<3;ii++){
  179.                             var vbox:VBox = new VBox();
  180.                             hbox.addChild(vbox);
  181.                             var label:Label = new Label;
  182.                             label.text = otherPerson.getItemAt(i*3+ii)["label"];
  183.                             vbox.addChild(label);
  184.                             var videoDisplay:VideoDisplay = new VideoDisplay();
  185.                             videoDisplay.live = true;
  186.                             videoDisplay.width = 320;
  187.                             videoDisplay.height = 240;
  188.                             vbox.addChild(videoDisplay);
  189.                             var video:Video = new Video();
  190.                             video.width = 320;
  191.                             video.height = 240;
  192.                             var netStream:NetStream = new NetStream(conn);
  193.                             video.attachNetStream(netStream);
  194.                             netStream.play(“chinahrt-”+label.text);
  195.                             videoDisplay.addChild(video);
  196.                         }
  197.                     }
  198.                 }else{
  199.                     for(var i:int=0;i<rowNum-1;i++){
  200.                         var hbox:HBox = new HBox();
  201.                         myBox.addChild(hbox);
  202.                         for(var ii:int=0;ii<3;ii++){
  203.                             var vbox:VBox = new VBox();
  204.                             hbox.addChild(vbox);
  205.                             var label:Label = new Label;
  206.                             label.text = otherPerson.getItemAt(i*3+ii)["label"];
  207.                             vbox.addChild(label);
  208.                             var videoDisplay:VideoDisplay = new VideoDisplay();
  209.                             videoDisplay.live = true;
  210.                             videoDisplay.width = 320;
  211.                             videoDisplay.height = 240;
  212.                             vbox.addChild(videoDisplay);
  213.                             var video:Video = new Video();
  214.                             video.width = 320;
  215.                             video.height = 240;
  216.                             var netStream:NetStream = new NetStream(conn);
  217.                             video.attachNetStream(netStream);
  218.                             netStream.play(“chinahrt-”+label.text);
  219.                             videoDisplay.addChild(video);
  220.                         }
  221.                     }
  222.                     var hbox:HBox = new HBox();
  223.                     myBox.addChild(hbox);
  224.                     for(var i:int=0;i<yushu;i++){
  225.                         var vbox:VBox = new VBox();
  226.                         hbox.addChild(vbox);
  227.                     //  myBox.addChild(vbox);
  228.                         var label:Label = new Label();
  229.                         label.text = otherPerson.getItemAt((rowNum-1)*3+i)["label"];
  230.                         vbox.addChild(label);
  231.                         var videoDisplay:VideoDisplay = new VideoDisplay();
  232.                         videoDisplay.live = true;
  233.                         videoDisplay.width = 320;
  234.                         videoDisplay.height = 240;
  235.                         vbox.addChild(videoDisplay);
  236.                         var video:Video = new Video();
  237.                         video.width = 320;
  238.                         video.height = 240;
  239.                         var netStream:NetStream = new NetStream(conn);
  240.                     //  Alert.show(otherPerson.getItemAt((rowNum-1)*3+i)["label"]);
  241.                         video.attachNetStream(netStream);
  242.                         netStream.play(“chinahrt-”+label.text);
  243.                         videoDisplay.addChild(video);
  244.                     }
  245.                 }
  246.             }
  247.         ]]>
  248.     </mx:Script>
  249.     <mx:states>
  250.         <mx:State id=”chatState” name=”chat”>
  251.             <mx:SetProperty target=”{form1}” name=”width” value=”0″/>
  252.             <mx:SetProperty target=”{form1}” name=”height” value=”0″/>
  253.             <mx:SetProperty target=”{form1}” name=”x” value=”0″/>
  254.             <mx:SetProperty target=”{form1}” name=”y” value=”0″/>
  255.             <mx:AddChild position=”lastChild”>
  256.                 <mx:Panel x=”10″ y=”10″ width=”381″ height=”370″ layout=”absolute” title=”聊天信息”>
  257.                     <mx:TextArea x=”10″ y=”10″ width=”215″ height=”235″ id=”txt_chatmsg”/>
  258.                     <mx:ComboBox x=”233″ y=”34″ width=”118″ id=”userList”></mx:ComboBox>
  259.                     <mx:Label x=”233″ y=”11″ text=”用户列表”/>
  260.                     <mx:DataGrid x=”233″ y=”64″ height=”256″ id=”users” width=”118″>
  261.                         <mx:columns>
  262.                             <mx:DataGridColumn headerText=”用户名” dataField=”label”/>
  263.                         </mx:columns>
  264.                     </mx:DataGrid>
  265.                     <mx:TextInput x=”10″ y=”253″ height=”67″ width=”150″ id=”txt_yousay”/>
  266.                     <mx:Button x=”168″ y=”253″ label=”发送” width=”57″ click=”sendMessage(event)”/>
  267.                 <!– <mx:Button x=”168″ y=”298″ label=”进入视频会议” width=”57″ click=”video_clickHandler(event)”/>–>
  268.                 </mx:Panel>
  269.             </mx:AddChild>
  270.             <mx:AddChild position=”lastChild”>
  271.                 <mx:VideoDisplay live=”true” x=”10″ y=”410″  width=”320″ height=”240″ id=”my_video”/>
  272.             </mx:AddChild>
  273.             <mx:AddChild position=”lastChild”>
  274.                 <mx:Label id=”label1″ x=”10″ y=”390″ text=”我的”/>
  275.             </mx:AddChild>
  276.             <!–<mx:AddChild position=”lastChild”>
  277.                 <mx:VideoDisplay live=”true”  x=”399″ y=”224″  width=”320″ height=”240″ id=”other_video”/>
  278.             </mx:AddChild>
  279.             <mx:AddChild position=”lastChild”>
  280.                 <mx:Label x=”399″ y=”198″ text=”对方的”/>
  281.             </mx:AddChild> –>
  282.             <mx:AddChild position=”lastChild”>
  283.                 <mx:VBox id=”myBox” x=”399″ y=”10″/>
  284.             </mx:AddChild>
  285.         </mx:State>
  286.     </mx:states>
  287.     <mx:Form x=”10″ y=”10″ width=”283″ height=”126″ id=”form1″>
  288.         <mx:FormItem label=”用户名:”>
  289.             <mx:TextInput id=”txt_name”/>
  290.         </mx:FormItem>
  291.         <mx:FormItem>
  292.             <mx:Button label=”登陆” click=”login(event)”/>
  293.         </mx:FormItem>
  294.     </mx:Form>
  295. </mx:Application>

百度网盘:http://pan.baidu.com/s/1hqkgBly