如何通过actionscript使用socket渲染IP摄像机视频?
到目前为止,我找到的解决方案需要 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);
}
}
}
So far the solution I found requires a crossdomain.xml
to work,but this is not available on an IP camera:
<?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);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
也许我不明白你的问题,但如果我们谈论的是同一件事......
在我的闪存中(这是用 AS2 编写的,所以你可能需要查找它在 AS3 中的不同之处,我注意到你不是使用系统的安全类...他们可能已经删除了它),我有这一行...
我很确定这只是从我的服务器的文档根中获取静态 crossdomain.xml 。
在服务器端,您的套接字代码(用什么编写的?)可以直接传递跨域策略。
这是我的 Perl 套接字中的片段,它响应闪存套接字的初始请求。我很久以前就写过这篇文章,但看起来套接字发送了这个微小的 xml 片段作为其与套接字“”的初始通信。作为回应,您想要执行以下操作...
确保这确实是您所需要的。有时,您所需要的只是让服务器将 crossdomain.xml 策略文件放在文档根目录中。
Maybe I'm not understanding your question, but if we're talking about the same thing...
In my flash (which was written in AS2 so you may need to look up how it's different in AS3, I notice you're not using the security class of System... they may have removed that), I have this line...
I'm pretty sure this simply goes and fetches the static crossdomain.xml from the docroot of my server.
On the server side of things your socket code (what is that written in?) can deliver the crossdomain policy directly.
Here's the piece from my Perl socket that responds to the flash socket's initial request. I wrote this a long time ago but it would appear that the socket sends this tiny xml fragment as its initial communication to the socket "<policy-file-request/>" in response to which you want to do the following...
Make sure this is actually what you need. Sometimes all you need is for the server to just have the crossdomain.xml policy file sitting at the docroot.