mirror of https://github.com/ossrs/srs.git
Eliminate unused *.as files for Adobe Flash. v5.0.22
parent
0b87950073
commit
7c9f88be0b
@ -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>
|
Binary file not shown.
@ -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,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
|
Binary file not shown.
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
|
Binary file not shown.
@ -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
|
Binary file not shown.
Binary file not shown.
@ -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());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue