如何使用actionscript渲染带有socket的IP摄像机视频?

时间:2010-10-03 06:36:35

标签: flash actionscript ip-camera

到目前为止,我找到的解决方案需要crossdomain.xml才能正常工作,但这在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);  
        }  

    }  

}  

1 个答案:

答案 0 :(得分:0)

也许我不理解你的问题,但如果我们谈论同样的事情......

在我的flash(用AS2编写,所以你可能需要查看它在AS3中的不同之处,我注意到你没有使用System的安全类......他们可能已经删除了它),我有这个线...

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

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

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

这是我的Perl套接字中响应flash套接字初始请求的部分。我很久以前写过这个,但看起来套接字会将这个微小的xml片段作为其初始通信发送到套接字“&lt; policy-file-request /&gt;”为了回应你想要做的以下......

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

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