到目前为止,我找到的解决方案需要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);
}
}
}
答案 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策略文件。