正在显示
5 个修改的文件
包含
224 行增加
和
87 行删除
| @@ -30,6 +30,32 @@ function SrsPlayer(container, width, height, private_object) { | @@ -30,6 +30,32 @@ function SrsPlayer(container, width, height, private_object) { | ||
| 30 | this.meatadata = {}; // for on_player_metadata | 30 | this.meatadata = {}; // for on_player_metadata |
| 31 | this.time = 0; // current stream time. | 31 | this.time = 0; // current stream time. |
| 32 | this.buffer_length = 0; // current stream buffer length. | 32 | this.buffer_length = 0; // current stream buffer length. |
| 33 | + this.kbps = 0; // current stream bitrate(video+audio) in kbps. | ||
| 34 | + this.fps = 0; // current stream video fps. | ||
| 35 | + this.rtime = 0; // flash relative time in ms. | ||
| 36 | + | ||
| 37 | + this.__fluency = { | ||
| 38 | + total_empty_count: 0, | ||
| 39 | + total_empty_time: 0, | ||
| 40 | + current_empty_time: 0 | ||
| 41 | + }; | ||
| 42 | + this.__fluency.on_stream_empty = function(time) { | ||
| 43 | + this.total_empty_count++; | ||
| 44 | + this.current_empty_time = time; | ||
| 45 | + }; | ||
| 46 | + this.__fluency.on_stream_full = function(time) { | ||
| 47 | + if (this.current_empty_time > 0) { | ||
| 48 | + this.total_empty_time += time - this.current_empty_time; | ||
| 49 | + this.current_empty_time = 0; | ||
| 50 | + } | ||
| 51 | + }; | ||
| 52 | + this.__fluency.calc = function(time) { | ||
| 53 | + var den = this.total_empty_count * 4 + this.total_empty_time * 2 + time; | ||
| 54 | + if (den > 0) { | ||
| 55 | + return time * 100 / den; | ||
| 56 | + } | ||
| 57 | + return 0; | ||
| 58 | + }; | ||
| 33 | } | 59 | } |
| 34 | /** | 60 | /** |
| 35 | * user can set some callback, then start the player. | 61 | * user can set some callback, then start the player. |
| @@ -49,6 +75,8 @@ SrsPlayer.prototype.start = function(url) { | @@ -49,6 +75,8 @@ SrsPlayer.prototype.start = function(url) { | ||
| 49 | flashvars.on_player_ready = "__srs_on_player_ready"; | 75 | flashvars.on_player_ready = "__srs_on_player_ready"; |
| 50 | flashvars.on_player_metadata = "__srs_on_player_metadata"; | 76 | flashvars.on_player_metadata = "__srs_on_player_metadata"; |
| 51 | flashvars.on_player_timer = "__srs_on_player_timer"; | 77 | flashvars.on_player_timer = "__srs_on_player_timer"; |
| 78 | + flashvars.on_player_empty = "__srs_on_player_empty"; | ||
| 79 | + flashvars.on_player_full = "__srs_on_player_full"; | ||
| 52 | 80 | ||
| 53 | var params = {}; | 81 | var params = {}; |
| 54 | params.wmode = "opaque"; | 82 | params.wmode = "opaque"; |
| @@ -113,6 +141,18 @@ SrsPlayer.prototype.resume = function() { | @@ -113,6 +141,18 @@ SrsPlayer.prototype.resume = function() { | ||
| 113 | this.callbackObj.ref.__resume(); | 141 | this.callbackObj.ref.__resume(); |
| 114 | } | 142 | } |
| 115 | /** | 143 | /** |
| 144 | + * get the stream fluency, where 100 is 100%. | ||
| 145 | + */ | ||
| 146 | +SrsPlayer.prototype.fluency = function() { | ||
| 147 | + return this.__fluency.calc(this.rtime); | ||
| 148 | +} | ||
| 149 | +/** | ||
| 150 | + * get the stream empty count. | ||
| 151 | + */ | ||
| 152 | +SrsPlayer.prototype.empty_count = function() { | ||
| 153 | + return this.__fluency.total_empty_count; | ||
| 154 | +} | ||
| 155 | +/** | ||
| 116 | * to set the DAR, for example, DAR=16:9 where num=16,den=9. | 156 | * to set the DAR, for example, DAR=16:9 where num=16,den=9. |
| 117 | * @param num, for example, 16. | 157 | * @param num, for example, 16. |
| 118 | * use metadata width if 0. | 158 | * use metadata width if 0. |
| @@ -148,7 +188,13 @@ SrsPlayer.prototype.on_player_ready = function() { | @@ -148,7 +188,13 @@ SrsPlayer.prototype.on_player_ready = function() { | ||
| 148 | SrsPlayer.prototype.on_player_metadata = function(metadata) { | 188 | SrsPlayer.prototype.on_player_metadata = function(metadata) { |
| 149 | // ignore. | 189 | // ignore. |
| 150 | } | 190 | } |
| 151 | -SrsPlayer.prototype.on_player_timer = function(time, buffer_length) { | 191 | +SrsPlayer.prototype.on_player_timer = function(time, buffer_length, kbps, fps, rtime) { |
| 192 | + // ignore. | ||
| 193 | +} | ||
| 194 | +SrsPlayer.prototype.on_player_empty = function(time) { | ||
| 195 | + // ignore. | ||
| 196 | +} | ||
| 197 | +SrsPlayer.prototype.on_player_full = function(time) { | ||
| 152 | // ignore. | 198 | // ignore. |
| 153 | } | 199 | } |
| 154 | function __srs_find_player(id) { | 200 | function __srs_find_player(id) { |
| @@ -177,7 +223,7 @@ function __srs_on_player_metadata(id, metadata) { | @@ -177,7 +223,7 @@ function __srs_on_player_metadata(id, metadata) { | ||
| 177 | 223 | ||
| 178 | player.on_player_metadata(metadata); | 224 | player.on_player_metadata(metadata); |
| 179 | } | 225 | } |
| 180 | -function __srs_on_player_timer(id, time, buffer_length) { | 226 | +function __srs_on_player_timer(id, time, buffer_length, kbps, fps, rtime) { |
| 181 | var player = __srs_find_player(id); | 227 | var player = __srs_find_player(id); |
| 182 | 228 | ||
| 183 | buffer_length = Math.max(0, buffer_length); | 229 | buffer_length = Math.max(0, buffer_length); |
| @@ -189,6 +235,19 @@ function __srs_on_player_timer(id, time, buffer_length) { | @@ -189,6 +235,19 @@ function __srs_on_player_timer(id, time, buffer_length) { | ||
| 189 | // so set the data before invoke it. | 235 | // so set the data before invoke it. |
| 190 | player.time = time; | 236 | player.time = time; |
| 191 | player.buffer_length = buffer_length; | 237 | player.buffer_length = buffer_length; |
| 192 | - | ||
| 193 | - player.on_player_timer(time, buffer_length); | 238 | + player.kbps = kbps; |
| 239 | + player.fps = fps; | ||
| 240 | + player.rtime = rtime; | ||
| 241 | + | ||
| 242 | + player.on_player_timer(time, buffer_length, kbps, fps, rtime); | ||
| 243 | +} | ||
| 244 | +function __srs_on_player_empty(id, time) { | ||
| 245 | + var player = __srs_find_player(id); | ||
| 246 | + player.__fluency.on_stream_empty(time); | ||
| 247 | + player.on_player_empty(time); | ||
| 248 | +} | ||
| 249 | +function __srs_on_player_full(id, time) { | ||
| 250 | + var player = __srs_find_player(id); | ||
| 251 | + player.__fluency.on_stream_full(time); | ||
| 252 | + player.on_player_full(time); | ||
| 194 | } | 253 | } |
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | * depends: jquery1.10 | 5 | * depends: jquery1.10 |
| 6 | * https://code.csdn.net/snippets/147103 | 6 | * https://code.csdn.net/snippets/147103 |
| 7 | * @see: http://blog.csdn.net/win_lin/article/details/17994347 | 7 | * @see: http://blog.csdn.net/win_lin/article/details/17994347 |
| 8 | - * v 1.0.10 | 8 | + * v 1.0.11 |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| @@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
| 12 | margin-top: -20px; | 12 | margin-top: -20px; |
| 13 | padding-top: 3px; | 13 | padding-top: 3px; |
| 14 | } | 14 | } |
| 15 | - #div_play_time { | 15 | + .div_play_time { |
| 16 | margin-top: 10px; | 16 | margin-top: 10px; |
| 17 | } | 17 | } |
| 18 | #pb_buffer_bg { | 18 | #pb_buffer_bg { |
| @@ -47,7 +47,7 @@ | @@ -47,7 +47,7 @@ | ||
| 47 | </div> | 47 | </div> |
| 48 | <div class="form-inline"> | 48 | <div class="form-inline"> |
| 49 | URL: | 49 | URL: |
| 50 | - <input type="text" id="txt_url" class="input-xxlarge" value=""></input> | 50 | + <input type="text" id="txt_url" class="input-xxlarge" value=""> |
| 51 | <button class="btn btn-primary" id="btn_play">播放视频</button> | 51 | <button class="btn btn-primary" id="btn_play">播放视频</button> |
| 52 | <button class="btn" id="btn_generate_link">生成链接</button> | 52 | <button class="btn" id="btn_generate_link">生成链接</button> |
| 53 | </div> | 53 | </div> |
| @@ -281,57 +281,82 @@ | @@ -281,57 +281,82 @@ | ||
| 281 | </div> | 281 | </div> |
| 282 | </div> | 282 | </div> |
| 283 | <div class="modal-footer" id="my_modal_footer"> | 283 | <div class="modal-footer" id="my_modal_footer"> |
| 284 | - <div class="input-prepend" id="div_play_time"> | ||
| 285 | - <span class="add-on" title="播放时长">@T</span> | ||
| 286 | - <input class="span2" style="width:85px" id="txt_time" type="text" placeholder="天 时:分:秒"> | ||
| 287 | - </div> | ||
| 288 | - <div class="btn-group dropup"> | ||
| 289 | - <button class="btn dropdown-toggle" data-toggle="dropdown"> | ||
| 290 | - <a id="fs_tips" href="#" data-toggle="tooltip" data-placement="top" title=""> | ||
| 291 | - <img src="img/tooltip.png"/> | ||
| 292 | - </a> | ||
| 293 | - 全屏大小<span class="caret"></span> | ||
| 294 | - </button> | ||
| 295 | - <ul class="dropdown-menu"> | ||
| 296 | - <li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li> | ||
| 297 | - <li><a id="btn_fs_size_screen_75" href="#">屏幕大小(75%)</a></li> | ||
| 298 | - <li><a id="btn_fs_size_screen_50" href="#">屏幕大小(50%)</a></li> | ||
| 299 | - <li><a id="btn_fs_size_video_100" href="#">视频大小(100%)</a></li> | ||
| 300 | - <li><a id="btn_fs_size_video_75" href="#">视频大小(75%)</a></li> | ||
| 301 | - <li><a id="btn_fs_size_video_50" href="#">视频大小(50%)</a></li> | ||
| 302 | - </ul> | ||
| 303 | - </div> | ||
| 304 | - <div class="btn-group dropup"> | ||
| 305 | - <button class="btn dropdown-toggle" data-toggle="dropdown">显示比例<span class="caret"></span></button> | ||
| 306 | - <ul class="dropdown-menu"> | ||
| 307 | - <li><a id="btn_dar_original" href="#">视频原始比例</a></li> | ||
| 308 | - <li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li> | ||
| 309 | - <li><a id="btn_dar_16_9" href="#">宽屏电视(16:9)</a></li> | ||
| 310 | - <li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li> | ||
| 311 | - <li><a id="btn_dar_fill" href="#">填充(容器比例)</a></li> | ||
| 312 | - </ul> | ||
| 313 | - </div> | ||
| 314 | - <div class="btn-group dropup"> | ||
| 315 | - <button class="btn dropdown-toggle" data-toggle="dropdown">缓冲区<span class="caret"></span></button> | ||
| 316 | - <ul class="dropdown-menu"> | ||
| 317 | - <li><a id="btn_bt_0_1" href="#">0.1秒(实时)</a></li> | ||
| 318 | - <li><a id="btn_bt_0_2" href="#">0.2秒(实时)</a></li> | ||
| 319 | - <li><a id="btn_bt_0_3" href="#">0.3秒(实时)</a></li> | ||
| 320 | - <li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li> | ||
| 321 | - <li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li> | ||
| 322 | - <li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li> | ||
| 323 | - <li><a id="btn_bt_2" href="#">2秒(较低延时)</a></li> | ||
| 324 | - <li><a id="btn_bt_3" href="#">3秒(流畅播放)</a></li> | ||
| 325 | - <li><a id="btn_bt_5" href="#">5秒(网速较低)</a></li> | ||
| 326 | - <li><a id="btn_bt_10" href="#">10秒(无所谓延迟)</a></li> | ||
| 327 | - <li><a id="btn_bt_30" href="#">30秒(流畅第一)</a></li> | ||
| 328 | - </ul> | 284 | + <div> |
| 285 | + <div class="btn-group dropup"> | ||
| 286 | + <button class="btn dropdown-toggle" data-toggle="dropdown"> | ||
| 287 | + 设置全屏比例大小<span class="caret"></span> | ||
| 288 | + </button> | ||
| 289 | + <ul class="dropdown-menu"> | ||
| 290 | + <li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li> | ||
| 291 | + <li><a id="btn_fs_size_screen_75" href="#">屏幕大小(75%)</a></li> | ||
| 292 | + <li><a id="btn_fs_size_screen_50" href="#">屏幕大小(50%)</a></li> | ||
| 293 | + <li><a id="btn_fs_size_video_100" href="#">视频大小(100%)</a></li> | ||
| 294 | + <li><a id="btn_fs_size_video_75" href="#">视频大小(75%)</a></li> | ||
| 295 | + <li><a id="btn_fs_size_video_50" href="#">视频大小(50%)</a></li> | ||
| 296 | + </ul> | ||
| 297 | + </div> | ||
| 298 | + <div class="btn-group dropup"> | ||
| 299 | + <button class="btn dropdown-toggle" data-toggle="dropdown">设置显示比例<span class="caret"></span></button> | ||
| 300 | + <ul class="dropdown-menu"> | ||
| 301 | + <li><a id="btn_dar_original" href="#">视频原始比例</a></li> | ||
| 302 | + <li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li> | ||
| 303 | + <li><a id="btn_dar_16_9" href="#">宽屏电视(16:9)</a></li> | ||
| 304 | + <li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li> | ||
| 305 | + <li><a id="btn_dar_fill" href="#">填充(容器比例)</a></li> | ||
| 306 | + </ul> | ||
| 307 | + </div> | ||
| 308 | + <div class="btn-group dropup"> | ||
| 309 | + <button class="btn dropdown-toggle" data-toggle="dropdown">设置缓冲区大小<span class="caret"></span></button> | ||
| 310 | + <ul class="dropdown-menu"> | ||
| 311 | + <li><a id="btn_bt_0_1" href="#">0.1秒(实时)</a></li> | ||
| 312 | + <li><a id="btn_bt_0_2" href="#">0.2秒(实时)</a></li> | ||
| 313 | + <li><a id="btn_bt_0_3" href="#">0.3秒(实时)</a></li> | ||
| 314 | + <li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li> | ||
| 315 | + <li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li> | ||
| 316 | + <li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li> | ||
| 317 | + <li><a id="btn_bt_2" href="#">2秒(较低延时)</a></li> | ||
| 318 | + <li><a id="btn_bt_3" href="#">3秒(流畅播放)</a></li> | ||
| 319 | + <li><a id="btn_bt_5" href="#">5秒(网速较低)</a></li> | ||
| 320 | + <li><a id="btn_bt_10" href="#">10秒(无所谓延迟)</a></li> | ||
| 321 | + <li><a id="btn_bt_30" href="#">30秒(流畅第一)</a></li> | ||
| 322 | + </ul> | ||
| 323 | + </div> | ||
| 324 | + <div class="btn-group dropup"> | ||
| 325 | + <a id="btn_fullscreen" class="btn">进入全屏</a> | ||
| 326 | + </div> | ||
| 327 | + <div class="btn-group dropup"> | ||
| 328 | + <button id="btn_pause" class="btn">暂停播放</button> | ||
| 329 | + <button id="btn_resume" class="btn hide">继续播放</button> | ||
| 330 | + </div> | ||
| 331 | + <div class="btn-group dropup"> | ||
| 332 | + <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭播放器</button> | ||
| 333 | + </div> | ||
| 329 | </div> | 334 | </div> |
| 330 | - <div class="btn-group dropup"> | ||
| 331 | - <button id="btn_pause" class="btn">暂停</button> | 335 | + <div class="hide" id="fullscreen_tips"> |
| 336 | + 请<font color="red">点击视频</font>进入全屏模式~<br/> | ||
| 337 | + 由于安全原因,Flash全屏无法使用JS触发 | ||
| 332 | </div> | 338 | </div> |
| 333 | - <div class="btn-group dropup"> | ||
| 334 | - <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭</button> | 339 | + <div> |
| 340 | + <div class="input-prepend div_play_time" title="视频的播放流畅度"> | ||
| 341 | + <span class="add-on">@F</span> | ||
| 342 | + <input class="span2" style="width:57px" id="txt_fluency" type="text" placeholder="100%"> | ||
| 343 | + </div> | ||
| 344 | + <div class="input-prepend div_play_time" title="视频总共卡顿次数"> | ||
| 345 | + <span class="add-on">@E</span> | ||
| 346 | + <input class="span2" style="width:85px" id="txt_empty_count" type="text" placeholder="0"> | ||
| 347 | + </div> | ||
| 348 | + <div class="input-prepend div_play_time" title="视频当前的帧率FPS"> | ||
| 349 | + <span class="add-on">@F</span> | ||
| 350 | + <input class="span2" style="width:85px" id="txt_fps" type="text" placeholder="fps"> | ||
| 351 | + </div> | ||
| 352 | + <div class="input-prepend div_play_time" title="视频当前的码率(视频+音频),单位:Kbps"> | ||
| 353 | + <span class="add-on">@B</span> | ||
| 354 | + <input class="span2" style="width:85px" id="txt_bitrate" type="text" placeholder="kbps"> | ||
| 355 | + </div> | ||
| 356 | + <div class="input-prepend div_play_time" title="播放时长,格式:天 时:分:秒"> | ||
| 357 | + <span class="add-on">@T</span> | ||
| 358 | + <input class="span2" style="width:85px" id="txt_time" type="text" placeholder="天 时:分:秒"> | ||
| 359 | + </div> | ||
| 335 | </div> | 360 | </div> |
| 336 | </div> | 361 | </div> |
| 337 | </div> | 362 | </div> |
| @@ -398,10 +423,6 @@ | @@ -398,10 +423,6 @@ | ||
| 398 | // url set to: rtmp://demo:1935/live/livestream | 423 | // url set to: rtmp://demo:1935/live/livestream |
| 399 | srs_init_rtmp("#txt_url", "#main_modal"); | 424 | srs_init_rtmp("#txt_url", "#main_modal"); |
| 400 | 425 | ||
| 401 | - $("#fs_tips").tooltip({ | ||
| 402 | - title: "点击视频进入或退出全屏" | ||
| 403 | - }); | ||
| 404 | - | ||
| 405 | $("#main_modal").on("show", function(){ | 426 | $("#main_modal").on("show", function(){ |
| 406 | if (srs_player) { | 427 | if (srs_player) { |
| 407 | return; | 428 | return; |
| @@ -427,7 +448,7 @@ | @@ -427,7 +448,7 @@ | ||
| 427 | select_dar("#btn_dar_original", 0, 0); | 448 | select_dar("#btn_dar_original", 0, 0); |
| 428 | select_fs_size("#btn_fs_size_screen_100", "screen", 100); | 449 | select_fs_size("#btn_fs_size_screen_100", "screen", 100); |
| 429 | }; | 450 | }; |
| 430 | - srs_player.on_player_timer = function(time, buffer_length) { | 451 | + srs_player.on_player_timer = function(time, buffer_length, kbps, fps, rtime) { |
| 431 | var buffer = buffer_length / this.buffer_time * 100; | 452 | var buffer = buffer_length / this.buffer_time * 100; |
| 432 | $("#pb_buffer").width(Number(buffer).toFixed(1) + "%"); | 453 | $("#pb_buffer").width(Number(buffer).toFixed(1) + "%"); |
| 433 | 454 | ||
| @@ -435,6 +456,11 @@ | @@ -435,6 +456,11 @@ | ||
| 435 | "缓冲区长度:" + Number(buffer_length).toFixed(1) + "秒(" | 456 | "缓冲区长度:" + Number(buffer_length).toFixed(1) + "秒(" |
| 436 | + Number(buffer).toFixed(1) + "%)"); | 457 | + Number(buffer).toFixed(1) + "%)"); |
| 437 | 458 | ||
| 459 | + $("#txt_bitrate").val(kbps.toFixed(1) + "kbps"); | ||
| 460 | + $("#txt_fps").val(fps.toFixed(1) + "fps"); | ||
| 461 | + $("#txt_empty_count").val(srs_player.empty_count() + "次卡顿"); | ||
| 462 | + $("#txt_fluency").val(srs_player.fluency().toFixed(2) + "%"); | ||
| 463 | + | ||
| 438 | var time_str = ""; | 464 | var time_str = ""; |
| 439 | // day | 465 | // day |
| 440 | time_str = padding(parseInt(time / 24 / 3600), 2, '0') + " "; | 466 | time_str = padding(parseInt(time / 24 / 3600), 2, '0') + " "; |
| @@ -454,10 +480,6 @@ | @@ -454,10 +480,6 @@ | ||
| 454 | }); | 480 | }); |
| 455 | 481 | ||
| 456 | $("#main_modal").on("hide", function(){ | 482 | $("#main_modal").on("hide", function(){ |
| 457 | - if ($("#main_modal").is(":visible")) { | ||
| 458 | - return; | ||
| 459 | - } | ||
| 460 | - | ||
| 461 | if (srs_player) { | 483 | if (srs_player) { |
| 462 | srs_player.stop(); | 484 | srs_player.stop(); |
| 463 | srs_player = null; | 485 | srs_player = null; |
| @@ -477,22 +499,27 @@ | @@ -477,22 +499,27 @@ | ||
| 477 | $("#link_stream").text(rtmp.stream); | 499 | $("#link_stream").text(rtmp.stream); |
| 478 | $("#link_rtmp").text($("#txt_url").val()); | 500 | $("#link_rtmp").text($("#txt_url").val()); |
| 479 | $("#link_url").attr("href", url); | 501 | $("#link_url").attr("href", url); |
| 480 | - $("#link_modal").modal({show:true, keyboard:false}); | 502 | + $("#link_modal").modal({show:true, keyboard:true}); |
| 481 | }); | 503 | }); |
| 482 | 504 | ||
| 483 | $("#btn_play").click(function(){ | 505 | $("#btn_play").click(function(){ |
| 484 | url = $("#txt_url").val(); | 506 | url = $("#txt_url").val(); |
| 485 | - $("#main_modal").modal({show:true, keyboard:false}); | 507 | + $("#main_modal").modal({show:true, keyboard:true}); |
| 486 | }); | 508 | }); |
| 487 | 509 | ||
| 488 | - $("#btn_pause").click(function(){ | ||
| 489 | - if ($("#btn_pause").text() == "暂停") { | ||
| 490 | - $("#btn_pause").text("继续"); | ||
| 491 | - srs_player.pause(); | ||
| 492 | - } else { | ||
| 493 | - $("#btn_pause").text("暂停"); | ||
| 494 | - srs_player.resume(); | ||
| 495 | - } | 510 | + $("#btn_fullscreen").click(function(){ |
| 511 | + $("#fullscreen_tips").toggle(); | ||
| 512 | + }); | ||
| 513 | + | ||
| 514 | + $("#btn_pause").click(function() { | ||
| 515 | + $("#btn_resume").toggle(); | ||
| 516 | + $("#btn_pause").toggle(); | ||
| 517 | + srs_player.pause(); | ||
| 518 | + }); | ||
| 519 | + $("#btn_resume").click(function(){ | ||
| 520 | + $("#btn_resume").toggle(); | ||
| 521 | + $("#btn_pause").toggle(); | ||
| 522 | + srs_player.resume(); | ||
| 496 | }); | 523 | }); |
| 497 | 524 | ||
| 498 | if (true) { | 525 | if (true) { |
| @@ -18,6 +18,7 @@ package | @@ -18,6 +18,7 @@ package | ||
| 18 | import flash.ui.ContextMenu; | 18 | import flash.ui.ContextMenu; |
| 19 | import flash.ui.ContextMenuItem; | 19 | import flash.ui.ContextMenuItem; |
| 20 | import flash.utils.Timer; | 20 | import flash.utils.Timer; |
| 21 | + import flash.utils.getTimer; | ||
| 21 | import flash.utils.setTimeout; | 22 | import flash.utils.setTimeout; |
| 22 | 23 | ||
| 23 | import flashx.textLayout.formats.Float; | 24 | import flashx.textLayout.formats.Float; |
| @@ -30,7 +31,9 @@ package | @@ -30,7 +31,9 @@ package | ||
| 30 | private var js_on_player_ready:String = null; | 31 | private var js_on_player_ready:String = null; |
| 31 | private var js_on_player_metadata:String = null; | 32 | private var js_on_player_metadata:String = null; |
| 32 | private var js_on_player_timer:String = null; | 33 | private var js_on_player_timer:String = null; |
| 33 | - | 34 | + private var js_on_player_empty:String = null; |
| 35 | + private var js_on_player_full:String = null; | ||
| 36 | + | ||
| 34 | // play param url. | 37 | // play param url. |
| 35 | private var user_url:String = null; | 38 | private var user_url:String = null; |
| 36 | // play param, user set width and height | 39 | // play param, user set width and height |
| @@ -93,6 +96,8 @@ package | @@ -93,6 +96,8 @@ package | ||
| 93 | this.js_on_player_ready = flashvars.on_player_ready; | 96 | this.js_on_player_ready = flashvars.on_player_ready; |
| 94 | this.js_on_player_metadata = flashvars.on_player_metadata; | 97 | this.js_on_player_metadata = flashvars.on_player_metadata; |
| 95 | this.js_on_player_timer = flashvars.on_player_timer; | 98 | this.js_on_player_timer = flashvars.on_player_timer; |
| 99 | + this.js_on_player_empty = flashvars.on_player_empty; | ||
| 100 | + this.js_on_player_full = flashvars.on_player_full; | ||
| 96 | 101 | ||
| 97 | this.media_timer.addEventListener(TimerEvent.TIMER, this.system_on_timer); | 102 | this.media_timer.addEventListener(TimerEvent.TIMER, this.system_on_timer); |
| 98 | this.media_timer.start(); | 103 | this.media_timer.start(); |
| @@ -106,7 +111,7 @@ package | @@ -106,7 +111,7 @@ package | ||
| 106 | */ | 111 | */ |
| 107 | private function system_on_js_ready():void { | 112 | private function system_on_js_ready():void { |
| 108 | if (!flash.external.ExternalInterface.available) { | 113 | if (!flash.external.ExternalInterface.available) { |
| 109 | - trace("js not ready, try later."); | 114 | + log("js not ready, try later."); |
| 110 | flash.utils.setTimeout(this.system_on_js_ready, 100); | 115 | flash.utils.setTimeout(this.system_on_js_ready, 100); |
| 111 | return; | 116 | return; |
| 112 | } | 117 | } |
| @@ -114,7 +119,7 @@ package | @@ -114,7 +119,7 @@ package | ||
| 114 | flash.external.ExternalInterface.addCallback("__play", this.js_call_play); | 119 | flash.external.ExternalInterface.addCallback("__play", this.js_call_play); |
| 115 | flash.external.ExternalInterface.addCallback("__stop", this.js_call_stop); | 120 | flash.external.ExternalInterface.addCallback("__stop", this.js_call_stop); |
| 116 | flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause); | 121 | flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause); |
| 117 | - flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume); | 122 | + flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume); |
| 118 | flash.external.ExternalInterface.addCallback("__set_dar", this.js_call_set_dar); | 123 | flash.external.ExternalInterface.addCallback("__set_dar", this.js_call_set_dar); |
| 119 | flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size); | 124 | flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size); |
| 120 | flash.external.ExternalInterface.addCallback("__set_bt", this.js_call_set_bt); | 125 | flash.external.ExternalInterface.addCallback("__set_bt", this.js_call_set_bt); |
| @@ -126,15 +131,39 @@ package | @@ -126,15 +131,39 @@ package | ||
| 126 | * system callack event, timer to do some regular tasks. | 131 | * system callack event, timer to do some regular tasks. |
| 127 | */ | 132 | */ |
| 128 | private function system_on_timer(evt:TimerEvent):void { | 133 | private function system_on_timer(evt:TimerEvent):void { |
| 129 | - if (!this.media_stream) { | ||
| 130 | - trace("stream is null, ignore timer event."); | 134 | + var ms:NetStream = this.media_stream; |
| 135 | + | ||
| 136 | + if (!ms) { | ||
| 137 | + log("stream is null, ignore timer event."); | ||
| 131 | return; | 138 | return; |
| 132 | } | 139 | } |
| 133 | - | ||
| 134 | - trace("notify js the timer event."); | 140 | + |
| 141 | + var rtime:Number = flash.utils.getTimer(); | ||
| 142 | + var bitrate:Number = Number((ms.info.videoBytesPerSecond + ms.info.audioBytesPerSecond) * 8 / 1000); | ||
| 143 | + log("on timer, time=" + ms.time.toFixed(2) + "s, buffer=" + ms.bufferLength.toFixed(2) + "s" | ||
| 144 | + + ", bitrate=" + bitrate.toFixed(1) + "kbps" | ||
| 145 | + + ", fps=" + ms.currentFPS.toFixed(1) | ||
| 146 | + + ", rtime=" + rtime.toFixed(0) | ||
| 147 | + ); | ||
| 135 | flash.external.ExternalInterface.call( | 148 | flash.external.ExternalInterface.call( |
| 136 | - this.js_on_player_timer, this.js_id, this.media_stream.time, this.media_stream.bufferLength); | 149 | + this.js_on_player_timer, this.js_id, ms.time, ms.bufferLength, |
| 150 | + bitrate, ms.currentFPS, rtime | ||
| 151 | + ); | ||
| 137 | } | 152 | } |
| 153 | + | ||
| 154 | + /** | ||
| 155 | + * system callback event, when stream is empty. | ||
| 156 | + */ | ||
| 157 | + private function system_on_buffer_empty():void { | ||
| 158 | + var time:Number = flash.utils.getTimer(); | ||
| 159 | + log("stream is empty at " + time + "ms"); | ||
| 160 | + flash.external.ExternalInterface.call(this.js_on_player_empty, this.js_id, time); | ||
| 161 | + } | ||
| 162 | + private function system_on_buffer_full():void { | ||
| 163 | + var time:Number = flash.utils.getTimer(); | ||
| 164 | + log("stream is full at " + time + "ms"); | ||
| 165 | + flash.external.ExternalInterface.call(this.js_on_player_full, this.js_id, time); | ||
| 166 | + } | ||
| 138 | 167 | ||
| 139 | /** | 168 | /** |
| 140 | * system callack event, when got metadata from stream. | 169 | * system callack event, when got metadata from stream. |
| @@ -181,7 +210,7 @@ package | @@ -181,7 +210,7 @@ package | ||
| 181 | */ | 210 | */ |
| 182 | private function user_on_click_video(evt:MouseEvent):void { | 211 | private function user_on_click_video(evt:MouseEvent):void { |
| 183 | if (!this.stage.allowsFullScreen) { | 212 | if (!this.stage.allowsFullScreen) { |
| 184 | - trace("donot allow fullscreen."); | 213 | + log("donot allow fullscreen."); |
| 185 | return; | 214 | return; |
| 186 | } | 215 | } |
| 187 | 216 | ||
| @@ -266,6 +295,7 @@ package | @@ -266,6 +295,7 @@ package | ||
| 266 | this.media_conn.close(); | 295 | this.media_conn.close(); |
| 267 | this.media_conn = null; | 296 | this.media_conn = null; |
| 268 | } | 297 | } |
| 298 | + log("player stopped"); | ||
| 269 | } | 299 | } |
| 270 | 300 | ||
| 271 | // srs infos | 301 | // srs infos |
| @@ -311,7 +341,7 @@ package | @@ -311,7 +341,7 @@ package | ||
| 311 | this.user_url = url; | 341 | this.user_url = url; |
| 312 | this.user_w = _width; | 342 | this.user_w = _width; |
| 313 | this.user_h = _height; | 343 | this.user_h = _height; |
| 314 | - trace("start to play url: " + this.user_url + ", w=" + this.user_w + ", h=" + this.user_h); | 344 | + log("start to play url: " + this.user_url + ", w=" + this.user_w + ", h=" + this.user_h); |
| 315 | 345 | ||
| 316 | js_call_stop(); | 346 | js_call_stop(); |
| 317 | 347 | ||
| @@ -358,7 +388,11 @@ package | @@ -358,7 +388,11 @@ package | ||
| 358 | 388 | ||
| 359 | if (evt.info.code == "NetStream.Video.DimensionChange") { | 389 | if (evt.info.code == "NetStream.Video.DimensionChange") { |
| 360 | system_on_metadata(media_metadata); | 390 | system_on_metadata(media_metadata); |
| 361 | - } | 391 | + } else if (evt.info.code == "NetStream.Buffer.Empty") { |
| 392 | + system_on_buffer_empty(); | ||
| 393 | + } else if (evt.info.code == "NetStream.Buffer.Full") { | ||
| 394 | + system_on_buffer_full(); | ||
| 395 | + } | ||
| 362 | 396 | ||
| 363 | // TODO: FIXME: failed event. | 397 | // TODO: FIXME: failed event. |
| 364 | }); | 398 | }); |
| @@ -460,7 +494,11 @@ package | @@ -460,7 +494,11 @@ package | ||
| 460 | } | 494 | } |
| 461 | 495 | ||
| 462 | // rescale to fs | 496 | // rescale to fs |
| 463 | - __update_video_size(num, den, obj.width * user_fs_percent / 100, obj.height * user_fs_percent / 100, this.stage.fullScreenWidth, this.stage.fullScreenHeight); | 497 | + __update_video_size(num, den, |
| 498 | + obj.width * user_fs_percent / 100, | ||
| 499 | + obj.height * user_fs_percent / 100, | ||
| 500 | + this.stage.fullScreenWidth, this.stage.fullScreenHeight | ||
| 501 | + ); | ||
| 464 | } | 502 | } |
| 465 | 503 | ||
| 466 | /** | 504 | /** |
| @@ -539,5 +577,18 @@ package | @@ -539,5 +577,18 @@ package | ||
| 539 | this.control_fs_mask.graphics.drawRect(0, 0, _width, _height); | 577 | this.control_fs_mask.graphics.drawRect(0, 0, _width, _height); |
| 540 | this.control_fs_mask.graphics.endFill(); | 578 | this.control_fs_mask.graphics.endFill(); |
| 541 | } | 579 | } |
| 580 | + | ||
| 581 | + private function log(msg:String):void { | ||
| 582 | + msg = "[" + new Date() +"][srs-player][" + js_id + "] " + msg; | ||
| 583 | + | ||
| 584 | + trace(msg); | ||
| 585 | + | ||
| 586 | + if (!flash.external.ExternalInterface.available) { | ||
| 587 | + flash.utils.setTimeout(log, 300, msg); | ||
| 588 | + return; | ||
| 589 | + } | ||
| 590 | + | ||
| 591 | + ExternalInterface.call("console.log", msg); | ||
| 592 | + } | ||
| 542 | } | 593 | } |
| 543 | } | 594 | } |
-
请 注册 或 登录 后发表评论