winlin

extract iplayer for srs-player.

@@ -12,6 +12,9 @@ @@ -12,6 +12,9 @@
12 margin-top: -20px; 12 margin-top: -20px;
13 padding-top: 3px; 13 padding-top: 3px;
14 } 14 }
  15 + #main_modal {
  16 + margin-top: -60px;
  17 + }
15 .div_play_time { 18 .div_play_time {
16 margin-top: 10px; 19 margin-top: 10px;
17 } 20 }
@@ -378,15 +381,13 @@ @@ -378,15 +381,13 @@
378 </div> 381 </div>
379 </div> 382 </div>
380 <div style="margin-top:-12px;"> 383 <div style="margin-top:-12px;">
  384 + <span id="debug_info"></span>
381 URL: <a href="#" id="player_url"></a> 385 URL: <a href="#" id="player_url"></a>
382 <div class="input-prepend div_play_time" title="当前时间:年-月-日 时:分:秒"> 386 <div class="input-prepend div_play_time" title="当前时间:年-月-日 时:分:秒">
383 <span class="add-on">@N</span> 387 <span class="add-on">@N</span>
384 <input class="span2" style="width:135px" id="player_clock" type="text" placeholder="年-月-日 时:分:秒"> 388 <input class="span2" style="width:135px" id="player_clock" type="text" placeholder="年-月-日 时:分:秒">
385 </div> 389 </div>
386 </div> 390 </div>
387 - <div>  
388 - <span id="debug_info"></span>  
389 - </div>  
390 </div> 391 </div>
391 </div> 392 </div>
392 <footer> 393 <footer>
@@ -496,6 +497,7 @@ @@ -496,6 +497,7 @@
496 } 497 }
497 498
498 $("#div_container").remove(); 499 $("#div_container").remove();
  500 + $("#debug_info").text("");
499 501
500 var div_container = $("<div/>"); 502 var div_container = $("<div/>");
501 $(div_container).attr("id", "div_container"); 503 $(div_container).attr("id", "div_container");
@@ -513,7 +515,7 @@ @@ -513,7 +515,7 @@
513 srs_player.on_player_metadata = function(metadata) { 515 srs_player.on_player_metadata = function(metadata) {
514 $("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")"); 516 $("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")");
515 if (metadata.ip && metadata.pid && metadata.cid) { 517 if (metadata.ip && metadata.pid && metadata.cid) {
516 - $("#debug_info").text("DEBUG: " + metadata.ip + ' grep -in "\\[' + metadata.pid + '\\]\\[' + metadata.cid + '\\]"'); 518 + $("#debug_info").text("ID:" + metadata.ip + '/' + metadata.pid + '/' + metadata.cid + '');
517 } 519 }
518 select_dar("#btn_dar_original", 0, 0); 520 select_dar("#btn_dar_original", 0, 0);
519 select_fs_size("#btn_fs_size_screen_100", "screen", 100); 521 select_fs_size("#btn_fs_size_screen_100", "screen", 100);
@@ -40,3 +40,4 @@ @@ -40,3 +40,4 @@
40 </actionScriptProperties> 40 </actionScriptProperties>
41 41
42 42
  43 +
  1 +package
  2 +{
  3 + import flash.display.Sprite;
  4 + import flash.display.StageAlign;
  5 + import flash.display.StageDisplayState;
  6 + import flash.display.StageScaleMode;
  7 + import flash.events.Event;
  8 + import flash.events.FullScreenEvent;
  9 + import flash.events.MouseEvent;
  10 + import flash.events.NetStatusEvent;
  11 + import flash.events.TimerEvent;
  12 + import flash.external.ExternalInterface;
  13 + import flash.media.SoundTransform;
  14 + import flash.media.Video;
  15 + import flash.net.NetConnection;
  16 + import flash.net.NetStream;
  17 + import flash.system.Security;
  18 + import flash.ui.ContextMenu;
  19 + import flash.ui.ContextMenuItem;
  20 + import flash.utils.Timer;
  21 + import flash.utils.getTimer;
  22 + import flash.utils.setTimeout;
  23 +
  24 + import flashx.textLayout.formats.Float;
  25 +
  26 + /**
  27 + * common player to play rtmp/flv stream,
  28 + * use system NetStream.
  29 + */
  30 + public class CommonPlayer implements IPlayer
  31 + {
  32 + private var js_id:String = null;
  33 +
  34 + // play param url.
  35 + private var user_url:String = null;
  36 +
  37 + private var media_stream:NetStream = null;
  38 + private var media_conn:NetConnection = null;
  39 +
  40 + private var owner:srs_player = null;
  41 +
  42 + public function CommonPlayer(o:srs_player) {
  43 + owner = o;
  44 + }
  45 +
  46 + public function init(flashvars:Object):void {
  47 + this.js_id = flashvars.id;
  48 + }
  49 +
  50 + public function stream():NetStream {
  51 + return this.media_stream;
  52 + }
  53 +
  54 + public function play(url:String):void {
  55 + var streamName:String;
  56 + this.user_url = url;
  57 +
  58 + this.media_conn = new NetConnection();
  59 + this.media_conn.client = {};
  60 + this.media_conn.client.onBWDone = function():void {};
  61 + this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
  62 + log("NetConnection: code=" + evt.info.code);
  63 +
  64 + if (evt.info.hasOwnProperty("data") && evt.info.data) {
  65 + owner.on_player_metadata(evt.info.data);
  66 + }
  67 +
  68 + // reject by server, maybe redirect.
  69 + if (evt.info.code == "NetConnection.Connect.Rejected") {
  70 + // RTMP 302 redirect.
  71 + if (evt.info.hasOwnProperty("ex") && evt.info.ex.code == 302) {
  72 + streamName = url.substr(url.lastIndexOf("/") + 1);
  73 + url = evt.info.ex.redirect + "/" + streamName;
  74 + log("Async RTMP 302 Redirect to: " + url);
  75 +
  76 + // notify server.
  77 + media_conn.call("Redirected", null, evt.info.ex.redirect);
  78 +
  79 + // do 302.
  80 + owner.on_player_302(url);
  81 + return;
  82 + }
  83 + }
  84 +
  85 + // TODO: FIXME: failed event.
  86 + if (evt.info.code != "NetConnection.Connect.Success") {
  87 + return;
  88 + }
  89 +
  90 + media_stream = new NetStream(media_conn);
  91 + media_stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
  92 + log("NetStream: code=" + evt.info.code);
  93 +
  94 + if (evt.info.code == "NetStream.Video.DimensionChange") {
  95 + owner.on_player_dimension_change();
  96 + } else if (evt.info.code == "NetStream.Buffer.Empty") {
  97 + owner.on_player_buffer_empty();
  98 + } else if (evt.info.code == "NetStream.Buffer.Full") {
  99 + owner.on_player_buffer_full();
  100 + }
  101 +
  102 + // TODO: FIXME: failed event.
  103 + });
  104 +
  105 + // setup stream before play.
  106 + owner.on_player_before_play();
  107 +
  108 + if (url.indexOf("http") == 0) {
  109 + media_stream.play(url);
  110 + } else {
  111 + streamName = url.substr(url.lastIndexOf("/") + 1);
  112 + media_stream.play(streamName);
  113 + }
  114 +
  115 + owner.on_player_play();
  116 + });
  117 +
  118 + if (url.indexOf("http") == 0) {
  119 + this.media_conn.connect(null);
  120 + } else {
  121 + var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));
  122 + this.media_conn.connect(tcUrl);
  123 + }
  124 + }
  125 +
  126 + public function close():void {
  127 + if (this.media_stream) {
  128 + this.media_stream.close();
  129 + this.media_stream = null;
  130 + }
  131 + if (this.media_conn) {
  132 + this.media_conn.close();
  133 + this.media_conn = null;
  134 + }
  135 + }
  136 +
  137 + private function log(msg:String):void {
  138 + Utility.log(js_id, msg);
  139 + }
  140 + }
  141 +}
  1 +package
  2 +{
  3 + import flash.net.NetStream;
  4 +
  5 + /**
  6 + * the player interface.
  7 + */
  8 + public interface IPlayer
  9 + {
  10 + /**
  11 + * initialize the player by flashvars for config.
  12 + * @param flashvars the config.
  13 + */
  14 + function init(flashvars:Object):void;
  15 +
  16 + /**
  17 + * get the NetStream to play the stream.
  18 + * @return the underlayer stream object.
  19 + */
  20 + function stream():NetStream;
  21 +
  22 + /**
  23 + * connect and play url.
  24 + * @param url the stream url to play.
  25 + */
  26 + function play(url:String):void;
  27 +
  28 + /**
  29 + * close the player.
  30 + */
  31 + function close():void;
  32 + }
  33 +}
  1 +package
  2 +{
  3 + import flash.display.Sprite;
  4 + import flash.display.StageAlign;
  5 + import flash.display.StageDisplayState;
  6 + import flash.display.StageScaleMode;
  7 + import flash.events.Event;
  8 + import flash.events.FullScreenEvent;
  9 + import flash.events.MouseEvent;
  10 + import flash.events.NetStatusEvent;
  11 + import flash.events.TimerEvent;
  12 + import flash.external.ExternalInterface;
  13 + import flash.media.SoundTransform;
  14 + import flash.media.Video;
  15 + import flash.net.NetConnection;
  16 + import flash.net.NetStream;
  17 + import flash.system.Security;
  18 + import flash.ui.ContextMenu;
  19 + import flash.ui.ContextMenuItem;
  20 + import flash.utils.Timer;
  21 + import flash.utils.getTimer;
  22 + import flash.utils.setTimeout;
  23 +
  24 + import flashx.textLayout.formats.Float;
  25 +
  26 + /**
  27 + * the m3u8 player.
  28 + */
  29 + public class M3u8Player implements IPlayer
  30 + {
  31 + private var js_id:String = null;
  32 +
  33 + // play param url.
  34 + private var user_url:String = null;
  35 +
  36 + private var media_stream:NetStream = null;
  37 + private var media_conn:NetConnection = null;
  38 +
  39 + private var owner:srs_player = null;
  40 +
  41 + public function M3u8Player(o:srs_player) {
  42 + owner = o;
  43 + }
  44 +
  45 + public function init(flashvars:Object):void {
  46 + this.js_id = flashvars.id;
  47 + }
  48 +
  49 + public function stream():NetStream {
  50 + return this.media_stream;
  51 + }
  52 +
  53 + public function play(url:String):void {
  54 + this.user_url = url;
  55 + }
  56 +
  57 + public function close():void {
  58 + if (this.media_stream) {
  59 + this.media_stream.close();
  60 + this.media_stream = null;
  61 + }
  62 + if (this.media_conn) {
  63 + this.media_conn.close();
  64 + this.media_conn = null;
  65 + }
  66 + }
  67 +
  68 + private function log(msg:String):void {
  69 + Utility.log(js_id, msg);
  70 + }
  71 + }
  72 +}
  1 +package
  2 +{
  3 + import flash.external.ExternalInterface;
  4 + import flash.utils.setTimeout;
  5 +
  6 + /**
  7 + * the utility functions.
  8 + */
  9 + public class Utility
  10 + {
  11 + /**
  12 + * initialize the player by flashvars for config.
  13 + * @param flashvars the config.
  14 + */
  15 + public static function stringEndswith(s:String, f:String):Boolean {
  16 + return s && f && s.indexOf(f) == s.length - f.length;
  17 + }
  18 +
  19 + /**
  20 + * write log to trace and console.log.
  21 + * @param msg the log message.
  22 + */
  23 + public static function log(js_id:String, msg:String):void {
  24 + msg = "[" + new Date() +"][srs-player][" + js_id + "] " + msg;
  25 +
  26 + trace(msg);
  27 +
  28 + if (!flash.external.ExternalInterface.available) {
  29 + flash.utils.setTimeout(log, 300, msg);
  30 + return;
  31 + }
  32 +
  33 + ExternalInterface.call("console.log", msg);
  34 + }
  35 + }
  36 +}
@@ -33,12 +33,13 @@ package @@ -33,12 +33,13 @@ package
33 private var js_on_player_timer:String = null; 33 private var js_on_player_timer:String = null;
34 private var js_on_player_empty:String = null; 34 private var js_on_player_empty:String = null;
35 private var js_on_player_full:String = null; 35 private var js_on_player_full:String = null;
36 -  
37 - // play param url.  
38 - private var user_url:String = null; 36 +
39 // play param, user set width and height 37 // play param, user set width and height
40 private var user_w:int = 0; 38 private var user_w:int = 0;
41 private var user_h:int = 0; 39 private var user_h:int = 0;
  40 + private var user_buffer_time:Number = 0;
  41 + private var user_max_buffer_time:Number = 0;
  42 + private var user_volume:Number = 0;
42 // user set dar den:num 43 // user set dar den:num
43 private var user_dar_den:int = 0; 44 private var user_dar_den:int = 0;
44 private var user_dar_num:int = 0; 45 private var user_dar_num:int = 0;
@@ -47,8 +48,6 @@ package @@ -47,8 +48,6 @@ package
47 private var user_fs_percent:int = 0; 48 private var user_fs_percent:int = 0;
48 49
49 // media specified. 50 // media specified.
50 - private var media_conn:NetConnection = null;  
51 - private var media_stream:NetStream = null;  
52 private var media_video:Video = null; 51 private var media_video:Video = null;
53 private var media_metadata:Object = {}; 52 private var media_metadata:Object = {};
54 private var media_timer:Timer = new Timer(300); 53 private var media_timer:Timer = new Timer(300);
@@ -57,6 +56,11 @@ package @@ -57,6 +56,11 @@ package
57 // flash donot allow js to set to fullscreen, 56 // flash donot allow js to set to fullscreen,
58 // only allow user click to enter fullscreen. 57 // only allow user click to enter fullscreen.
59 private var control_fs_mask:Sprite = new Sprite(); 58 private var control_fs_mask:Sprite = new Sprite();
  59 +
  60 + // the common player to play stream.
  61 + private var player:IPlayer = null;
  62 + // the flashvars config.
  63 + private var config:Object = null;
60 64
61 public function srs_player() 65 public function srs_player()
62 { 66 {
@@ -93,7 +97,8 @@ package @@ -93,7 +97,8 @@ package
93 if (!flashvars.hasOwnProperty("id")) { 97 if (!flashvars.hasOwnProperty("id")) {
94 throw new Error("must specifies the id"); 98 throw new Error("must specifies the id");
95 } 99 }
96 - 100 +
  101 + this.config = flashvars;
97 this.js_id = flashvars.id; 102 this.js_id = flashvars.id;
98 this.js_on_player_ready = flashvars.on_player_ready; 103 this.js_on_player_ready = flashvars.on_player_ready;
99 this.js_on_player_metadata = flashvars.on_player_metadata; 104 this.js_on_player_metadata = flashvars.on_player_metadata;
@@ -134,7 +139,11 @@ package @@ -134,7 +139,11 @@ package
134 * system callack event, timer to do some regular tasks. 139 * system callack event, timer to do some regular tasks.
135 */ 140 */
136 private function system_on_timer(evt:TimerEvent):void { 141 private function system_on_timer(evt:TimerEvent):void {
137 - var ms:NetStream = this.media_stream; 142 + if (!player) {
  143 + return;
  144 + }
  145 +
  146 + var ms:NetStream = player.stream();
138 147
139 if (!ms) { 148 if (!ms) {
140 //log("stream is null, ignore timer event."); 149 //log("stream is null, ignore timer event.");
@@ -249,8 +258,8 @@ package @@ -249,8 +258,8 @@ package
249 * function for js to call: to pause the stream. ignore if not play. 258 * function for js to call: to pause the stream. ignore if not play.
250 */ 259 */
251 private function js_call_pause():void { 260 private function js_call_pause():void {
252 - if (this.media_stream) {  
253 - this.media_stream.pause(); 261 + if (player && player.stream()) {
  262 + player.stream().pause();
254 log("user pause play"); 263 log("user pause play");
255 } 264 }
256 } 265 }
@@ -259,8 +268,8 @@ package @@ -259,8 +268,8 @@ package
259 * function for js to call: to resume the stream. ignore if not play. 268 * function for js to call: to resume the stream. ignore if not play.
260 */ 269 */
261 private function js_call_resume():void { 270 private function js_call_resume():void {
262 - if (this.media_stream) {  
263 - this.media_stream.resume(); 271 + if (player && player.stream()) {
  272 + player.stream().resume();
264 log("user resume play"); 273 log("user resume play");
265 } 274 }
266 } 275 }
@@ -301,8 +310,8 @@ package @@ -301,8 +310,8 @@ package
301 * @buffer_time the buffer time in seconds. 310 * @buffer_time the buffer time in seconds.
302 */ 311 */
303 private function js_call_set_bt(buffer_time:Number):void { 312 private function js_call_set_bt(buffer_time:Number):void {
304 - if (this.media_stream) {  
305 - this.media_stream.bufferTime = buffer_time; 313 + if (player && player.stream()) {
  314 + player.stream().bufferTime = buffer_time;
306 log("user set bufferTime to " + buffer_time.toFixed(2) + "s"); 315 log("user set bufferTime to " + buffer_time.toFixed(2) + "s");
307 } 316 }
308 } 317 }
@@ -313,8 +322,8 @@ package @@ -313,8 +322,8 @@ package
313 * @remark this is the key feature for realtime communication by flash. 322 * @remark this is the key feature for realtime communication by flash.
314 */ 323 */
315 private function js_call_set_mbt(max_buffer_time:Number):void { 324 private function js_call_set_mbt(max_buffer_time:Number):void {
316 - if (this.media_stream) {  
317 - this.media_stream.bufferTimeMax = max_buffer_time; 325 + if (player && player.stream()) {
  326 + player.stream().bufferTimeMax = max_buffer_time;
318 log("user set bufferTimeMax to " + max_buffer_time.toFixed(2) + "s"); 327 log("user set bufferTimeMax to " + max_buffer_time.toFixed(2) + "s");
319 } 328 }
320 } 329 }
@@ -327,13 +336,10 @@ package @@ -327,13 +336,10 @@ package
327 this.removeChild(this.media_video); 336 this.removeChild(this.media_video);
328 this.media_video = null; 337 this.media_video = null;
329 } 338 }
330 - if (this.media_stream) {  
331 - this.media_stream.close();  
332 - this.media_stream = null;  
333 - }  
334 - if (this.media_conn) {  
335 - this.media_conn.close();  
336 - this.media_conn = null; 339 +
  340 + if (player) {
  341 + player.close();
  342 + player = null;
337 } 343 }
338 log("player stopped"); 344 log("player stopped");
339 } 345 }
@@ -403,97 +409,83 @@ package @@ -403,97 +409,83 @@ package
403 * @param volume, the volume, 0 is mute, 1 is 100%, 2 is 200%. 409 * @param volume, the volume, 0 is mute, 1 is 100%, 2 is 200%.
404 */ 410 */
405 private function js_call_play(url:String, _width:int, _height:int, buffer_time:Number, max_buffer_time:Number, volume:Number):void { 411 private function js_call_play(url:String, _width:int, _height:int, buffer_time:Number, max_buffer_time:Number, volume:Number):void {
406 - this.user_url = url;  
407 this.user_w = _width; 412 this.user_w = _width;
408 this.user_h = _height; 413 this.user_h = _height;
409 - log("start to play url: " + this.user_url + ", w=" + this.user_w + ", h=" + this.user_h 414 + this.user_buffer_time = buffer_time;
  415 + this.user_max_buffer_time = max_buffer_time;
  416 + this.user_volume = volume;
  417 + log("start to play url: " + url + ", w=" + this.user_w + ", h=" + this.user_h
410 + ", buffer=" + buffer_time.toFixed(2) + "s, max_buffer=" + max_buffer_time.toFixed(2) + "s, volume=" + volume.toFixed(2) 418 + ", buffer=" + buffer_time.toFixed(2) + "s, max_buffer=" + max_buffer_time.toFixed(2) + "s, volume=" + volume.toFixed(2)
411 ); 419 );
412 420
413 js_call_stop(); 421 js_call_stop();
414 -  
415 - this.media_conn = new NetConnection();  
416 - this.media_conn.client = {};  
417 - this.media_conn.client.onBWDone = function():void {};  
418 - this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {  
419 - log("NetConnection: code=" + evt.info.code);  
420 -  
421 - if (evt.info.hasOwnProperty("data") && evt.info.data) {  
422 - on_debug_info(evt.info.data);  
423 - update_context_items();  
424 - }  
425 -  
426 - // reject by server, maybe redirect.  
427 - if (evt.info.code == "NetConnection.Connect.Rejected") {  
428 - // RTMP 302 redirect.  
429 - if (evt.info.hasOwnProperty("ex") && evt.info.ex.code == 302) {  
430 - var streamName:String = url.substr(url.lastIndexOf("/") + 1);  
431 - url = evt.info.ex.redirect + "/" + streamName;  
432 - log("Async RTMP 302 Redirect to: " + url);  
433 -  
434 - // notify server.  
435 - media_conn.call("Redirected", null, evt.info.ex.redirect);  
436 -  
437 - // do 302.  
438 - setTimeout(function(){  
439 - log("Async RTMP 302 Redirected.");  
440 - js_call_play(url, _width, _height, buffer_time, max_buffer_time, volume);  
441 - }, 1000);  
442 - return;  
443 - }  
444 - }  
445 -  
446 - // TODO: FIXME: failed event.  
447 - if (evt.info.code != "NetConnection.Connect.Success") {  
448 - return;  
449 - }  
450 -  
451 - media_stream = new NetStream(media_conn);  
452 - media_stream.soundTransform = new SoundTransform(volume);  
453 - media_stream.bufferTime = buffer_time;  
454 - media_stream.bufferTimeMax = max_buffer_time;  
455 - media_stream.client = {};  
456 - media_stream.client.onMetaData = system_on_metadata;  
457 - media_stream.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {  
458 - log("NetStream: code=" + evt.info.code);  
459 -  
460 - if (evt.info.code == "NetStream.Video.DimensionChange") {  
461 - system_on_metadata(media_metadata);  
462 - } else if (evt.info.code == "NetStream.Buffer.Empty") {  
463 - system_on_buffer_empty();  
464 - } else if (evt.info.code == "NetStream.Buffer.Full") {  
465 - system_on_buffer_full();  
466 - }  
467 -  
468 - // TODO: FIXME: failed event.  
469 - });  
470 -  
471 - if (url.indexOf("http") == 0) {  
472 - media_stream.play(url);  
473 - } else {  
474 - var streamName:String = url.substr(url.lastIndexOf("/") + 1);  
475 - media_stream.play(streamName);  
476 - }  
477 -  
478 - media_video = new Video();  
479 - media_video.width = _width;  
480 - media_video.height = _height;  
481 - media_video.attachNetStream(media_stream);  
482 - media_video.smoothing = true;  
483 - addChild(media_video);  
484 -  
485 - __draw_black_background(_width, _height);  
486 -  
487 - // lowest layer, for mask to cover it.  
488 - setChildIndex(media_video, 0);  
489 - });  
490 -  
491 - if (url.indexOf("http") == 0) {  
492 - this.media_conn.connect(null); 422 +
  423 + // create player.
  424 + if (Utility.stringEndswith(url, ".m3u8")) {
  425 + player = new M3u8Player(this);
  426 + log("create M3U8 player.");
493 } else { 427 } else {
494 - var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));  
495 - this.media_conn.connect(tcUrl); 428 + player = new CommonPlayer(this);
  429 + log("create Common player.");
  430 + }
  431 +
  432 + // init player by config.
  433 + player.init(config);
  434 +
  435 + // play the url.
  436 + player.play(url);
  437 + }
  438 + public function on_player_before_play():void {
  439 + if (!player) {
  440 + return;
496 } 441 }
  442 +
  443 + var ms:NetStream = player.stream();
  444 + if (!ms) {
  445 + return;
  446 + }
  447 +
  448 + ms.soundTransform = new SoundTransform(user_volume);
  449 + ms.bufferTime = user_buffer_time;
  450 + ms.bufferTimeMax = user_max_buffer_time;
  451 + ms.client = {};
  452 + ms.client.onMetaData = system_on_metadata;
  453 + }
  454 + public function on_player_play():void {
  455 + if (!player) {
  456 + return;
  457 + }
  458 +
  459 + media_video = new Video();
  460 + media_video.width = user_w;
  461 + media_video.height = user_h;
  462 + media_video.attachNetStream(player.stream());
  463 + media_video.smoothing = true;
  464 + addChild(media_video);
  465 +
  466 + __draw_black_background(user_w, user_h);
  467 +
  468 + // lowest layer, for mask to cover it.
  469 + setChildIndex(media_video, 0);
  470 + }
  471 + public function on_player_metadata(data:Object):void {
  472 + on_debug_info(data);
  473 + update_context_items();
  474 + }
  475 + public function on_player_302(url:String):void {
  476 + setTimeout(function():void{
  477 + log("Async RTMP 302 Redirected.");
  478 + js_call_play(url, user_w, user_h, user_buffer_time, user_max_buffer_time, user_volume);
  479 + }, 1000);
  480 + }
  481 + public function on_player_dimension_change():void {
  482 + system_on_metadata(media_metadata);
  483 + }
  484 + public function on_player_buffer_empty():void {
  485 + system_on_buffer_empty();
  486 + }
  487 + public function on_player_buffer_full():void {
  488 + system_on_buffer_full();
497 } 489 }
498 490
499 /** 491 /**
@@ -650,16 +642,7 @@ package @@ -650,16 +642,7 @@ package
650 } 642 }
651 643
652 private function log(msg:String):void { 644 private function log(msg:String):void {
653 - msg = "[" + new Date() +"][srs-player][" + js_id + "] " + msg;  
654 -  
655 - trace(msg);  
656 -  
657 - if (!flash.external.ExternalInterface.available) {  
658 - flash.utils.setTimeout(log, 300, msg);  
659 - return;  
660 - }  
661 -  
662 - ExternalInterface.call("console.log", msg); 645 + Utility.log(js_id, msg);
663 } 646 }
664 } 647 }
665 } 648 }