winlin

fix the bitrate bug(in Bps), use enhanced microphone.

@@ -276,6 +276,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw @@ -276,6 +276,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw
276 * nginx v1.5.0: 139524 lines <br/> 276 * nginx v1.5.0: 139524 lines <br/>
277 277
278 ### History 278 ### History
  279 +* v0.9, 2013-12-25, fix the bitrate bug(in Bps), use enhanced microphone.
279 * v0.9, 2013-12-22, demo video meeting or chat(srs+cherrypy+jquery+bootstrap). 280 * v0.9, 2013-12-22, demo video meeting or chat(srs+cherrypy+jquery+bootstrap).
280 * v0.9, 2013-12-22, merge from wenjie, support banwidth test. 281 * v0.9, 2013-12-22, merge from wenjie, support banwidth test.
281 * v0.9, 2013-12-22, merge from wenjie: support set chunk size at vhost level 282 * v0.9, 2013-12-22, merge from wenjie: support set chunk size at vhost level
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -53,31 +53,6 @@ function update_nav() { @@ -53,31 +53,6 @@ function update_nav() {
53 } 53 }
54 54
55 /** 55 /**
56 -* log specified, there must be a log element as:  
57 - <!-- for the log -->  
58 - <div class="alert alert-info fade in" id="txt_log">  
59 - <button type="button" class="close" data-dismiss="alert">×</button>  
60 - <strong><span id="txt_log_title">Usage:</span></strong>  
61 - <span id="txt_log_msg">创建会议室,或者加入会议室</span>  
62 - </div>  
63 -*/  
64 -function info(desc) {  
65 - $("#txt_log").addClass("alert-info").removeClass("alert-error").removeClass("alert-warn");  
66 - $("#txt_log_title").text("Info:");  
67 - $("#txt_log_msg").text(desc);  
68 -}  
69 -function warn(code, desc) {  
70 - $("#txt_log").removeClass("alert-info").removeClass("alert-error").addClass("alert-warn");  
71 - $("#txt_log_title").text("Warn:");  
72 - $("#txt_log_msg").text("code: " + code + ", " + desc);  
73 -}  
74 -function error(code, desc) {  
75 - $("#txt_log").removeClass("alert-info").addClass("alert-error").removeClass("alert-warn");  
76 - $("#txt_log_title").text("Error:");  
77 - $("#txt_log_msg").text("code: " + code + ", " + desc);  
78 -}  
79 -  
80 -/**  
81 * parse the query string to object. 56 * parse the query string to object.
82 */ 57 */
83 function parse_query_string(){ 58 function parse_query_string(){
@@ -247,10 +222,8 @@ function srs_init_publish(rtmp_url) { @@ -247,10 +222,8 @@ function srs_init_publish(rtmp_url) {
247 } 222 }
248 } 223 }
249 224
250 -/**  
251 -* when publisher ready, init the page elements.  
252 -*/  
253 -function srs_publisher_initialize_page( 225 +// without default values set.
  226 +function srs_initialize_codec_page(
254 cameras, microphones, 227 cameras, microphones,
255 sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate 228 sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate
256 ) { 229 ) {
@@ -265,14 +238,36 @@ function srs_publisher_initialize_page( @@ -265,14 +238,36 @@ function srs_publisher_initialize_page(
265 break; 238 break;
266 } 239 }
267 } 240 }
  241 + // optional: select the first "integrated" signed.
  242 + for (var i = 0; i < cameras.length; i++) {
  243 + if (cameras[i].toLowerCase().indexOf("integrated") >= 0) {
  244 + $(sl_cameras + " option[value='" + i + "']").attr("selected", true);
  245 + break;
  246 + }
  247 + }
268 248
269 $(sl_microphones).empty(); 249 $(sl_microphones).empty();
270 for (var i = 0; i < microphones.length; i++) { 250 for (var i = 0; i < microphones.length; i++) {
271 $(sl_microphones).append("<option value='" + i + "'>" + microphones[i] + "</option"); 251 $(sl_microphones).append("<option value='" + i + "'>" + microphones[i] + "</option");
272 } 252 }
  253 + // optional: select the first no "default" signed.
  254 + for (var i = 0; i < microphones.length; i++) {
  255 + if (microphones[i].toLowerCase().indexOf("default") == -1) {
  256 + $(sl_microphones + " option[value='" + i + "']").attr("selected", true);
  257 + break;
  258 + }
  259 + }
  260 + // optional: select the first "realtek" signed.
  261 + for (var i = 0; i < microphones.length; i++) {
  262 + if (microphones[i].toLowerCase().indexOf("realtek") >= 0) {
  263 + $(sl_microphones + " option[value='" + i + "']").attr("selected", true);
  264 + break;
  265 + }
  266 + }
273 267
274 $(sl_vcodec).empty(); 268 $(sl_vcodec).empty();
275 var vcodecs = ["h264", "vp6"]; 269 var vcodecs = ["h264", "vp6"];
  270 + vcodecs = ["h264"]; // h264 only.
276 for (var i = 0; i < vcodecs.length; i++) { 271 for (var i = 0; i < vcodecs.length; i++) {
277 $(sl_vcodec).append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option"); 272 $(sl_vcodec).append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option");
278 } 273 }
@@ -282,7 +277,6 @@ function srs_publisher_initialize_page( @@ -282,7 +277,6 @@ function srs_publisher_initialize_page(
282 for (var i = 0; i < profiles.length; i++) { 277 for (var i = 0; i < profiles.length; i++) {
283 $(sl_profile).append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option"); 278 $(sl_profile).append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option");
284 } 279 }
285 - $(sl_profile + " option[value='main']").attr("selected", true);  
286 280
287 $(sl_level).empty(); 281 $(sl_level).empty();
288 var levels = ["1", "1b", "1.1", "1.2", "1.3", 282 var levels = ["1", "1b", "1.1", "1.2", "1.3",
@@ -290,7 +284,6 @@ function srs_publisher_initialize_page( @@ -290,7 +284,6 @@ function srs_publisher_initialize_page(
290 for (var i = 0; i < levels.length; i++) { 284 for (var i = 0; i < levels.length; i++) {
291 $(sl_level).append("<option value='" + levels[i] + "'>" + levels[i] + "</option"); 285 $(sl_level).append("<option value='" + levels[i] + "'>" + levels[i] + "</option");
292 } 286 }
293 - $(sl_level + " option[value='4.1']").attr("selected", true);  
294 287
295 $(sl_gop).empty(); 288 $(sl_gop).empty();
296 var gops = ["0.3", "0.5", "1", "2", "3", "4", 289 var gops = ["0.3", "0.5", "1", "2", "3", "4",
@@ -298,7 +291,6 @@ function srs_publisher_initialize_page( @@ -298,7 +291,6 @@ function srs_publisher_initialize_page(
298 for (var i = 0; i < gops.length; i++) { 291 for (var i = 0; i < gops.length; i++) {
299 $(sl_gop).append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option"); 292 $(sl_gop).append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option");
300 } 293 }
301 - $(sl_gop + " option[value='10']").attr("selected", true);  
302 294
303 $(sl_size).empty(); 295 $(sl_size).empty();
304 var sizes = ["176x144", "320x240", "352x240", 296 var sizes = ["176x144", "320x240", "352x240",
@@ -307,14 +299,12 @@ function srs_publisher_initialize_page( @@ -307,14 +299,12 @@ function srs_publisher_initialize_page(
307 for (i = 0; i < sizes.length; i++) { 299 for (i = 0; i < sizes.length; i++) {
308 $(sl_size).append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option"); 300 $(sl_size).append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option");
309 } 301 }
310 - $(sl_size + " option[value='640x480']").attr("selected", true);  
311 302
312 $(sl_fps).empty(); 303 $(sl_fps).empty();
313 var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"]; 304 var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];
314 for (i = 0; i < fpses.length; i++) { 305 for (i = 0; i < fpses.length; i++) {
315 $(sl_fps).append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option"); 306 $(sl_fps).append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option");
316 } 307 }
317 - $(sl_fps + " option[value='20']").attr("selected", true);  
318 308
319 $(sl_bitrate).empty(); 309 $(sl_bitrate).empty();
320 var bitrates = ["50", "200", "350", "500", "650", "800", 310 var bitrates = ["50", "200", "350", "500", "650", "800",
@@ -322,6 +312,40 @@ function srs_publisher_initialize_page( @@ -322,6 +312,40 @@ function srs_publisher_initialize_page(
322 for (i = 0; i < bitrates.length; i++) { 312 for (i = 0; i < bitrates.length; i++) {
323 $(sl_bitrate).append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option"); 313 $(sl_bitrate).append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option");
324 } 314 }
  315 +}
  316 +/**
  317 +* when publisher ready, init the page elements.
  318 +*/
  319 +function srs_publisher_initialize_page(
  320 + cameras, microphones,
  321 + sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate
  322 +) {
  323 + srs_initialize_codec_page(
  324 + cameras, microphones,
  325 + sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate
  326 + );
  327 +
  328 + //var profiles = ["baseline", "main"];
  329 + $(sl_profile + " option[value='main']").attr("selected", true);
  330 +
  331 + //var levels = ["1", "1b", "1.1", "1.2", "1.3",
  332 + // "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];
  333 + $(sl_level + " option[value='4.1']").attr("selected", true);
  334 +
  335 + //var gops = ["0.3", "0.5", "1", "2", "3", "4",
  336 + // "5", "6", "7", "8", "9", "10", "15", "20"];
  337 + $(sl_gop + " option[value='10']").attr("selected", true);
  338 +
  339 + //var sizes = ["176x144", "320x240", "352x240",
  340 + // "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",
  341 + // "1024x768", "1280x720", "1360x768", "1920x1080"];
  342 + $(sl_size + " option[value='640x480']").attr("selected", true);
  343 +
  344 + //var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];
  345 + $(sl_fps + " option[value='20']").attr("selected", true);
  346 +
  347 + //var bitrates = ["50", "200", "350", "500", "650", "800",
  348 + // "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];
325 $(sl_bitrate + " option[value='500']").attr("selected", true); 349 $(sl_bitrate + " option[value='500']").attr("selected", true);
326 } 350 }
327 /** 351 /**
@@ -331,75 +355,33 @@ function srs_chat_initialize_page( @@ -331,75 +355,33 @@ function srs_chat_initialize_page(
331 cameras, microphones, 355 cameras, microphones,
332 sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate 356 sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate
333 ) { 357 ) {
334 - $(sl_cameras).empty();  
335 - for (var i = 0; i < cameras.length; i++) {  
336 - $(sl_cameras).append("<option value='" + i + "'>" + cameras[i] + "</option");  
337 - }  
338 - // optional: select the first no "virtual" signed.  
339 - for (var i = 0; i < cameras.length; i++) {  
340 - if (cameras[i].toLowerCase().indexOf("virtual") == -1) {  
341 - $(sl_cameras + " option[value='" + i + "']").attr("selected", true);  
342 - break;  
343 - }  
344 - }  
345 -  
346 - $(sl_microphones).empty();  
347 - for (var i = 0; i < microphones.length; i++) {  
348 - $(sl_microphones).append("<option value='" + i + "'>" + microphones[i] + "</option");  
349 - }  
350 -  
351 - $(sl_vcodec).empty();  
352 - var vcodecs = ["h264", "vp6"];  
353 - for (var i = 0; i < vcodecs.length; i++) {  
354 - $(sl_vcodec).append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option");  
355 - } 358 + srs_initialize_codec_page(
  359 + cameras, microphones,
  360 + sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate
  361 + );
356 362
357 - $(sl_profile).empty();  
358 - var profiles = ["baseline", "main"];  
359 - for (var i = 0; i < profiles.length; i++) {  
360 - $(sl_profile).append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option");  
361 - } 363 + //var profiles = ["baseline", "main"];
362 $(sl_profile + " option[value='baseline']").attr("selected", true); 364 $(sl_profile + " option[value='baseline']").attr("selected", true);
363 365
364 - $(sl_level).empty();  
365 - var levels = ["1", "1b", "1.1", "1.2", "1.3",  
366 - "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];  
367 - for (var i = 0; i < levels.length; i++) {  
368 - $(sl_level).append("<option value='" + levels[i] + "'>" + levels[i] + "</option");  
369 - }  
370 - $(sl_level + " option[value='3.1']").attr("selected", true); 366 + //var levels = ["1", "1b", "1.1", "1.2", "1.3",
  367 + // "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];
  368 + $(sl_level + " option[value='2.1']").attr("selected", true);
371 369
372 - $(sl_gop).empty();  
373 - var gops = ["0.3", "0.5", "1", "2", "3", "4",  
374 - "5", "6", "7", "8", "9", "10", "15", "20"];  
375 - for (var i = 0; i < gops.length; i++) {  
376 - $(sl_gop).append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option");  
377 - } 370 + //var gops = ["0.3", "0.5", "1", "2", "3", "4",
  371 + // "5", "6", "7", "8", "9", "10", "15", "20"];
378 $(sl_gop + " option[value='0.5']").attr("selected", true); 372 $(sl_gop + " option[value='0.5']").attr("selected", true);
379 373
380 - $(sl_size).empty();  
381 - var sizes = ["176x144", "320x240", "352x240",  
382 - "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",  
383 - "1024x768", "1280x720", "1360x768", "1920x1080"];  
384 - for (i = 0; i < sizes.length; i++) {  
385 - $(sl_size).append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option");  
386 - }  
387 - $(sl_size + " option[value='460x240']").attr("selected", true); 374 + //var sizes = ["176x144", "320x240", "352x240",
  375 + // "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",
  376 + // "1024x768", "1280x720", "1360x768", "1920x1080"];
  377 + $(sl_size + " option[value='320x240']").attr("selected", true);
388 378
389 - $(sl_fps).empty();  
390 - var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];  
391 - for (i = 0; i < fpses.length; i++) {  
392 - $(sl_fps).append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option");  
393 - }  
394 - $(sl_fps + " option[value='15']").attr("selected", true); 379 + //var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];
  380 + $(sl_fps + " option[value='10']").attr("selected", true);
395 381
396 - $(sl_bitrate).empty();  
397 - var bitrates = ["50", "200", "350", "500", "650", "800",  
398 - "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];  
399 - for (i = 0; i < bitrates.length; i++) {  
400 - $(sl_bitrate).append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option");  
401 - }  
402 - $(sl_bitrate + " option[value='350']").attr("selected", true); 382 + //var bitrates = ["50", "200", "350", "500", "650", "800",
  383 + // "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];
  384 + $(sl_bitrate + " option[value='200']").attr("selected", true);
403 } 385 }
404 /** 386 /**
405 * get the vcodec and acodec. 387 * get the vcodec and acodec.
@@ -451,6 +433,7 @@ function SrsPlayer(container, width, height, private_object) { @@ -451,6 +433,7 @@ function SrsPlayer(container, width, height, private_object) {
451 this.id = SrsPlayer.__id++; 433 this.id = SrsPlayer.__id++;
452 this.stream_url = null; 434 this.stream_url = null;
453 this.buffer_time = 0.8; // default to 0.8 435 this.buffer_time = 0.8; // default to 0.8
  436 + this.volume = 1.0; // default to 100%
454 this.callbackObj = null; 437 this.callbackObj = null;
455 438
456 // callback set the following values. 439 // callback set the following values.
@@ -502,12 +485,19 @@ SrsPlayer.prototype.start = function(url) { @@ -502,12 +485,19 @@ SrsPlayer.prototype.start = function(url) {
502 /** 485 /**
503 * play the stream. 486 * play the stream.
504 * @param stream_url the url of stream, rtmp or http. 487 * @param stream_url the url of stream, rtmp or http.
  488 +* @param volume the volume, 0 is mute, 1 is 100%, 2 is 200%.
505 */ 489 */
506 -SrsPlayer.prototype.play = function(url) { 490 +SrsPlayer.prototype.play = function(url, volume) {
507 if (url) { 491 if (url) {
508 this.stream_url = url; 492 this.stream_url = url;
509 } 493 }
510 - this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time); 494 +
  495 + // volume maybe 0, so never use if(volume) to check its value.
  496 + if (volume != null && volume != undefined) {
  497 + this.volume = volume;
  498 + }
  499 +
  500 + this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time, this.volume);
511 } 501 }
512 SrsPlayer.prototype.stop = function() { 502 SrsPlayer.prototype.stop = function() {
513 for (var i = 0; i < SrsPlayer.__players.length; i++) { 503 for (var i = 0; i < SrsPlayer.__players.length; i++) {
@@ -652,7 +642,7 @@ function SrsPublisher(container, width, height, private_object) { @@ -652,7 +642,7 @@ function SrsPublisher(container, width, height, private_object) {
652 this.errors = { 642 this.errors = {
653 "100": "无法获取指定的摄像头", //error_camera_get 643 "100": "无法获取指定的摄像头", //error_camera_get
654 "101": "无法获取指定的麦克风", //error_microphone_get 644 "101": "无法获取指定的麦克风", //error_microphone_get
655 - "102": "摄像头为禁用状态,推流时请允许flash访问摄像头", //error_camera_muted 645 + "102": "摄像头为禁用状态,推流时请允许flash访问摄像头" //error_camera_muted
656 }; 646 };
657 } 647 }
658 /** 648 /**
  1 +/**
  2 +* log specified, there must be a log element as:
  3 + <!-- for the log -->
  4 + <div class="alert alert-info fade in" id="txt_log">
  5 + <button type="button" class="close" data-dismiss="alert">×</button>
  6 + <strong><span id="txt_log_title">标题:</span></strong>
  7 + <span id="txt_log_msg">日志内容</span>
  8 + </div>
  9 +*/
  10 +function info(desc) {
  11 + $("#txt_log").addClass("alert-info").removeClass("alert-error").removeClass("alert-warn");
  12 + $("#txt_log_title").text("Info:");
  13 + $("#txt_log_msg").text(desc);
  14 +}
  15 +function warn(code, desc) {
  16 + $("#txt_log").removeClass("alert-info").removeClass("alert-error").addClass("alert-warn");
  17 + $("#txt_log_title").text("Warn:");
  18 + $("#txt_log_msg").text("code: " + code + ", " + desc);
  19 +}
  20 +function error(code, desc) {
  21 + $("#txt_log").removeClass("alert-info").addClass("alert-error").removeClass("alert-warn");
  22 + $("#txt_log_title").text("Error:");
  23 + $("#txt_log_msg").text("code: " + code + ", " + desc);
  24 +}
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script> 7 <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/srs.js"></script> 9 <script type="text/javascript" src="js/srs.js"></script>
  10 + <script type="text/javascript" src="js/srs.log.js"></script>
10 <style> 11 <style>
11 body{ 12 body{
12 padding-top: 55px; 13 padding-top: 55px;
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -420,7 +421,7 @@ @@ -420,7 +421,7 @@
420 if (realtime_player) { 421 if (realtime_player) {
421 // directly play the url for the realtime player. 422 // directly play the url for the realtime player.
422 realtime_player.stop(); 423 realtime_player.stop();
423 - realtime_player.play(url); 424 + realtime_player.play(url, 0);
424 } 425 }
425 } 426 }
426 }); 427 });
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -10,6 +10,7 @@ package @@ -10,6 +10,7 @@ package
10 import flash.events.NetStatusEvent; 10 import flash.events.NetStatusEvent;
11 import flash.events.TimerEvent; 11 import flash.events.TimerEvent;
12 import flash.external.ExternalInterface; 12 import flash.external.ExternalInterface;
  13 + import flash.media.SoundTransform;
13 import flash.media.Video; 14 import flash.media.Video;
14 import flash.net.NetConnection; 15 import flash.net.NetConnection;
15 import flash.net.NetStream; 16 import flash.net.NetStream;
@@ -19,6 +20,8 @@ package @@ -19,6 +20,8 @@ package
19 import flash.utils.Timer; 20 import flash.utils.Timer;
20 import flash.utils.setTimeout; 21 import flash.utils.setTimeout;
21 22
  23 + import flashx.textLayout.formats.Float;
  24 +
22 public class srs_player extends Sprite 25 public class srs_player extends Sprite
23 { 26 {
24 // user set id. 27 // user set id.
@@ -280,8 +283,9 @@ package @@ -280,8 +283,9 @@ package
280 * @param _width, the player width. 283 * @param _width, the player width.
281 * @param _height, the player height. 284 * @param _height, the player height.
282 * @param buffer_time, the buffer time in seconds. recommend to >=0.5 285 * @param buffer_time, the buffer time in seconds. recommend to >=0.5
  286 + * @param volume, the volume, 0 is mute, 1 is 100%, 2 is 200%.
283 */ 287 */
284 - private function js_call_play(url:String, _width:int, _height:int, buffer_time:Number):void { 288 + private function js_call_play(url:String, _width:int, _height:int, buffer_time:Number, volume:Number):void {
285 this.user_url = url; 289 this.user_url = url;
286 this.user_w = _width; 290 this.user_w = _width;
287 this.user_h = _height; 291 this.user_h = _height;
@@ -313,6 +317,7 @@ package @@ -313,6 +317,7 @@ package
313 } 317 }
314 318
315 media_stream = new NetStream(media_conn); 319 media_stream = new NetStream(media_conn);
  320 + media_stream.soundTransform = new SoundTransform(volume);
316 media_stream.bufferTime = buffer_time; 321 media_stream.bufferTime = buffer_time;
317 media_stream.client = {}; 322 media_stream.client = {};
318 media_stream.client.onMetaData = system_on_metadata; 323 media_stream.client.onMetaData = system_on_metadata;
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;
@@ -10,6 +10,9 @@ package @@ -10,6 +10,9 @@ package
10 import flash.media.H264Profile; 10 import flash.media.H264Profile;
11 import flash.media.H264VideoStreamSettings; 11 import flash.media.H264VideoStreamSettings;
12 import flash.media.Microphone; 12 import flash.media.Microphone;
  13 + import flash.media.MicrophoneEnhancedMode;
  14 + import flash.media.MicrophoneEnhancedOptions;
  15 + import flash.media.SoundCodec;
13 import flash.media.Video; 16 import flash.media.Video;
14 import flash.net.NetConnection; 17 import flash.net.NetConnection;
15 import flash.net.NetStream; 18 import flash.net.NetStream;
@@ -135,27 +138,31 @@ package @@ -135,27 +138,31 @@ package
135 this.js_call_stop(); 138 this.js_call_stop();
136 139
137 // microphone and camera 140 // microphone and camera
138 - var m:Microphone = Microphone.getMicrophone(acodec.device_code);  
139 - if(m == null){ 141 + var microphone:Microphone = null;
  142 + //microphone = Microphone.getEnhancedMicrophone(acodec.device_code);
  143 + if (!microphone) {
  144 + microphone = Microphone.getMicrophone(acodec.device_code);
  145 + }
  146 + if(microphone == null){
140 this.system_error(this.error_microphone_get, "failed to open microphone " + acodec.device_code + "(" + acodec.device_name + ")"); 147 this.system_error(this.error_microphone_get, "failed to open microphone " + acodec.device_code + "(" + acodec.device_name + ")");
141 return; 148 return;
142 } 149 }
143 // ignore muted, for flash will require user to access it. 150 // ignore muted, for flash will require user to access it.
144 151
145 // Remark: the name is the index! 152 // Remark: the name is the index!
146 - var c:Camera = Camera.getCamera(vcodec.device_code);  
147 - if(c == null){ 153 + var camera:Camera = Camera.getCamera(vcodec.device_code);
  154 + if(camera == null){
148 this.system_error(this.error_camera_get, "failed to open camera " + vcodec.device_code + "(" + vcodec.device_name + ")"); 155 this.system_error(this.error_camera_get, "failed to open camera " + vcodec.device_code + "(" + vcodec.device_name + ")");
149 return; 156 return;
150 } 157 }
151 // ignore muted, for flash will require user to access it. 158 // ignore muted, for flash will require user to access it.
152 // but we still warn user. 159 // but we still warn user.
153 - if(c && c.muted){ 160 + if(camera && camera.muted){
154 this.system_warn(this.error_camera_muted, "Access Denied, camera " + vcodec.device_code + "(" + vcodec.device_name + ") is muted"); 161 this.system_warn(this.error_camera_muted, "Access Denied, camera " + vcodec.device_code + "(" + vcodec.device_name + ") is muted");
155 } 162 }
156 163
157 - this.media_camera = c;  
158 - this.media_microphone = m; 164 + this.media_camera = camera;
  165 + this.media_microphone = microphone;
159 166
160 this.media_conn = new NetConnection(); 167 this.media_conn = new NetConnection();
161 this.media_conn.client = {}; 168 this.media_conn.client = {};
@@ -188,14 +195,14 @@ package @@ -188,14 +195,14 @@ package
188 // TODO: FIXME: failed event. 195 // TODO: FIXME: failed event.
189 }); 196 });
190 197
191 - __build_video_codec(media_stream, c, vcodec);  
192 - __build_audio_codec(media_stream, m, acodec); 198 + __build_video_codec(media_stream, camera, vcodec);
  199 + __build_audio_codec(media_stream, microphone, acodec);
193 200
194 if (media_microphone) { 201 if (media_microphone) {
195 - media_stream.attachAudio(m); 202 + media_stream.attachAudio(microphone);
196 } 203 }
197 if (media_camera) { 204 if (media_camera) {
198 - media_stream.attachCamera(c); 205 + media_stream.attachCamera(camera);
199 } 206 }
200 207
201 var streamName:String = url.substr(url.lastIndexOf("/")); 208 var streamName:String = url.substr(url.lastIndexOf("/"));
@@ -264,6 +271,10 @@ package @@ -264,6 +271,10 @@ package
264 // if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that 271 // if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that
265 // your sound capture device supports, usually 11 kHz. 272 // your sound capture device supports, usually 11 kHz.
266 m.rate = microRate; 273 m.rate = microRate;
  274 +
  275 + // see: http://www.adobe.com/cn/devnet/flashplayer/articles/acoustic-echo-cancellation.html
  276 + m.codec = SoundCodec.SPEEX;
  277 + m.framesPerPacket = 1;
267 } 278 }
268 private function __build_video_codec(stream:NetStream, c:Camera, vcodec:Object):void { 279 private function __build_video_codec(stream:NetStream, c:Camera, vcodec:Object):void {
269 if (!c) { 280 if (!c) {
@@ -332,9 +343,9 @@ package @@ -332,9 +343,9 @@ package
332 // (highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth, 343 // (highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth,
333 // pass 0 for quality. 344 // pass 0 for quality.
334 // winlin: 345 // winlin:
335 - // bandwidth is in bps not kbps. 500*1000 = 500kbps. 346 + // bandwidth is in Bps not kbps.
336 // quality=1 is lowest quality, 100 is highest quality. 347 // quality=1 is lowest quality, 100 is highest quality.
337 - c.setQuality(cameraBitrate * 1000, cameraQuality); 348 + c.setQuality(cameraBitrate / 8.0 * 1000, cameraQuality);
338 } 349 }
339 } 350 }
340 } 351 }
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 <script type="text/javascript" src="js/bootstrap.min.js"></script> 8 <script type="text/javascript" src="js/bootstrap.min.js"></script>
9 <script type="text/javascript" src="js/swfobject.js"></script> 9 <script type="text/javascript" src="js/swfobject.js"></script>
10 <script type="text/javascript" src="js/srs.js"></script> 10 <script type="text/javascript" src="js/srs.js"></script>
  11 + <script type="text/javascript" src="js/srs.log.js"></script>
11 <style> 12 <style>
12 body{ 13 body{
13 padding-top: 55px; 14 padding-top: 55px;