flash - 使用 as3 通过 flash 加载和播放 mjpeg - 套接字错误

标签 flash actionscript-3 sockets mjpeg

我想创建一个 Flash MJPEG 播放器,以便不受支持的浏览器可以查看它。

我在这里尝试了 2 种路线,一种使用 urlStream,另一种使用套接字。我将使用套接字,因为它似乎越来越远。

MJPEG 播放器将播放来自远程 IP 摄像机的摄像机流。因为摄像头位于路由器后面,所以它位于端口 8006。我已在该端口的摄像头根目录上传了一个 crossdomain.xml 文件

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <site-control permitted-cross-domain-policies="master-only" />
    <allow-access-from domain="*" to-ports="*" />
</cross-domain-policy>

此位置位于 h**p://domainofcam.com:8006/crossdomain.xml

在附件中您将找到我正在使用的 as3 代码。在我的 Flash 文件中,我在第 1 帧上,

Security.loadPolicyFile("xmlsocket:h**p://domainofcam_com:8006/crossdomain.xml"); 
trace("xmlsocket:h**p://domainofcam_com:8006/crossdomain.xml")  
var cam:MJPEG = new MJPEG("h**p://domainofcam.com", "/mjpeg.cgi", 8006);
addChild(cam);

我的 MJPEG as3 文件是这样的:

package 
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLRequestHeader;
    import flash.net.URLStream;
    import flash.net.Socket;
    import flash.utils.ByteArray;
    import com.dynamicflash.util.Base64;

    /**
     * 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


        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.addEventListener(IOErrorEvent.IO_ERROR, IOErrorSocket);
            webcamSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
            webcamSocket.connect(host, port);

        }

        private function IOErrorSocket(event:IOErrorEvent):void {
                var date:Date = new Date();
                trace(event);
        }

        private function securityError(event:SecurityErrorEvent):void {
            var date:Date = new Date();
            trace(event);
        }

        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");
        }

        function handleData(e:ProgressEvent):void {
            // 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);
        }

    }

}

当我运行调试时,我得到以下输出:

[IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: h*p://domainofcam.com"] [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security sandbox violation: file:///Repository/projects/Surfcam/mjpg/MJPG.swf cannot load data from h*p://domainofcam.com:8006."]

最佳答案

我也遇到过同样的问题。解决方案是使用 URLStream 而不是 Socket。 这里是工作源代码,几乎没有变化 - 我已经制作了 MXML 组件以在 Flex 中使用它。

package ru.idecide.olimpstroy
{
    import com.dynamicflash.util.Base64;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.HTTPStatusEvent;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.Socket;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.net.URLRequestHeader;
    import flash.net.URLRequestMethod;
    import flash.net.URLStream;
    import flash.utils.ByteArray;

    import mx.core.IMXMLObject;

    public class  MJPG extends EventDispatcher implements IMXMLObject
    {
        [Bindable]
        public var user:String;                       //Auth user name
        [Bindable]
        public var pass:String;                       //Auth user password
        [Bindable]
        public var host:String;                       //host server of stream
        [Bindable]
        public var port:int = 80;                     //port of stream
        [Bindable]
        public var file:String;                       //Location of MJPEG


        private var start:int = 0;                    //marker for start of jpg

        private var imageBuffer:ByteArray = new ByteArray();  //image holder


        public function MJPG()
        {
            loader = new Loader;
        }

        private var stream:URLStream;

        public function initialized(document:Object, id:String):void
        {
            stream = new URLStream();
            var request:URLRequest = new URLRequest(host + ":" + port.toString() + file);
            request.requestHeaders.push(new URLRequestHeader("Authorization", "Basic " + Base64.encode(user + ":" + pass)));
            configureListeners(stream);
            try {
                stream.load(request);
            } catch (error:Error) {
                trace("Unable to load requested URL.");
            }
        }

        private function configureListeners(dispatcher:EventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, completeHandler);
            dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            dispatcher.addEventListener(Event.OPEN, openHandler);
            dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        }

        private function parseHeader():void {
            trace("parseHeader", "length: " + imageBuffer.length);
            stream.readBytes(imageBuffer, imageBuffer.length)

            while(findImages()){
                //donothing
            }
        }

        private function completeHandler(event:Event):void {
            trace("completeHandler: " + event);
            parseHeader();
        }

        private function openHandler(event:Event):void {
            trace("openHandler: " + event);
        }

        private function progressHandler(event:Event):void {
            trace("progressHandler: " + event);
            parseHeader();
        }

        private function securityErrorHandler(event:SecurityErrorEvent):void {
            trace("securityErrorHandler: " + event);
        }

        private function httpStatusHandler(event:HTTPStatusEvent):void {
            trace("httpStatusHandler: " + event);
        }

        private function ioErrorHandler(event:IOErrorEvent):void {
            trace("ioErrorHandler: " + event);
        }

        private function onLoaded(e:Event):void {
            //var bytes:ByteArray = loader.data;
            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 var loader:Loader;

        private var _bitmapData:BitmapData;

        private function displayImage(image:ByteArray):void
        {
            loader.loadBytes(image);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete_handler);
        }

        private function loaderComplete_handler(event:Event):void
        {
            if (_bitmapData)
                _bitmapData.dispose();
            _bitmapData = Bitmap(loader.content).bitmapData;
            dispatchEvent(new Event("bitmapDataUpdate"));
        }

        [Bindable(event="bitmapDataUpdate")]
        public function get bitmapData():BitmapData
        {
            return _bitmapData;
        }
    }
}

我这样使用它:

<fx:Declarations>
<mp:MJPG host=""http://example.com" file="/mjpg/video.mjpg" user="{user}" pass="{password}" id="videoProvider"/>
</fx:Declarations>
<s:BitmapImage source="{videoProvider.bitmapData}" smooth="true" width="100%"/>

我建议您不要像示例中那样使用 Loader,因为它会使图像抽搐。在我的示例中,它运行良好。

关于flash - 使用 as3 通过 flash 加载和播放 mjpeg - 套接字错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8173496/

相关文章:

flash - 如何在具有不规则边缘的闪光催化剂中创建按钮

actionscript-3 - navigatorToURL post 方法的 as3 问题

flash - 将对象置于前面,在 Flash AS3 中

java - 安全性:如果我在建立连接时已经对连接进行了标记,那么有必要在 .writeUTF() 中使用 JWT 吗?

apache-flex - AS3 : Export a MovieClip or Canvas to swf

javascript - 如何知道某些东西是用 Flash 还是 Javascript 编程的

actionscript-3 - 1119 : Access of possibly undefined property SEEKED through a reference with static type Class

sockets - 使用套接字创建代理

Python 和 FFMPEG 视频流不通过 HTML5 显示

apache-flex - 压缩 swf 文件是否可能导致文件更大?