mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
210 lines
No EOL
6.7 KiB
ActionScript
210 lines
No EOL
6.7 KiB
ActionScript
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);
|
|
}
|
|
}
|
|
} |