Eliminate unused *.as files for Adobe Flash. v5.0.22

pull/2895/head
winlin 3 years ago
parent 0b87950073
commit 7c9f88be0b

@ -8,6 +8,7 @@ The changelog for SRS.
## SRS 5.0 Changelog
* v5.0, 2022-01-18, Eliminate unused *.as files for Adobe Flash. v5.0.22
* v5.0, 2022-01-13, Switch LICENSE from MIT to **MIT or MulanPSL-2.0**. v5.0.21
* v5.0, 2021-10-24, For [#2689](https://github.com/ossrs/srs/issues/2689): Support loongarch, loongson CPU. v5.0.19
* v5.0, 2021-10-17, Support daemon(fork twice) for Darwin/OSX [ST#23](https://github.com/ossrs/state-threads/issues/23). v5.0.18

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="srs_bwt.as" projectUUID="00251213-e6a2-4dd5-a033-125cc78f843c" version="10">
<compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="false" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="release" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
<excludedEntries>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
</excludedEntries>
</libraryPathEntry>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="srs_bwt.as"/>
</applications>
<modules/>
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>srs_bwt</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
</projectDescription>

@ -1,576 +0,0 @@
//
// Copyright (c) 2013-2021 Winlin
//
// SPDX-License-Identifier: MIT
//
package
{
import flash.events.NetStatusEvent;
import flash.external.ExternalInterface;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.ObjectEncoding;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
/**
* SRS bandwidth check/test library,
* user can copy this file and use it directly,
* this library will export as callback functions, and js callback functions.
*
* Usage:
* var bandwidth:SrsBandwidth = new SrsBandwidth();
* bandwidth.initialize(......); // required
* bandwidth.check_bandwidth(......); // required
* bandwidth.stop(); // optional
*
* @remark we donot use event, but use callback functions set by initialize.
*/
public class SrsBandwidth
{
/**
* server notice client to do the downloading/play bandwidth test.
*/
public static const StatusSrsBwtcPlayStart:String = "srs.bwtc.play.start";
/**
* server notice client to complete the downloading/play bandwidth test.
*/
public static const StatusSrsBwtcPlayStop:String = "srs.bwtc.play.stop";
/**
* server notice client to do the uploading/publish bandwidth test.
*/
public static const StatusSrsBwtcPublishStart:String = "srs.bwtc.publish.start";
/**
* server notice client to complete the uploading/publish bandwidth test.
*/
public static const StatusSrsBwtcPublishStop:String = "srs.bwtc.publish.stop";
/**
* constructor, do nothing
*/
public function SrsBandwidth()
{
}
/**
* initialize the bandwidth test tool, the callbacks. null to ignore.
*
* the as callbacks.
* @param as_on_ready, function():void, callback when bandwidth tool is ready to run.
* @param as_on_status_change, function(code:String, data:String):void, where:
* code can be:
* "NetConnection.Connect.Failed", see NetStatusEvent(evt.info.code).
* "NetConnection.Connect.Rejected", see NetStatusEvent(evt.info.code).
* "NetConnection.Connect.Success", see NetStatusEvent(evt.info.code).
* "NetConnection.Connect.Closed", see NetStatusEvent(evt.info.code).
* SrsBandwidth.StatusSrsBwtcPlayStart, "srs.bwtc.play.start", when srs start test play bandwidth.
* SrsBandwidth.StatusSrsBwtcPlayStop, "srs.bwtc.play.stop", when srs complete test play bandwidth.
* SrsBandwidth.StatusSrsBwtcPublishStart, "srs.bwtc.publish.start", when srs start test publish bandwidth.
* SrsBandwidth.StatusSrsBwtcPublishStop, "srs.bwtc.publish.stop", when srs complete test publish bandwidth.
* data is extra parameter:
* kbps, for code is SrsBandwidth.StatusSrsBwtcPlayStop or SrsBandwidth.StatusSrsBwtcPublishStop.
* "", otherwise empty string.
* @param as_on_progress_change, function(percent:Number):void, where:
* percent, the progress percent, 0 means 0%, 100 means 100%.
* @param as_on_srs_info, function(srs_server:String, srs_primary:String, srs_authors:String, srs_id:String, srs_pid:String, srs_server_ip:String):void, where:
* srs_server: the srs server info.
* srs_primary: the srs primary authors info.
* srs_authors: the srs authors info.
* srs_id: the tracable log id, to direclty grep the log.
* srs_pid: the srs process id, to direclty grep the log.
* srs_server_ip: the srs server ip, where client connected at.
* @param as_on_complete, function(start_time:Number, end_time:Number, play_kbps:Number, publish_kbps:Number, play_bytes:Number, publish_bytes:Number, play_time:Number, publish_time:Number):void, where
* start_time, the start timestamp, in ms.
* end_time, the finish timestamp, in ms.
* play_kbps, the play/downloading kbps.
* publish_kbps, the publish/uploading kbps.
* play_bytes, the bytes play/download from server, in bytes.
* publish_bytes, the bytes publish/upload to server, in bytes.
* play_time, the play/download duration time, in ms.
* publish_time, the publish/upload duration time, in ms.
*
* the js callback id.
* @param js_id, specifies the id of swfobject, used to identify the bandwidth object.
* for all js callback, the first param always be the js_id, to identify the callback object.
*
* the js callbacks.
* @param js_on_ready, function(js_id:String):void, callback when bandwidth tool is ready to run.
* @param js_on_status_change, function(js_id:String, code:String, data:String):void
* @param as_on_progress_change, function(js_id:String, percent:Number):void
* @param as_on_srs_info, function(js_id:String, srs_server:String, srs_primary:String, srs_authors:String, srs_id:String, srs_pid:String, srs_server_ip:String):void
* @param as_on_complete, function(js_id:String, start_time:Number, end_time:Number, play_kbps:Number, publish_kbps:Number, play_bytes:Number, publish_bytes:Number, play_time:Number, publish_time:Number):void
*
* the js export functions.
* @param js_export_check_bandwidth, function(url:String):void, for js to start bandwidth check, @see: check_bandwidth(url:String):void
* @param js_export_stop, function():void, for js to stop bandwidth check, @see: stop():void
*
* @remark, all parameters can be null.
* @remark, as and js callback use same parameter, except that the js calblack first parameter is js_id:String.
*/
public function initialize(
as_on_ready:Function, as_on_status_change:Function, as_on_progress_change:Function, as_on_srs_info:Function, as_on_complete:Function,
js_id:String, js_on_ready:String, js_on_status_change:String, js_on_progress_change:String, js_on_srs_info:String, js_on_complete:String,
js_export_check_bandwidth:String, js_export_stop:String
):void {
this.as_on_ready = as_on_ready;
this.as_on_srs_info = as_on_srs_info;
this.as_on_status_change = as_on_status_change;
this.as_on_progress_change = as_on_progress_change;
this.as_on_complete = as_on_complete;
this.js_id = js_id;
this.js_on_srs_info = js_on_srs_info;
this.js_on_ready = js_on_ready;
this.js_on_status_change = js_on_status_change;
this.js_on_progress_change = js_on_progress_change;
this.js_on_complete = js_on_complete;
this.js_export_check_bandwidth = js_export_check_bandwidth;
this.js_export_stop = js_export_stop;
flash.utils.setTimeout(this.system_on_js_ready, 0);
}
/**
* start check bandwidth.
* @param url, a String indicates the url to check bandwidth,
* format as: rtmp://server:port/app?key=xxx&&vhost=xxx
* for example, rtmp://dev:1935/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com
* where the key and vhost must be config in SRS, like:
* vhost bandcheck.srs.com {
* enabled on;
* chunk_size 65000;
* bandcheck {
* enabled on;
* key "35c9b402c12a7246868752e2878f7e0e";
* interval 30;
* limit_kbps 4000;
* }
* }
*
* @remark user must invoke this as method, or js exported method.
*/
public function check_bandwidth(url:String):void {
this.js_call_check_bandwidth(url);
}
/**
* stop check bancwidth.
* @remark it's optional, however, user can abort the bandwidth check.
*/
public function stop():void {
this.js_call_stop();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// Private Section, ignore please. ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
////////////////////////// ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* ***********************************************************************
* private section, including private fields, method and embeded classes.
* ***********************************************************************
*/
/**
* as callback.
*/
private var as_on_ready:Function;
private var as_on_srs_info:Function;
private var as_on_status_change:Function;
private var as_on_progress_change:Function;
private var as_on_complete:Function;
/**
* js callback.
*/
private var js_id:String;
private var js_on_ready:String;
private var js_on_srs_info:String;
private var js_on_status_change:String;
private var js_on_progress_change:String;
private var js_on_complete:String;
/**
* js export functions.
*/
private var js_export_check_bandwidth:String;
private var js_export_stop:String;
/**
* srs debug infos
*/
private var srs_server:String = null;
private var srs_primary:String = null;
private var srs_authors:String = null;
private var srs_id:String = null;
private var srs_pid:String = null;
private var srs_server_ip:String = null;
/**
* the underlayer connection, to send call message to do the bandwidth
* check/test with server.
*/
private var connection:NetConnection = null;
// for bms4, use stream to play then do bandwidth test.
private var stream:NetStream = null;
/**
* use timeout to sendout publish call packets.
* when got stop publish packet from server, stop publish call loop.
*/
private var publish_timeout_handler:uint = 0;
/**
* system callack event, when js ready, register callback for js.
* the actual main function.
*/
private function system_on_js_ready():void {
if (!flash.external.ExternalInterface.available) {
log("js not ready, try later.");
flash.utils.setTimeout(this.system_on_js_ready, 100);
return;
}
if (this.js_export_check_bandwidth != null) {
flash.external.ExternalInterface.addCallback(this.js_export_check_bandwidth, this.js_call_check_bandwidth);
}
if (this.js_export_stop != null) {
flash.external.ExternalInterface.addCallback(this.js_export_stop, this.js_call_stop);
}
if (as_on_ready != null) {
as_on_ready();
}
if (js_on_ready != null) {
flash.external.ExternalInterface.call(this.js_on_ready, this.js_id);
}
}
private function js_call_check_bandwidth(url:String):void {
js_call_stop();
__on_progress_change(0);
// init connection
log("create connection for bandwidth check");
connection = new NetConnection;
connection.objectEncoding = ObjectEncoding.AMF0;
connection.client = {
onStatus: onStatus,
// play
onSrsBandCheckStartPlayBytes: onSrsBandCheckStartPlayBytes,
onSrsBandCheckPlaying: onSrsBandCheckPlaying,
onSrsBandCheckStopPlayBytes: onSrsBandCheckStopPlayBytes,
// publish
onSrsBandCheckStartPublishBytes: onSrsBandCheckStartPublishBytes,
onSrsBandCheckStopPublishBytes: onSrsBandCheckStopPublishBytes,
onSrsBandCheckFinished: onSrsBandCheckFinished
};
connection.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
connection.connect(url);
__on_progress_change(3);
}
private function js_call_stop():void {
if (connection) {
connection.close();
connection = null;
}
}
/**
* NetConnection callback this function, when recv server call "onSrsBandCheckStartPlayBytes"
* then start @updatePlayProgressTimer for updating the progressbar
* */
private function onSrsBandCheckStartPlayBytes(evt:Object):void{
var duration_ms:Number = evt.duration_ms;
var interval_ms:Number = evt.interval_ms;
log("start play test, duration=" + duration_ms + ", interval=" + interval_ms);
connection.call("onSrsBandCheckStartingPlayBytes", null);
__on_status_change(SrsBandwidth.StatusSrsBwtcPlayStart);
__on_progress_change(10);
}
private function onSrsBandCheckPlaying(evt:Object):void{
}
private function onSrsBandCheckStopPlayBytes(evt:Object):void{
var duration_ms:Number = evt.duration_ms;
var interval_ms:Number = evt.interval_ms;
var duration_delta:Number = evt.duration_delta;
var bytes_delta:Number = evt.bytes_delta;
var kbps:Number = 0;
if(duration_delta > 0){
kbps = bytes_delta * 8.0 / duration_delta; // b/ms == kbps
}
kbps = (int(kbps * 10))/10.0;
flash.utils.setTimeout(stopPlayTest, 0);
__on_status_change(SrsBandwidth.StatusSrsBwtcPlayStop, String(kbps));
__on_progress_change(40);
}
private function stopPlayTest():void{
connection.call("onSrsBandCheckStoppedPlayBytes", null);
}
/**
* publishing methods.
*/
private function onSrsBandCheckStartPublishBytes(evt:Object):void{
var duration_ms:Number = evt.duration_ms;
var interval_ms:Number = evt.interval_ms;
connection.call("onSrsBandCheckStartingPublishBytes", null);
flash.utils.setTimeout(publisher, 0);
__on_status_change(SrsBandwidth.StatusSrsBwtcPublishStart);
__on_progress_change(60);
}
private function publisher():void{
var data:Array = new Array();
/**
* the data size cannot too large, it will increase the test time.
* server need atleast got one packet, then timeout to stop the publish.
*
* cannot too small neither, it will limit the max publish kbps.
*
* the test values:
* test_s test_s
* data_size max_publish_kbps (no limit) (limit upload to 5KBps)
* 100 2116 6.5 7.3
* 200 4071 6.5 7.7
* 300 6438 6.5 10.3
* 400 9328 6.5 10.2
* 500 10377 6.5 10.0
* 600 13737 6.5 10.8
* 700 15635 6.5 12.0
* 800 18103 6.5 14.0
* 900 20484 6.5 14.2
* 1000 21447 6.5 16.8
*/
var data_size:int = 900;
for(var i:int; i < data_size; i++) {
data.push("SrS band check data from client's publishing......");
}
connection.call("onSrsBandCheckPublishing", null, data);
publish_timeout_handler = flash.utils.setTimeout(publisher, 0);
}
private function onSrsBandCheckStopPublishBytes(evt:Object):void{
var duration_ms:Number = evt.duration_ms;
var interval_ms:Number = evt.interval_ms;
var duration_delta:Number = evt.duration_delta;
var bytes_delta:Number = evt.bytes_delta;
var kbps:Number = 0;
if(duration_delta > 0){
kbps = bytes_delta * 8.0 / duration_delta; // b/ms == kbps
}
kbps = (int(kbps * 10))/10.0;
stopPublishTest();
__on_progress_change(90);
}
private function stopPublishTest():void{
// the stop publish response packet can not send out, for the queue is full.
//connection.call("onSrsBandCheckStoppedPublishBytes", null);
// clear the timeout to stop the send loop.
if (publish_timeout_handler > 0) {
flash.utils.clearTimeout(publish_timeout_handler);
publish_timeout_handler = 0;
}
}
private function onSrsBandCheckFinished(evt:Object):void{
var start_time:Number = evt.start_time;
var end_time:Number = evt.end_time;
var play_kbps:Number = evt.play_kbps;
var publish_kbps:Number = evt.publish_kbps;
var play_bytes:Number = evt.play_bytes;
var play_time:Number = evt.play_time;
var publish_bytes:Number = evt.publish_bytes;
var publish_time:Number = evt.publish_time;
if (this.as_on_complete != null) {
this.as_on_complete(start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time);
}
if (this.js_on_complete != null) {
flash.external.ExternalInterface.call(this.js_on_complete, this.js_id,
start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time);
}
__on_progress_change(100);
// when got finish packet, directly close connection.
js_call_stop();
// the last final packet can not send out, for the queue is full.
//connection.call("finalClientPacket", null);
}
/**
* get NetConnection NetStatusEvent
*/
private function onStatus(evt:NetStatusEvent): void {
log(evt.info.code);
var srs_version:String = null;
if (evt.info.hasOwnProperty("data") && evt.info.data) {
if (evt.info.data.hasOwnProperty("srs_server")) {
srs_server = evt.info.data.srs_server;
}
if (evt.info.data.hasOwnProperty("srs_primary")) {
srs_primary = evt.info.data.srs_primary;
}
if (evt.info.data.hasOwnProperty("srs_authors")) {
srs_authors = evt.info.data.srs_authors;
}
if (evt.info.data.hasOwnProperty("srs_id")) {
srs_id = evt.info.data.srs_id;
}
if (evt.info.data.hasOwnProperty("srs_pid")) {
srs_pid = evt.info.data.srs_pid;
}
if (evt.info.data.hasOwnProperty("srs_server_ip")) {
srs_server_ip = evt.info.data.srs_server_ip;
}
if (evt.info.data.hasOwnProperty("srs_version")) {
srs_version = evt.info.data.srs_version;
}
if (this.as_on_srs_info != null) {
this.as_on_srs_info(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip);
}
if (this.js_on_srs_info != null) {
flash.external.ExternalInterface.call(this.js_on_srs_info, this.js_id,
srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip);
}
}
var e:NetStatusEvent = evt;
var foo:Function = function():void{
var evt:NetStatusEvent = e;
if (evt.info.code) {
__on_status_change(evt.info.code);
}
switch(evt.info.code){
case "NetConnection.Connect.Success":
__on_progress_change(8);
break;
}
};
foo();
// for bms4, play stream to trigger the bandwidth check.
if (evt.info.code != "NetConnection.Connect.Success") {
return;
}
if (stream != null) {
return;
}
var is_bms:Boolean = false;
if (srs_server.indexOf("BMS/") == 0 || srs_server.indexOf("UPYUN/") == 0) {
is_bms = true;
}
if (parseInt(srs_version.charAt(0)) >= 4 && is_bms) {
stream = new NetStream(connection);
stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void{
log(evt.info.code);
if (evt.info.code == "NetStream.Play.Start") {
}
});
stream.play("test");
log("play stream for " + srs_server + " " + srs_version);
return;
}
}
/**
* invoke the callback.
*/
private function __on_progress_change(percent:Number):void {
if (this.as_on_progress_change != null) {
this.as_on_progress_change(percent);
}
if (this.js_on_progress_change != null) {
flash.external.ExternalInterface.call(this.js_on_progress_change, this.js_id,
percent);
}
}
private function __on_status_change(code:String, data:String=""):void {
if (this.as_on_status_change != null) {
this.as_on_status_change(code, data);
}
if (this.js_on_status_change != null) {
flash.external.ExternalInterface.call(this.js_on_status_change, this.js_id,
code, data);
}
}
private function log(msg:String):void {
trace(msg);
if (ExternalInterface.available) {
ExternalInterface.call("console.log", msg);
}
}
}
}

@ -1,234 +0,0 @@
//
// Copyright (c) 2013-2021 Winlin
//
// SPDX-License-Identifier: MIT
//
/**
* the SrsBandwidth library for js to do bandwidth test.
* @param container the html container id.
* @param width a float value specifies the width of bandwidth.
* @param height a float value specifies the height of bandwidth.
* @param private_object [optional] an object that used as private object,
* for example, the logic chat object which owner this bandwidth.
* Usage:
var bandwidth = new SrsBandwidth("container_id", 100, 1);
bandwidth.on_bandwidth_ready = function() {
// auto start check bandwidth when tool is ready.
this.check_bandwidth(url);
}
bandwidth.on_update_progress = function(percent) {
// console.log(percent + "%");
}
bandwidth.on_update_status = function(status) {
// console.log(status);
}
bandwidth.on_srs_info = function(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip) {
// console.log(
// "server:" + srs_server + ", primary:" + srs_primary + ", authors:" + srs_authors +
// ", srs_id:" + srs_id + ", srs_pid:" + srs_pid + ", ip:" + srs_server_ip
//);
}
bandwidth.render("rtmp://dev:1935/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com");
* where the HTML page must contains an element:
<div id="container_id"></div>
* this js will directly erase the container by swfobject.
*/
function SrsBandwidth(container, width, height, private_object) {
if (!SrsBandwidth.__id) {
SrsBandwidth.__id = 100;
}
if (!SrsBandwidth.__bandwidths) {
SrsBandwidth.__bandwidths = [];
}
SrsBandwidth.__bandwidths.push(this);
this.private_object = private_object;
this.container = container;
this.width = width;
this.height = height;
this.id = SrsBandwidth.__id++;
this.stream_url = null;
this.callbackObj = null;
// the callback set data.
this.percent = 0;
this.status = "";
this.server = "";
this.completed = false;
}
/**
* user can set some callback, then start the bandwidth.
* @param url the bandwidth test url.
* callbacks:
* on_bandwidth_ready():void, when srs bandwidth ready, user can play.
* on_update_progress(percent:Number):void, when srs bandwidth update the progress.
* percent:Number 100 means 100%.
* on_update_status(status:String):void, when srs bandwidth update the status.
* status:String the human readable status text.
*/
SrsBandwidth.prototype.render = function(url) {
if (url) {
this.stream_url = url;
}
// embed the flash.
var flashvars = {};
flashvars.id = this.id;
flashvars.on_bandwidth_ready = "__srs_on_bandwidth_ready";
flashvars.on_update_progress = "__srs_on_update_progress";
flashvars.on_update_status = "__srs_on_update_status";
flashvars.on_srs_info = "__srs_on_srs_info";
flashvars.on_complete = "__srs_on_complete";
var params = {};
params.wmode = "opaque";
params.allowFullScreen = "true";
params.allowScriptAccess = "always";
var attributes = {};
var self = this;
swfobject.embedSWF(
"srs_bwt/release/srs_bwt.swf?_version="+srs_get_version_code(),
this.container,
this.width, this.height,
"11.1.0", "js/AdobeFlashbandwidthInstall.swf",
flashvars, params, attributes,
function(callbackObj){
self.callbackObj = callbackObj;
}
);
return this;
}
/**
* play the stream.
* @param stream_url the url of stream, rtmp or http.
*/
SrsBandwidth.prototype.check_bandwidth = function(url) {
this.stop();
SrsBandwidth.__bandwidths.push(this);
// the callback set data.
this.percent = 0;
this.status = "";
this.server = "";
this.completed = false;
if (url) {
this.stream_url = url;
}
this.callbackObj.ref.__check_bandwidth(this.stream_url);
}
SrsBandwidth.prototype.stop = function(url) {
for (var i = 0; i < SrsBandwidth.__bandwidths.length; i++) {
var bandwidth = SrsBandwidth.__bandwidths[i];
if (bandwidth.id != this.id) {
continue;
}
SrsBandwidth.__bandwidths.splice(i, 1);
break;
}
this.callbackObj.ref.__stop();
}
SrsBandwidth.prototype.on_bandwidth_ready = function() {
}
SrsBandwidth.prototype.on_update_progress = function(percent) {
}
SrsBandwidth.prototype.on_update_status = function(status) {
}
SrsBandwidth.prototype.on_srs_info = function(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip) {
}
SrsBandwidth.prototype.on_complete = function(start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time) {
}
SrsBandwidth.prototype.on_error = function(code) {
}
function __srs_find_bandwidth(id) {
for (var i = 0; i < SrsBandwidth.__bandwidths.length; i++) {
var bandwidth = SrsBandwidth.__bandwidths[i];
if (bandwidth.id != id) {
continue;
}
return bandwidth;
}
throw new Error("bandwidth not found. id=" + id);
}
function __srs_on_bandwidth_ready(id) {
var bandwidth = __srs_find_bandwidth(id);
bandwidth.on_bandwidth_ready();
}
function __srs_on_update_progress(id, percent) {
var bandwidth = __srs_find_bandwidth(id);
bandwidth.percent = percent;
bandwidth.on_update_progress(percent);
}
function __srs_on_update_status(id, code, data) {
var bandwidth = __srs_find_bandwidth(id);
var status = "";
switch(code){
case "NetConnection.Connect.Failed":
if (bandwidth.completed) {
return;
}
bandwidth.on_error(code);
status = "连接服务器失败!";
break;
case "NetConnection.Connect.Rejected":
if (bandwidth.completed) {
return;
}
bandwidth.completed = true;
bandwidth.on_update_progress(100);
bandwidth.on_error(code);
status = "服务器拒绝连接,测速过于频繁!";
break;
case "NetConnection.Connect.Success":
status = "连接服务器成功!";
break;
case "NetConnection.Connect.Closed":
if (bandwidth.completed) {
return;
}
bandwidth.on_error(code);
status = "连接已断开!";
break;
case "srs.bwtc.play.start":
status = "开始测试下行带宽";
break;
case "srs.bwtc.play.stop":
bandwidth.completed = true;
status = "下行带宽测试完毕," + data + "kbps开始测试上行带宽。";
break;
default:
return;
}
bandwidth.status = status;
bandwidth.on_update_status(status);
}
function __srs_on_srs_info(id, srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip) {
var bandwidth = __srs_find_bandwidth(id);
bandwidth.status = status;
bandwidth.server = srs_server_ip;
bandwidth.on_srs_info(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip);
}
function __srs_on_complete(id, start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time) {
var bandwidth = __srs_find_bandwidth(id);
var status = "检测结束: " + bandwidth.server + " 上行: " + publish_kbps + " kbps" + " 下行: " + play_kbps + " kbps"
+ " 测试时间: " + Number((end_time - start_time) / 1000).toFixed(1) + " 秒";
bandwidth.status = status;
bandwidth.on_update_status(status);
bandwidth.on_complete(start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time);
}

@ -1,186 +0,0 @@
//
// Copyright (c) 2013-2021 Winlin
//
// SPDX-License-Identifier: MIT
//
package
{
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.system.System;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.Timer;
import flash.utils.setTimeout;
public class srs_bwt extends Sprite
{
/**
* the SRS bandwidth check/test library object.
*/
private var bandwidth:SrsBandwidth = new SrsBandwidth();
/**
* when not specifies any param, directly run the swf.
*/
private var default_url:String = "rtmp://dev:1935/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com";
public function srs_bwt()
{
if (!this.stage) {
this.addEventListener(Event.ADDED_TO_STAGE, this.system_on_add_to_stage);
} else {
this.system_on_add_to_stage(null);
}
}
private function system_on_add_to_stage(evt:Event):void {
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
// init context menu
var myMenu:ContextMenu = new ContextMenu();
myMenu.hideBuiltInItems();
myMenu.customItems.push(new ContextMenuItem("SRS带宽测试工具", true));
this.contextMenu = myMenu;
check_bandwidth();
}
private function check_bandwidth():void {
// closure
var self:srs_bwt = this;
/////////////////////////////////////////////////////////////////////
// initialize the bandwidth check/test library
/////////////////////////////////////////////////////////////////////
// js callback, set to null if ignore.
var conf:Object = this.root.loaderInfo.parameters;
var js_id:String = conf.id? conf.id:null;
var js_on_ready:String = conf.on_bandwidth_ready? conf.on_bandwidth_ready:null;
var js_on_srs_info:String = conf.on_srs_info? conf.on_srs_info:null;
var js_on_progress_change:String = conf.on_update_progress? conf.on_update_progress:null;
var js_on_status_change:String = conf.on_update_status? conf.on_update_status:null;
var js_on_complete:String = conf.on_complete? conf.on_complete:null;
// js export, set to null to disable
var js_export_check_bandwidth:String = "__check_bandwidth";
var js_export_stop:String = "__stop";
// as callback, set to null if ignore.
var as_on_ready:Function = function():void {
self.on_ready();
};
var as_on_status_change:Function = function(code:String, data:String):void {
self.on_status_change(code, data);
};
var as_on_progress_change:Function = function(percent:Number):void {
self.on_progress(percent);
};
var as_on_srs_info:Function = function(srs_server:String, srs_primary:String, srs_authors:String, srs_id:String, srs_pid:String, srs_server_ip:String):void {
self.update_context_items(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip);
};
var as_on_complete:Function = function(start_time:Number, end_time:Number, play_kbps:Number, publish_kbps:Number, play_bytes:Number, publish_bytes:Number, play_time:Number, publish_time:Number):void {
self.on_complete(start_time, end_time, play_kbps, publish_kbps, play_bytes, publish_bytes, play_time, publish_time);
};
bandwidth.initialize(
as_on_ready, as_on_status_change, as_on_progress_change, as_on_srs_info, as_on_complete,
js_id, js_on_ready, js_on_status_change, js_on_progress_change, js_on_srs_info, js_on_complete,
js_export_check_bandwidth, js_export_stop
);
/////////////////////////////////////////////////////////////////////
}
private function on_ready():void {
var conf:Object = this.root.loaderInfo.parameters;
// for directly run swf.
if (!conf.id) {
log("directly run swf, load default url: " + this.default_url);
this.bandwidth.check_bandwidth(this.default_url);
}
}
private function on_progress(percent:Number):void {
log("progress:" + percent + "%");
}
private function update_context_items(
srs_server:String, srs_primary:String, srs_authors:String,
srs_id:String, srs_pid:String, srs_server_ip:String
):void {
// for context menu
var customItems:Array = [new ContextMenuItem("SrsPlayer")];
if (srs_server != null) {
customItems.push(new ContextMenuItem("Server: " + srs_server));
}
if (srs_primary != null) {
customItems.push(new ContextMenuItem("Primary: " + srs_primary));
}
if (srs_authors != null) {
customItems.push(new ContextMenuItem("Authors: " + srs_authors));
}
if (srs_server_ip != null) {
customItems.push(new ContextMenuItem("SrsIp: " + srs_server_ip));
}
if (srs_pid != null) {
customItems.push(new ContextMenuItem("SrsPid: " + srs_pid));
}
if (srs_id != null) {
customItems.push(new ContextMenuItem("SrsId: " + srs_id));
}
contextMenu.customItems = customItems;
}
public function on_status_change(code:String, data:String): void {
log(code);
switch(code){
case "NetConnection.Connect.Failed":
log("连接服务器失败!");
break;
case "NetConnection.Connect.Rejected":
log("服务器拒绝连接!");
break;
case "NetConnection.Connect.Success":
log("连接服务器成功!");
break;
case SrsBandwidth.StatusSrsBwtcPlayStart:
log("开始测试下行带宽");
break;
case SrsBandwidth.StatusSrsBwtcPlayStop:
log("下行带宽测试完毕," + data + "kbps开始测试上行带宽。");
break;
case SrsBandwidth.StatusSrsBwtcPublishStart:
log("开始测试上行带宽");
break;
case SrsBandwidth.StatusSrsBwtcPublishStop:
log("上行带宽测试完毕," + data + "kbps");
break;
case "NetConnection.Connect.Closed":
log("连接已断开!");
break;
}
}
private function on_complete(
start_time:Number, end_time:Number, play_kbps:Number, publish_kbps:Number,
play_bytes:Number, publish_bytes:Number, play_time:Number, publish_time:Number
):void {
var status:String = "检测结束: 上行: " + publish_kbps + " kbps" + " 下行: " + play_kbps + " kbps"
+ " 测试时间: " + Number((end_time - start_time) / 1000).toFixed(1) + " 秒";
log(status);
}
private function log(msg:String):void {
trace(msg);
if (ExternalInterface.available) {
ExternalInterface.call("console.log", msg);
}
}
}
}

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="srs_player.as" projectUUID="1bb41a0e-6b1f-49b5-8603-219442f9f9b3" version="10">
<compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="false" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="release" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
<excludedEntries>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
</excludedEntries>
</libraryPathEntry>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="srs_player.as"/>
</applications>
<modules/>
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>srs_player</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
</projectDescription>

@ -1,3 +0,0 @@
#Wed Dec 18 10:07:19 CST 2013
eclipse.preferences.version=1
encoding/<project>=utf-8

File diff suppressed because it is too large Load Diff

@ -1,210 +0,0 @@
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.FullScreenEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.URLVariables;
import flash.system.Security;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.utils.setTimeout;
import flashx.textLayout.formats.Float;
/**
* common player to play rtmp/flv stream,
* use system NetStream.
*/
public class Player
{
// refresh every ts_fragment_seconds*M3u8RefreshRatio
public static var M3u8RefreshRatio:Number = 0.3;
// parse ts every this ms.
public static var TsParseAsyncInterval:Number = 80;
private var js_id:String = null;
// play param url.
private var user_url:String = null;
private var media_stream:NetStream = null;
private var media_conn:NetConnection = null;
private var owner:srs_player = null;
public function Player(o:srs_player) {
owner = o;
}
public function init(flashvars:Object):void {
this.js_id = flashvars.id;
}
public function stream():NetStream {
return this.media_stream;
}
private function dumps_object(obj:Object):String {
var smr:String = "";
for (var k:String in obj) {
smr += k + "=" + obj[k] + ", ";
}
return smr;
}
public function play(url:String):void {
owner.on_player_status("init", "Ready to play");
var streamName:String;
this.user_url = url;
this.media_conn = new NetConnection();
this.media_conn.client = {};
this.media_conn.client.onBWDone = function():void {};
this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
log("NetConnection: type=" + evt.type + ", bub=" + evt.bubbles + ", can=" + evt.cancelable
+ ", info is " + dumps_object(evt.info));
if (evt.info.hasOwnProperty("data") && evt.info.data) {
owner.on_player_metadata(evt.info.data);
}
// reject by server, maybe redirect.
if (evt.info.code == "NetConnection.Connect.Rejected") {
// RTMP 302 redirect.
if (evt.info.hasOwnProperty("ex") && evt.info.ex.code == 302) {
streamName = url.substr(url.lastIndexOf("/") + 1);
url = evt.info.ex.redirect + "/" + streamName;
log("Async RTMP 302 Redirect to: " + url);
// notify server.
media_conn.call("Redirected", null, evt.info.ex.redirect);
// do 302.
owner.on_player_302(url);
return;
}
owner.on_player_status("rejected", "Server reject play");
close();
}
if (evt.info.code == "NetConnection.Connect.Success") {
owner.on_player_status("connected", "Connected at server");
}
if (evt.info.code == "NetConnection.Connect.Closed") {
close();
}
if (evt.info.code == "NetConnection.Connect.Failed") {
owner.on_player_status("failed", "Connect to server failed.");
close();
}
// TODO: FIXME: failed event.
if (evt.info.code != "NetConnection.Connect.Success") {
return;
}
if (url.indexOf(".m3u8") > 0) {
media_stream = new HlsNetStream(M3u8RefreshRatio, TsParseAsyncInterval, media_conn);
} else {
media_stream = new NetStream(media_conn);
}
media_stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
log("NetStream: type=" + evt.type + ", bub=" + evt.bubbles + ", can=" + evt.cancelable
+ ", info is " + dumps_object(evt.info));
if (evt.info.code == "NetStream.Play.Start") {
owner.on_player_status("play", "Start to play stream");
}
if (evt.info.code == "NetStream.Play.StreamNotFound") {
owner.on_player_status("rejected", "Stream not found");
close();
}
if (evt.info.code == "NetStream.Video.DimensionChange") {
owner.on_player_dimension_change();
} else if (evt.info.code == "NetStream.Buffer.Empty") {
owner.on_player_buffer_empty();
} else if (evt.info.code == "NetStream.Buffer.Full") {
owner.on_player_buffer_full();
}
// TODO: FIXME: failed event.
});
// setup stream before play.
owner.on_player_before_play();
if (url.indexOf("http") == 0) {
media_stream.play(url);
} else {
streamName = url.substr(url.lastIndexOf("/") + 1);
media_stream.play(streamName);
}
owner.on_player_play();
});
if (url.indexOf("http") == 0) {
this.media_conn.connect(null);
} else {
var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));
streamName = url.substr(url.lastIndexOf("/") + 1);
// parse vhost from stream query.
if (streamName.indexOf("?") >= 0) {
var uv:URLVariables = new URLVariables(user_url.substr(user_url.indexOf("?") + 1));
var domain:String = uv["domain"];
if (!domain) {
domain = uv["vhost"];
}
if (domain) {
tcUrl += "?vhost=" + domain;
}
}
this.media_conn.connect(tcUrl);
}
}
public function close():void {
var notify:Boolean = false;
if (this.media_stream) {
this.media_stream.close();
this.media_stream = null;
notify = true;
}
if (this.media_conn) {
this.media_conn.close();
this.media_conn = null;
notify = true;
}
if (notify) {
owner.on_player_status("closed", "Server closed.");
}
}
private function log(msg:String):void {
Utility.log(js_id, msg);
}
}
}

@ -1,51 +0,0 @@
package
{
import flash.external.ExternalInterface;
import flash.utils.setTimeout;
/**
* the utility functions.
*/
public class Utility
{
/**
* total log.
*/
public static var logData:String = "";
/**
* whether string s endswith f.
*/
public static function stringEndswith(s:String, f:String):Boolean {
return s && f && s.indexOf(f) == s.length - f.length;
}
/**
* whether string s startswith f.
*/
public static function stringStartswith(s:String, f:String):Boolean {
return s && f && s.indexOf(f) == 0;
}
/**
* write log to trace and console.log.
* @param msg the log message.
*/
public static function log(js_id:String, msg:String):void {
if (js_id) {
msg = "[" + new Date() +"][srs-player][" + js_id + "] " + msg;
}
logData += msg + "\n";
trace(msg);
if (!flash.external.ExternalInterface.available) {
flash.utils.setTimeout(log, 300, null, msg);
return;
}
ExternalInterface.call("console.log", msg);
}
}
}

@ -1,668 +0,0 @@
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.FullScreenEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.system.Security;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.utils.setTimeout;
import flashx.textLayout.formats.Float;
public class srs_player extends Sprite
{
// user set id.
private var js_id:String = null;
// user set callback
private var js_on_player_ready:String = null;
private var js_on_player_metadata:String = null;
private var js_on_player_timer:String = null;
private var js_on_player_empty:String = null;
private var js_on_player_full:String = null;
private var js_on_player_status:String = null;
// play param, user set width and height
private var user_w:int = 0;
private var user_h:int = 0;
private var user_buffer_time:Number = 0;
private var user_max_buffer_time:Number = 0;
private var user_volume:Number = 0;
// user set dar den:num
private var user_dar_den:int = 0;
private var user_dar_num:int = 0;
// user set fs(fullscreen) refer and percent.
private var user_fs_refer:String = null;
private var user_fs_percent:int = 0;
// media specified.
private var media_video:Video = null;
private var media_metadata:Object = {};
private var media_timer:Timer = new Timer(300);
// controls.
// flash donot allow js to set to fullscreen,
// only allow user click to enter fullscreen.
private var control_fs_mask:Sprite = new Sprite();
// the common player to play stream.
private var player:Player = null;
// the flashvars config.
private var config:Object = null;
public function srs_player()
{
if (!this.stage) {
this.addEventListener(Event.ADDED_TO_STAGE, this.system_on_add_to_stage);
} else {
this.system_on_add_to_stage(null);
}
}
/**
* system event callback, when this control added to stage.
* the main function.
*/
private function system_on_add_to_stage(evt:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, this.system_on_add_to_stage);
this.stage.align = StageAlign.TOP_LEFT;
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, this.user_on_stage_fullscreen);
Security.allowDomain("*");
this.addChild(this.control_fs_mask);
this.control_fs_mask.buttonMode = true;
this.control_fs_mask.addEventListener(MouseEvent.CLICK, user_on_click_video);
this.contextMenu = new ContextMenu();
this.contextMenu.hideBuiltInItems();
var flashvars:Object = this.root.loaderInfo.parameters;
if (!flashvars.hasOwnProperty("id")) {
throw new Error("must specifies the id");
}
this.config = flashvars;
this.js_id = flashvars.id;
this.js_on_player_ready = flashvars.on_player_ready;
this.js_on_player_metadata = flashvars.on_player_metadata;
this.js_on_player_timer = flashvars.on_player_timer;
this.js_on_player_empty = flashvars.on_player_empty;
this.js_on_player_full = flashvars.on_player_full;
this.js_on_player_status = flashvars.on_player_status;
this.media_timer.addEventListener(TimerEvent.TIMER, this.system_on_timer);
this.media_timer.start();
flash.utils.setTimeout(this.system_on_js_ready, 0);
}
/**
* system callack event, when js ready, register callback for js.
* the actual main function.
*/
private function system_on_js_ready():void {
if (!flash.external.ExternalInterface.available) {
log("js not ready, try later.");
flash.utils.setTimeout(this.system_on_js_ready, 100);
return;
}
flash.external.ExternalInterface.addCallback("__play", this.js_call_play);
flash.external.ExternalInterface.addCallback("__stop", this.js_call_stop);
flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause);
flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume);
flash.external.ExternalInterface.addCallback("__set_dar", this.js_call_set_dar);
flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size);
flash.external.ExternalInterface.addCallback("__set_bt", this.js_call_set_bt);
flash.external.ExternalInterface.addCallback("__set_mbt", this.js_call_set_mbt);
flash.external.ExternalInterface.addCallback("__dump_log", this.js_call_dump_log);
flash.external.ExternalInterface.call(this.js_on_player_ready, this.js_id);
}
/**
* system callack event, timer to do some regular tasks.
*/
private function system_on_timer(evt:TimerEvent):void {
if (!player) {
return;
}
var ms:NetStream = player.stream();
if (!ms) {
//log("stream is null, ignore timer event.");
return;
}
var rtime:Number = flash.utils.getTimer();
var bitrate:Number = Number((ms.info.videoBytesPerSecond + ms.info.audioBytesPerSecond) * 8 / 1000);
log("on timer, time=" + ms.time.toFixed(2) + "s, buffer=" + ms.bufferLength.toFixed(2) + "s"
+ ", bitrate=" + bitrate.toFixed(1) + "kbps"
+ ", fps=" + ms.currentFPS.toFixed(1)
+ ", rtime=" + rtime.toFixed(0)
);
flash.external.ExternalInterface.call(
this.js_on_player_timer, this.js_id, ms.time, ms.bufferLength,
bitrate, ms.currentFPS, rtime
);
}
/**
* system callback event, when stream is empty.
*/
private function system_on_buffer_empty():void {
var time:Number = flash.utils.getTimer();
log("stream is empty at " + time + "ms");
flash.external.ExternalInterface.call(this.js_on_player_empty, this.js_id, time);
}
private function system_on_buffer_full():void {
var time:Number = flash.utils.getTimer();
log("stream is full at " + time + "ms");
flash.external.ExternalInterface.call(this.js_on_player_full, this.js_id, time);
}
/**
* system callack event, when got metadata from stream.
* or got video dimension change event(the DAR notification), to update the metadata manually.
*/
private function system_on_metadata(metadata:Object):void {
if (!media_metadata) {
media_metadata = {};
}
for (var k:String in metadata) {
media_metadata[k] = metadata[k];
}
// update the debug info.
on_debug_info(media_metadata);
update_context_items();
// for js.
var obj:Object = __get_video_size_object();
obj.server = 'srs';
obj.contributor = 'winlin';
if (srs_server != null) {
obj.server = srs_server;
}
if (srs_primary != null) {
obj.contributor = srs_primary;
}
if (srs_authors != null) {
obj.contributor = srs_authors;
}
if (srs_id != null) {
obj.cid = srs_id;
}
if (srs_pid != null) {
obj.pid = srs_pid;
}
if (srs_server_ip != null) {
obj.ip = srs_server_ip;
}
var s:String = "";
for (var key:String in obj) {
s += key + "=" + obj[key] + " ";
}
log("metadata is " + s);
var code:int = flash.external.ExternalInterface.call(js_on_player_metadata, js_id, obj);
if (code != 0) {
throw new Error("callback on_player_metadata failed. code=" + code);
}
}
/**
* player callack event, when user click video to enter or leave fullscreen.
*/
private function user_on_stage_fullscreen(evt:FullScreenEvent):void {
if (!evt.fullScreen) {
__execute_user_set_dar();
} else {
__execute_user_enter_fullscreen();
}
}
/**
* user event callback, js cannot enter the fullscreen mode, user must click to.
*/
private function user_on_click_video(evt:MouseEvent):void {
if (!this.stage.allowsFullScreen) {
log("donot allow fullscreen.");
return;
}
// enter fullscreen to get the fullscreen size correctly.
if (this.stage.displayState == StageDisplayState.FULL_SCREEN) {
this.stage.displayState = StageDisplayState.NORMAL;
} else {
this.stage.displayState = StageDisplayState.FULL_SCREEN;
}
}
/**
* function for js to call: to pause the stream. ignore if not play.
*/
private function js_call_pause():void {
if (player && player.stream()) {
player.stream().pause();
log("user pause play");
}
}
/**
* function for js to call: to resume the stream. ignore if not play.
*/
private function js_call_resume():void {
if (player && player.stream()) {
player.stream().resume();
log("user resume play");
}
}
/**
* dumps all log data.
*/
private function js_call_dump_log():String {
return Utility.logData;
}
/**
* to set the DAR, for example, DAR=16:9 where num=16,den=9.
* @param num, for example, 16.
* use metadata width if 0.
* use user specified width if -1.
* @param den, for example, 9.
* use metadata height if 0.
* use user specified height if -1.
*/
private function js_call_set_dar(num:int, den:int):void {
user_dar_num = num;
user_dar_den = den;
flash.utils.setTimeout(__execute_user_set_dar, 0);
log("user set dar to " + num + "/" + den);
}
/**
* set the fullscreen size data.
* @refer the refer fullscreen mode. it can be:
* video: use video orignal size.
* screen: use screen size to rescale video.
* @param percent, the rescale percent, where
* 100 means 100%.
*/
private function js_call_set_fs_size(refer:String, percent:int):void {
user_fs_refer = refer;
user_fs_percent = percent;
log("user set refer to " + refer + ", percent to" + percent);
}
/**
* set the stream buffer time in seconds.
* @buffer_time the buffer time in seconds.
*/
private function js_call_set_bt(buffer_time:Number):void {
if (player && player.stream()) {
player.stream().bufferTime = buffer_time;
log("user set bufferTime to " + buffer_time.toFixed(2) + "s");
}
}
/**
* set the max stream buffer time in seconds.
* @max_buffer_time the max buffer time in seconds.
* @remark this is the key feature for realtime communication by flash.
*/
private function js_call_set_mbt(max_buffer_time:Number):void {
if (player && player.stream()) {
player.stream().bufferTimeMax = max_buffer_time;
log("user set bufferTimeMax to " + max_buffer_time.toFixed(2) + "s");
}
}
/**
* function for js to call: to stop the stream. ignore if not play.
*/
private function js_call_stop():void {
if (this.media_video) {
this.removeChild(this.media_video);
this.media_video = null;
}
if (player) {
player.close();
player = null;
}
log("player stopped");
}
// srs infos
private var srs_server:String = null;
private var srs_primary:String = null;
private var srs_authors:String = null;
private var srs_id:String = null;
private var srs_pid:String = null;
private var srs_server_ip:String = null;
private function update_context_items():void {
// for context menu
var customItems:Array = [new ContextMenuItem("SrsPlayer")];
if (srs_server != null) {
customItems.push(new ContextMenuItem("Server: " + srs_server));
}
if (srs_primary != null) {
customItems.push(new ContextMenuItem("Primary: " + srs_primary));
}
if (srs_authors != null) {
customItems.push(new ContextMenuItem("Authors: " + srs_authors));
}
if (srs_server_ip != null) {
customItems.push(new ContextMenuItem("SrsIp: " + srs_server_ip));
}
if (srs_pid != null) {
customItems.push(new ContextMenuItem("SrsPid: " + srs_pid));
}
if (srs_id != null) {
customItems.push(new ContextMenuItem("SrsId: " + srs_id));
}
contextMenu.customItems = customItems;
}
/**
* server can set the debug info in _result of RTMP connect, or metadata.
*/
private function on_debug_info(data:*):void {
if (data.hasOwnProperty("srs_server")) {
srs_server = data.srs_server;
}
if (data.hasOwnProperty("srs_primary")) {
srs_primary = data.srs_primary;
}
if (data.hasOwnProperty("srs_authors")) {
srs_authors = data.srs_authors;
}
if (data.hasOwnProperty("srs_id")) {
srs_id = data.srs_id;
}
if (data.hasOwnProperty("srs_pid")) {
srs_pid = data.srs_pid;
}
if (data.hasOwnProperty("srs_server_ip")) {
srs_server_ip = data.srs_server_ip;
}
}
/**
* function for js to call: to play the stream. stop then play.
* @param url, the rtmp/http url to play.
* @param _width, the player width.
* @param _height, the player height.
* @param buffer_time, the buffer time in seconds. recommend to >=0.5
* @param max_buffer_time, the max buffer time in seconds. recommend to 3 x buffer_time.
* @param volume, the volume, 0 is mute, 1 is 100%, 2 is 200%.
*/
private function js_call_play(url:String, _width:int, _height:int, buffer_time:Number, max_buffer_time:Number, volume:Number):void {
this.user_w = _width;
this.user_h = _height;
this.user_buffer_time = buffer_time;
this.user_max_buffer_time = max_buffer_time;
this.user_volume = volume;
log("start to play url: " + url + ", w=" + this.user_w + ", h=" + this.user_h
+ ", buffer=" + buffer_time.toFixed(2) + "s, max_buffer=" + max_buffer_time.toFixed(2) + "s, volume=" + volume.toFixed(2)
);
js_call_stop();
// trim last ?
while (Utility.stringEndswith(url, "?")) {
url = url.substr(0, url.length - 1);
}
// create player.
player = new Player(this);
// init player by config.
player.init(config);
// play the url.
player.play(url);
}
public function on_player_before_play():void {
if (!player) {
return;
}
var ms:NetStream = player.stream();
if (!ms) {
return;
}
ms.soundTransform = new SoundTransform(user_volume);
ms.bufferTime = user_buffer_time;
ms.bufferTimeMax = user_max_buffer_time;
ms.client = {};
ms.client.onMetaData = system_on_metadata;
}
public function on_player_play():void {
if (!player) {
return;
}
media_video = new Video();
media_video.width = user_w;
media_video.height = user_h;
media_video.attachNetStream(player.stream());
media_video.smoothing = true;
addChild(media_video);
__draw_black_background(user_w, user_h);
// lowest layer, for mask to cover it.
setChildIndex(media_video, 0);
}
public function on_player_metadata(data:Object):void {
system_on_metadata(data);
}
public function on_player_302(url:String):void {
setTimeout(function():void{
log("Async RTMP 302 Redirected.");
js_call_play(url, user_w, user_h, user_buffer_time, user_max_buffer_time, user_volume);
}, 1000);
}
public function on_player_dimension_change():void {
system_on_metadata(media_metadata);
}
public function on_player_buffer_empty():void {
system_on_buffer_empty();
}
public function on_player_buffer_full():void {
system_on_buffer_full();
}
public function on_player_status(code:String, desc:String):void {
log("[STATUS] code=" + code + ", desc=" + desc);
flash.external.ExternalInterface.call(this.js_on_player_status, this.js_id, code, desc);
}
/**
* get the "right" size of video,
* 1. initialize with the original video object size.
* 2. override with metadata size if specified.
* 3. override with codec size if specified.
*/
private function __get_video_size_object():Object {
if (!media_video) {
return {};
}
var obj:Object = {
width: media_video.width,
height: media_video.height
};
// override with metadata size.
if (this.media_metadata.hasOwnProperty("width")) {
obj.width = this.media_metadata.width;
}
if (this.media_metadata.hasOwnProperty("height")) {
obj.height = this.media_metadata.height;
}
// override with codec size.
if (media_video.videoWidth > 0) {
obj.width = media_video.videoWidth;
}
if (media_video.videoHeight > 0) {
obj.height = media_video.videoHeight;
}
return obj;
}
/**
* execute the enter fullscreen action.
*/
private function __execute_user_enter_fullscreen():void {
if (!user_fs_refer || user_fs_percent <= 0) {
return;
}
// change to video size if refer to video.
var obj:Object = __get_video_size_object();
// get the DAR
var den:int = user_dar_den;
var num:int = user_dar_num;
if (den == 0) {
den = obj.height;
}
if (den == -1) {
den = this.stage.fullScreenHeight;
}
if (num == 0) {
num = obj.width;
}
if (num == -1) {
num = this.stage.fullScreenWidth;
}
// for refer is screen.
if (user_fs_refer == "screen") {
obj = {
width: this.stage.fullScreenWidth,
height: this.stage.fullScreenHeight
};
}
// rescale to fs
__update_video_size(num, den,
obj.width * user_fs_percent / 100,
obj.height * user_fs_percent / 100,
this.stage.fullScreenWidth, this.stage.fullScreenHeight
);
}
/**
* for user set dar, or leave fullscreen to recover the dar.
*/
private function __execute_user_set_dar():void {
// get the DAR
var den:int = user_dar_den;
var num:int = user_dar_num;
var obj:Object = __get_video_size_object();
if (den == 0) {
den = obj.height;
}
if (den == -1) {
den = this.user_h;
}
if (num == 0) {
num = obj.width;
}
if (num == -1) {
num = this.user_w;
}
__update_video_size(num, den, this.user_w, this.user_h, this.user_w, this.user_h);
}
/**
* update the video width and height,
* according to the specifies DAR(den:num) and max size(w:h).
* set the position of video(x,y) specifies by size(sw:sh),
* and update the bg to size(sw:sh).
* @param _num/_den the DAR. use to rescale the player together with paper size.
* @param _w/_h the video draw paper size. used to rescale the player together with DAR.
* @param _sw/_wh the stage size, >= paper size. used to center the player.
*/
private function __update_video_size(_num:int, _den:int, _w:int, _h:int, _sw:int, _sh:int):void {
if (!this.media_video || _den <= 0 || _num <= 0) {
return;
}
// set DAR.
// calc the height by DAR
var _height:int = _w * _den / _num;
if (_height <= _h) {
this.media_video.width = _w;
this.media_video.height = _height;
} else {
// height overflow, calc the width by DAR
var _width:int = _h * _num / _den;
this.media_video.width = _width;
this.media_video.height = _h;
}
// align center.
this.media_video.x = (_sw - this.media_video.width) / 2;
this.media_video.y = (_sh - this.media_video.height) / 2;
__draw_black_background(_sw, _sh);
}
/**
* draw black background and draw the fullscreen mask.
*/
private function __draw_black_background(_width:int, _height:int):void {
// draw black bg.
this.graphics.beginFill(0x00, 1.0);
this.graphics.drawRect(0, 0, _width, _height);
this.graphics.endFill();
// draw the fs mask.
this.control_fs_mask.graphics.beginFill(0xff0000, 0);
this.control_fs_mask.graphics.drawRect(0, 0, _width, _height);
this.control_fs_mask.graphics.endFill();
}
private function log(msg:String):void {
Utility.log(js_id, msg);
}
}
}

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="srs_publisher.as" projectUUID="f002791f-ee2e-41b7-aa3a-a7af6c65aa58" version="10">
<compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="false" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="release" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
<excludedEntries>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
</excludedEntries>
</libraryPathEntry>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="srs_publisher.as"/>
</applications>
<modules/>
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>srs_publisher</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
</projectDescription>

@ -1,3 +0,0 @@
#Wed Dec 18 10:10:45 CST 2013
eclipse.preferences.version=1
encoding/<project>=utf-8

@ -1,462 +0,0 @@
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.external.ExternalInterface;
import flash.media.Camera;
import flash.media.H264Profile;
import flash.media.H264VideoStreamSettings;
import flash.media.Microphone;
import flash.media.MicrophoneEnhancedMode;
import flash.media.MicrophoneEnhancedOptions;
import flash.media.SoundCodec;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.setTimeout;
public class srs_publisher extends Sprite
{
// user set id.
private var js_id:String = null;
// user set callback
private var js_on_publisher_ready:String = null;
private var js_on_publisher_error:String = null;
private var js_on_publisher_warn:String = null;
// publish param url.
private var user_url:String = null;
// play param, user set width and height
private var user_w:int = 0;
private var user_h:int = 0;
private var user_vcodec:Object = {};
private var user_acodec:Object = {};
// media specified.
private var media_conn:NetConnection = null;
private var media_stream:NetStream = null;
private var media_video:Video = null;
private var media_camera:Camera = null;
private var media_microphone:Microphone = null;
// error code.
private const error_camera_get:int = 100;
private const error_microphone_get:int = 101;
private const error_camera_muted:int = 102;
private const error_connection_closed:int = 103;
private const error_connection_failed:int = 104;
public function srs_publisher()
{
if (!this.stage) {
this.addEventListener(Event.ADDED_TO_STAGE, this.system_on_add_to_stage);
} else {
this.system_on_add_to_stage(null);
}
}
/**
* system event callback, when this control added to stage.
* the main function.
*/
private function system_on_add_to_stage(evt:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, this.system_on_add_to_stage);
this.stage.align = StageAlign.TOP_LEFT;
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.contextMenu = new ContextMenu();
this.contextMenu.hideBuiltInItems();
var flashvars:Object = this.root.loaderInfo.parameters;
if (!flashvars.hasOwnProperty("id")) {
throw new Error("must specifies the id");
}
this.js_id = flashvars.id;
this.js_on_publisher_ready = flashvars.on_publisher_ready;
this.js_on_publisher_error = flashvars.on_publisher_error;
this.js_on_publisher_warn = flashvars.on_publisher_warn;
// initialized size.
this.user_w = flashvars.width;
this.user_h = flashvars.height;
// try to get the camera, if muted, alert the security and requires user to open it.
var c:Camera = Camera.getCamera();
if (c.muted) {
Security.showSettings(SecurityPanel.PRIVACY);
}
__show_local_camera(c);
flash.utils.setTimeout(this.system_on_js_ready, 0);
}
/**
* system callack event, when js ready, register callback for js.
* the actual main function.
*/
private function system_on_js_ready():void {
if (!flash.external.ExternalInterface.available) {
trace("js not ready, try later.");
flash.utils.setTimeout(this.system_on_js_ready, 100);
return;
}
flash.external.ExternalInterface.addCallback("__publish", this.js_call_publish);
flash.external.ExternalInterface.addCallback("__stop", this.js_call_stop);
var cameras:Array = Camera.names;
var microphones:Array = Microphone.names;
trace("retrieve system cameras(" + cameras + ") and microphones(" + microphones + ")");
flash.external.ExternalInterface.call(this.js_on_publisher_ready, this.js_id, cameras, microphones);
}
/**
* notify the js an error occur.
*/
private function system_error(code:int, desc:String):void {
trace("system error, code=" + code + ", error=" + desc);
flash.external.ExternalInterface.call(this.js_on_publisher_error, this.js_id, code);
}
private function system_warn(code:int, desc:String):void {
trace("system warn, code=" + code + ", error=" + desc);
flash.external.ExternalInterface.call(this.js_on_publisher_warn, this.js_id, code);
}
// srs infos
private var srs_server:String = null;
private var srs_primary:String = null;
private var srs_authors:String = null;
private var srs_id:String = null;
private var srs_pid:String = null;
private var srs_server_ip:String = null;
private function update_context_items():void {
// for context menu
var customItems:Array = [new ContextMenuItem("SrsPlayer")];
if (srs_server != null) {
customItems.push(new ContextMenuItem("Server: " + srs_server));
}
if (srs_primary != null) {
customItems.push(new ContextMenuItem("Primary: " + srs_primary));
}
if (srs_authors != null) {
customItems.push(new ContextMenuItem("Authors: " + srs_authors));
}
if (srs_server_ip != null) {
customItems.push(new ContextMenuItem("SrsIp: " + srs_server_ip));
}
if (srs_pid != null) {
customItems.push(new ContextMenuItem("SrsPid: " + srs_pid));
}
if (srs_id != null) {
customItems.push(new ContextMenuItem("SrsId: " + srs_id));
}
contextMenu.customItems = customItems;
}
/**
* publish stream to server.
* @param url a string indicates the rtmp url to publish.
* @param _width, the player width.
* @param _height, the player height.
* @param vcodec an object contains the video codec info.
* @param acodec an object contains the audio codec info.
*/
private function js_call_publish(url:String, _width:int, _height:int, vcodec:Object, acodec:Object):void {
trace("start to publish to " + url + ", vcodec " + JSON.stringify(vcodec) + ", acodec " + JSON.stringify(acodec));
this.user_url = url;
this.user_w = _width;
this.user_h = _height;
this.user_vcodec = vcodec;
this.user_acodec = acodec;
this.js_call_stop();
// microphone and camera
var microphone:Microphone = null;
//microphone = Microphone.getEnhancedMicrophone(acodec.device_code);
if (!microphone) {
microphone = Microphone.getMicrophone(acodec.device_code);
}
if(microphone == null){
this.system_error(this.error_microphone_get, "failed to open microphone " + acodec.device_code + "(" + acodec.device_name + ")");
return;
}
// ignore muted, for flash will require user to access it.
// Remark: the name is the index!
var camera:Camera = Camera.getCamera(vcodec.device_code);
if(camera == null){
this.system_error(this.error_camera_get, "failed to open camera " + vcodec.device_code + "(" + vcodec.device_name + ")");
return;
}
// ignore muted, for flash will require user to access it.
// but we still warn user.
if(camera && camera.muted){
this.system_warn(this.error_camera_muted, "Access Denied, camera " + vcodec.device_code + "(" + vcodec.device_name + ") is muted");
}
this.media_camera = camera;
this.media_microphone = microphone;
this.media_conn = new NetConnection();
this.media_conn.client = {};
this.media_conn.client.onBWDone = function():void {};
this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
trace ("NetConnection: code=" + evt.info.code);
if (evt.info.hasOwnProperty("data") && evt.info.data) {
if (evt.info.data.hasOwnProperty("srs_server")) {
srs_server = evt.info.data.srs_server;
}
if (evt.info.data.hasOwnProperty("srs_primary")) {
srs_primary = evt.info.data.srs_primary;
}
if (evt.info.data.hasOwnProperty("srs_authors")) {
srs_authors = evt.info.data.srs_authors;
}
if (evt.info.data.hasOwnProperty("srs_id")) {
srs_id = evt.info.data.srs_id;
}
if (evt.info.data.hasOwnProperty("srs_pid")) {
srs_pid = evt.info.data.srs_pid;
}
if (evt.info.data.hasOwnProperty("srs_server_ip")) {
srs_server_ip = evt.info.data.srs_server_ip;
}
update_context_items();
}
if (evt.info.code == "NetConnection.Connect.Closed") {
js_call_stop();
system_error(error_connection_closed, "server closed the connection");
return;
}
if (evt.info.code == "NetConnection.Connect.Failed") {
js_call_stop();
system_error(error_connection_failed, "connect to server failed");
return;
}
// TODO: FIXME: failed event.
if (evt.info.code != "NetConnection.Connect.Success") {
return;
}
media_stream = new NetStream(media_conn);
media_stream.client = {};
media_stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
trace ("NetStream: code=" + evt.info.code);
// TODO: FIXME: failed event.
});
__build_video_codec(media_stream, camera, vcodec);
__build_audio_codec(media_stream, microphone, acodec);
if (media_microphone) {
media_stream.attachAudio(microphone);
}
if (media_camera) {
media_stream.attachCamera(camera);
}
var streamName:String = url.substr(url.lastIndexOf("/"));
media_stream.publish(streamName);
__show_local_camera(media_camera);
});
var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));
this.media_conn.connect(tcUrl);
}
/**
* function for js to call: to stop the stream. ignore if not publish.
*/
private function js_call_stop():void {
if (this.media_stream) {
this.media_stream.attachAudio(null);
this.media_stream.attachCamera(null);
this.media_stream.close();
this.media_stream = null;
}
if (this.media_conn) {
this.media_conn.close();
this.media_conn = null;
}
}
private function __build_audio_codec(stream:NetStream, m:Microphone, acodec:Object):void {
if (!m) {
return;
}
// if no microphone, donot set the params.
if(m == null){
return;
}
// use default values.
var microEncodeQuality:int = 8;
var microRate:int = 22; // 22 === 22050 Hz
trace("[Publish] audio encoding parameters: "
+ "audio(microphone) codec=" + acodec.codec + "encodeQuality=" + microEncodeQuality
+ ", rate=" + microRate + "(22050Hz)"
);
// The encoded speech quality when using the Speex codec. Possible values are from 0 to 10. The default value is 6. Higher numbers
// represent higher quality but require more bandwidth, as shown in the following table. The bit rate values that are listed represent
// net bit rates and do not include packetization overhead.
m.encodeQuality = microEncodeQuality;
// The rate at which the microphone is capturing sound, in kHz. Acceptable values are 5, 8, 11, 22, and 44. The default value is 8 kHz
// if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that
// your sound capture device supports, usually 11 kHz.
m.rate = microRate;
// see: http://www.adobe.com/cn/devnet/flashplayer/articles/acoustic-echo-cancellation.html
if (acodec.codec == "nellymoser") {
m.codec = SoundCodec.NELLYMOSER;
} else if (acodec.codec == "pcma") {
m.codec = SoundCodec.PCMA;
} else if (acodec.codec == "pcmu") {
m.codec = SoundCodec.PCMU;
} else {
m.codec = SoundCodec.SPEEX;
}
m.framesPerPacket = 1;
}
private function __build_video_codec(stream:NetStream, c:Camera, vcodec:Object):void {
if (!c) {
return;
}
if(vcodec.codec == "vp6"){
trace("use VP6, donot use H.264 publish encoding.");
return;
}
var x264profile:String = (vcodec.profile == "main") ? H264Profile.MAIN : H264Profile.BASELINE;
var x264level:String = vcodec.level;
var cameraFps:Number = Number(vcodec.fps);
var x264KeyFrameInterval:int = int(vcodec.gop * cameraFps);
var cameraWidth:int = String(vcodec.size).split("x")[0];
var cameraHeight:int = String(vcodec.size).split("x")[1];
var cameraBitrate:int = int(vcodec.bitrate);
// use default values.
var cameraQuality:int = 85;
trace("[Publish] video h.264(x264) encoding parameters: "
+ "profile=" + x264profile
+ ", level=" + x264level
+ ", keyFrameInterval(gop)=" + x264KeyFrameInterval
+ "; video(camera) width=" + cameraWidth
+ ", height=" + cameraHeight
+ ", fps=" + cameraFps
+ ", bitrate=" + cameraBitrate
+ ", quality=" + cameraQuality
);
var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
// we MUST set its values first, then set the NetStream.videoStreamSettings, or it will keep the origin values.
h264Settings.setProfileLevel(x264profile, x264level);
stream.videoStreamSettings = h264Settings;
// the setKeyFrameInterval/setMode/setQuality use the camera settings.
// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/VideoStreamSettings.html
// Note This feature will be supported in future releases of Flash Player and AIR, for now, Camera parameters are used.
//
//h264Settings.setKeyFrameInterval(4);
//h264Settings.setMode(800, 600, 15);
//h264Settings.setQuality(500, 0);
// set the camera and microphone.
// setKeyFrameInterval(keyFrameInterval:int):void
// keyFrameInterval:int A value that specifies which video frames are transmitted in full (as keyframes) instead of being
// interpolated by the video compression algorithm. A value of 1 means that every frame is a keyframe, a value of 3 means
// that every third frame is a keyframe, and so on. Acceptable values are 1 through 48.
c.setKeyFrameInterval(x264KeyFrameInterval);
// setMode(width:int, height:int, fps:Number, favorArea:Boolean = true):void
// width:int The requested capture width, in pixels. The default value is 160.
// height:int The requested capture height, in pixels. The default value is 120.
// fps:Number The requested rate at which the camera should capture data, in frames per second. The default value is 15.
c.setMode(cameraWidth, cameraHeight, cameraFps);
// setQuality(bandwidth:int, quality:int):void
// bandwidth:int Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second.
// To specify that the video can use as much bandwidth as needed to maintain the value of quality, pass 0 for bandwidth.
// The default value is 16384.
// quality:int An integer that specifies the required level of picture quality, as determined by the amount of compression
// being applied to each video frame. Acceptable values range from 1 (lowest quality, maximum compression) to 100
// (highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth,
// pass 0 for quality.
// winlin:
// bandwidth is in Bps not kbps.
// quality=1 is lowest quality, 100 is highest quality.
c.setQuality(cameraBitrate / 8.0 * 1000, cameraQuality);
}
private function __show_local_camera(c:Camera):void {
if (this.media_video) {
this.media_video.attachCamera(null);
this.removeChild(this.media_video);
this.media_video = null;
}
// show local camera
media_video = new Video();
media_video.attachCamera(c);
media_video.smoothing = true;
addChild(media_video);
// rescale the local camera.
var cw:Number = user_h * c.width / c.height;
if (cw > user_w) {
var ch:Number = user_w * c.height / c.width;
media_video.width = user_w;
media_video.height = ch;
} else {
media_video.width = cw;
media_video.height = user_h;
}
media_video.x = (user_w - media_video.width) / 2;
media_video.y = (user_h - media_video.height) / 2;
__draw_black_background(user_w, user_h);
// lowest layer, for mask to cover it.
setChildIndex(media_video, 0);
}
/**
* draw black background and draw the fullscreen mask.
*/
private function __draw_black_background(_width:int, _height:int):void {
// draw black bg.
this.graphics.beginFill(0x00, 1.0);
this.graphics.drawRect(0, 0, _width, _height);
this.graphics.endFill();
// draw the fs mask.
//this.control_fs_mask.graphics.beginFill(0xff0000, 0);
//this.control_fs_mask.graphics.drawRect(0, 0, _width, _height);
//this.control_fs_mask.graphics.endFill();
}
}
}

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="srs_reuse_conn.as" projectUUID="ccfd5c0a-9963-467a-8739-75ac79faaef5" version="10">
<compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="release" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
<excludedEntries>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
</excludedEntries>
</libraryPathEntry>
<libraryPathEntry kind="3" linkType="1" path="FlashCS5UI.swc" useDefaultLinkType="false"/>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="srs_reuse_conn.as"/>
</applications>
<modules/>
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>srs_reuse_conn</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
</projectDescription>

@ -1,3 +0,0 @@
#Sat Nov 22 18:40:22 CST 2014
eclipse.preferences.version=1
encoding/<project>=utf-8

@ -1,123 +0,0 @@
package
{
import fl.controls.Button;
import fl.controls.TextInput;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
[SWF(backgroundColor="0xEEEEEE",frameRate="30",width="1024",height="576")]
public class srs_reuse_conn extends Sprite
{
public function srs_reuse_conn()
{
if (stage) {
onAddedToStage(null);
} else {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
}
private function onAddedToStage(evt:Event):void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var txtUrl:TextInput = new TextInput();
var btnConn:Button = new Button();
var btnPlay:Button = new Button();
txtUrl.x = 10;
txtUrl.y = 10;
txtUrl.width = 400;
txtUrl.text = "rtmp://dev/live/livestream";
addChild(txtUrl);
btnConn.label = "Connect";
btnConn.x = txtUrl.x + txtUrl.width + 10;
btnConn.y = txtUrl.y;
btnConn.width = 100;
addChild(btnConn);
btnPlay.label = "Play";
btnPlay.x = btnConn.x + btnConn.width + 10;
btnPlay.y = btnConn.y;
btnPlay.width = 100;
addChild(btnPlay);
var video:Video = new Video();
video.x = txtUrl.x;
video.y = txtUrl.y + txtUrl.height + 10;
addChild(video);
var conn:NetConnection = null;
var stream:NetStream = null;
var tcUrl:Function = function():String {
var url:String = txtUrl.text;
return url.substr(0, url.lastIndexOf("/"));
}
var streamName:Function = function():String {
var url:String = txtUrl.text;
return url.substr(tcUrl().length + 1);
}
var closeConnection:Function = function():void {
if (stream) {
stream.close();
stream = null;
}
if (conn) {
conn.close();
conn = null;
}
btnConn.label = "Connect";
btnPlay.visible = false;
};
btnPlay.visible = false;
btnConn.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
if (btnConn.label == "Connect") {
conn = new NetConnection();
conn.client = {
onBWDone: function():void{}
};
conn.addEventListener(NetStatusEvent.NET_STATUS, function(ne:NetStatusEvent):void {
if (ne.info.code == "NetConnection.Connect.Success") {
btnPlay.visible = true;
} else if (ne.info.code == "NetConnection.Connect.Closed") {
closeConnection();
}
trace(ne.info.code);
});
conn.connect(tcUrl());
btnConn.label = "Close";
} else {
closeConnection();
}
});
btnPlay.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
if (stream) {
stream.close();
stream = null;
}
stream = new NetStream(conn);
stream.client = {
onMetaData: function(metadata:Object):void {
video.width = metadata.width;
video.height = metadata.height;
}
};
video.attachNetStream(stream);
stream.play(streamName());
});
}
}
}

@ -9,6 +9,6 @@
#define VERSION_MAJOR 5
#define VERSION_MINOR 0
#define VERSION_REVISION 21
#define VERSION_REVISION 22
#endif

Loading…
Cancel
Save