装载&使用 as3 通过 flash 播放 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”气泡= false可取消= false eventPhase=2 text="错误#2031:套接字错误。URL: h*p://domainofcam.com"] [SecurityErrorEvent type="securityError" bubbles = false cancelable = false eventPhase = 2 text =“错误#2048: 安全沙箱违规: file:///Repository/projects/Surfcam/mjpg/MJPG.swf 无法加载数据 来自 h*p://domainofcam.com:8006。"]
I would like to create a flash MJPEG player so unsupported browsers can view it.
I have tried 2 routes here, one with a urlStream and other with Sockets. I am going with the sockets because it seems to be getting farther.
The MJPEG player will play a camera stream from a remote IP camera. Because the camera is located behind a router, it is on port 8006. I have uploaded a crossdomain.xml file at the root of the camera at that port
<?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>
This is located at h**p://domainofcam.com:8006/crossdomain.xml
Attached you will find my as3 code that I am using. In my flash file I have on frame 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);
and my MJPEG as3 file is as such:
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);
}
}
}
When I run debug I get the following output:
[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."]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我也遇到过同样的问题。解决方案是使用 URLStream 而不是 Socket。
这是工作源代码,几乎没有变化 - 我已经制作了 MXML 组件以在 Flex 中使用它。
我这样使用它:
我建议您不要像您的示例中那样使用 Loader,因为它会使图像抽搐。在我的例子中它运行良好。
I've faced with the same problem. The solution was in using URLStream instead of Socket.
Here is working source code with little changes - I've made MXML component to use it in Flex.
I use it this way:
I advice you to not use Loader as in your example because it makes the image twitch. In my the example it works well.
你可以试试这个:
https://github.com/alloyking/Foscam-Flex
看起来是为移动应用程序设计的- 安卓。
You could try this:
https://github.com/alloyking/Foscam-Flex
Looks to be designed for a mobile app - Android.
您错误地调用了该方法,应该类似于:
var cam:MJPEG = new MJPEG("192.168.1.10", "/video.mjpeg",8080);
(删除主机中的前导http://)
you're calling the method incorrectly, should be like:
var cam:MJPEG = new MJPEG("192.168.1.10", "/video.mjpeg",8080);
(drop the leading http:// in the host)