2010-10-03 111 views
1

到目前为止,我找到了解决办法需要一个crossdomain.xml工作,但这不是一个可用的IP摄像机:如何通过actionscript呈现IP摄像头视频?

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()"> 
    <mx:Script> 
     <![CDATA[ 
      import utils.video.mjpeg.MJPEG; 
      public function init():void{ 
       Security.loadPolicyFile("xmlsocket:http://10.8.0.54/crossdomain.xml"); 
       trace("xmlsocket:http://10.8.0.54/crossdomain.xml") 
       var vid:MJPEG = new MJPEG("10.8.0.54", "", 8081); 
       video.rawChildren.addChild(vid); 
      } 
     ]]> 
    </mx:Script> 
    <mx:VBox id="video"></mx:VBox> 
</mx:Application> 
////////////////////////// 
package utils.video.mjpeg 
{ 
    import flash.display.Loader; 
    import flash.events.Event; 
    import flash.events.ProgressEvent; 
    import flash.net.Socket; 
    import flash.utils.ByteArray; 

    import mx.utils.Base64Encoder; 

    /** 
    * This is a class used to view a MJPEG 
    * @author Josh Chernoff | GFX Complex 
    * 
    */ 
    public class MJPEG extends Loader 
    { 
     private var _user:String;         //Auth user name 
     private var _pass:String;         //Auth user password 

     private var _host:String;         //host server of stream 
     private var _port:int;          //port of stream   
     private var _file:String;         //Location of MJPEG 
     private var _start:int = 0;         //marker for start of jpg 

     private var webcamSocket:Socket = new Socket();    //socket connection 
     private var imageBuffer:ByteArray = new ByteArray();  //image holder 

     /** 
     * Create's a new instance of the MJPEG class. Note that due a sandbox security problem, unless you can place a crossdomain.xml 
     * on the host server you will only be able to use this class in your AIR applications. 
     * 
     * @example import MJPEG; 
     *   var cam:MJPEG = new MJPEG("192.168.0.100", "/img/video.mjpeg", 80); 
     *   addChild(cam); 
     *   
     * @param host:String | Host of the server. Do not include protocol 
     * @param file:String | Path to the file on the server. Start with a forward slash 
     * @param port:int | Port of the host server; 
     * @param user:String | User name for Auth 
     * @param pass:String | User password for Auth 
     */ 
     public function MJPEG (host:String, file:String, port:int = 80, user:String = null, pass:String = null) 
     { 
      _host = host; 
      _file = file; 
      _port = port; 
      _user = user; 
      _pass = pass; 

      webcamSocket.addEventListener(Event.CONNECT, handleConnect); 
      webcamSocket.addEventListener(ProgressEvent.SOCKET_DATA, handleData); 
      webcamSocket.connect(host, port); 

     } 

     private function handleConnect(e:Event):void 
     { 
      // we're connected send a request 
      var httpRequest:String = "GET "+_file+" HTTP/1.1\r\n"; 
      httpRequest+= "Host: localhost:80\r\n"; 
      /* 
      if(_user != null && _pass != null){ 
          var source:String = String(_user + ":" + _pass); 
          var auth:String = Base64.encode(source); 
          httpRequest += "Authorization: Basic " + auth.toString()+ "\r\n"; //NOTE THIS MAY NEEED TO BE EDITED TO WORK WITH YOUR CAM 
      } 
      */ 
      httpRequest+="Connection: keep-alive\r\n\r\n"; 
      webcamSocket.writeMultiByte(httpRequest, "us-ascii"); 
     } 

     private function handleData(e:ProgressEvent):void { 
      //trace("Got Data!" + e); 
      // get the data that we received. 

      // append the data to our imageBuffer 
      webcamSocket.readBytes(imageBuffer, imageBuffer.length); 
      //trace(imageBuffer.length); 
      while(findImages()){ 
      //donothing 
      } 


     } 


     private function findImages():Boolean 
     { 

      var x:int = _start; 
      var startMarker:ByteArray = new ByteArray();  
      var end:int = 0; 
      var image:ByteArray; 

      if (imageBuffer.length > 1) { 
       if(_start == 0){ 
        //Check for start of JPG 
        for (x; x < imageBuffer.length - 1; x++) { 

         // get the first two bytes. 
         imageBuffer.position = x; 
         imageBuffer.readBytes(startMarker, 0, 2); 

         //Check for end of JPG 
         if (startMarker[0] == 255 && startMarker[1] == 216) { 
          _start = x; 
          break;      
         } 
        } 
       } 
       for (x; x < imageBuffer.length - 1; x++) { 
        // get the first two bytes. 
        imageBuffer.position = x; 
        imageBuffer.readBytes(startMarker, 0, 2); 
        if (startMarker[0] == 255 && startMarker[1] == 217){ 

         end = x; 

         image = new ByteArray(); 
         imageBuffer.position = _start; 
         imageBuffer.readBytes(image, 0, end - _start); 

         displayImage(image); 

         // truncate the imageBuffer 
         var newImageBuffer:ByteArray = new ByteArray(); 

         imageBuffer.position = end; 
         imageBuffer.readBytes(newImageBuffer, 0); 
         imageBuffer = newImageBuffer; 

         _start = 0; 
         x = 0; 
         return true; 
        } 
       } 
      } 

      return false; 
     } 

     private function displayImage(image:ByteArray):void 
     { 
      this.loadBytes(image); 
     } 

    } 

} 

回答

0

也许我不理解你的问题,但如果我们在谈论同样的事情...在我的闪存(这是用AS2写的,所以你可能需要查看它在AS3中的不同,我注意到你没有使用系统的安全类...他们可能已经删除了) ,我有这条线...

System.security.loadPolicyFile("xml_root.socket://" + _root.HOST + ":" +_root.GAME_PORT); 

我很确定这只是从我的服务器的docroot中提取静态crossdomain.xml。

在服务器端,您的套接字代码(用什么写的?)可以直接提供跨域策略。

下面是我的Perl套接字中的一部分,它响应Flash套接字的初始请求。我很久以前写过这篇文章,但是看起来套接字将这个微小的xml片段作为其初始通信发送到套接字“<策略文件请求/ >”,以响应您要执行以下操作...

if($input eq "<policy-file-request/>"){ #if the string arriving on the socket == <policy-file-request>" 

    #assemble the printed response to look just like a crossdomain policy file. Set permissions as you normally would. 
    #if you don't know perl, the qq~ is just a way to provide a chunk of multiline code in one fragment. But note the \0 at the end. All socket messages have to be null terminated manually by you. 
    $MESSAGE =  qq~<?xml version="1.0"?> 
         <cross-domain-policy> 
         <allow-access-from domain="*" to-ports="*"/> 
         </cross-domain-policy>\0~; 
} 
print "$MESSAGE"; #send the string back on the socket 

确保这实际上是您所需要的。有时您只需要服务器将crossdomain.xml策略文件放在docroot中。

+0

但我没有控制服务器端,它是IP摄像机本身的内部。 – ollydbg 2010-10-03 07:36:03

+0

啊。我现在明白了。我不得不查看一台IP摄像机是什么......从来没有听过这种表达。我认为处理这个最简单的方法是通过服务器创建一个中继,并让你的Flash套接字连接到该套接字。让我们谈谈在不同的套接字端口上的摄像头,所以... IP摄像头 - >服务器套接字 - > Flash。服务器套接字不关心安全性,可以与相机通话,并且可以为Flash提供所需的安全性。假设您的IP摄像机与您的计算机位于同一网络上,您可以轻松地在其上运行该套接字。 – 2010-10-03 07:37:46

+0

非常像USB摄像头,但可以通过URL访问。 – ollydbg 2010-10-03 07:41:30