wenjiegit

update master

1 -//////////////////////////////////////////////////////////////////////////////////  
2 -//////////////////////////////////////////////////////////////////////////////////  
3 -//////////////////////////////////////////////////////////////////////////////////  
4 -  
5 -/**  
6 -* player specified size.  
7 -*/  
8 -function srs_get_player_modal() { return 740; }  
9 -function srs_get_player_width() { return srs_get_player_modal() - 30; }  
10 -function srs_get_player_height() { return srs_get_player_width() * 9 / 19; }  
11 -  
12 -// to query the swf anti cache.  
13 -function srs_get_version_code() { return "1.9"; }  
14 -// get the default vhost for players.  
15 -function srs_get_player_vhost() { return "players"; }  
16 -// the api server port, for chat room.  
17 -function srs_get_api_server_port() { return 8085; }  
18 -// get the stream published to vhost,  
19 -// generally we need to transcode the stream to support HLS and filters.  
20 -// for example, src_vhost is "players", we transcode stream to vhost "players_pub".  
21 -// if not equals to the player vhost, return the orignal vhost.  
22 -function srs_get_player_publish_vhost(src_vhost) { return (src_vhost != srs_get_player_vhost())? src_vhost:(src_vhost + "_pub"); }  
23 -// for chat, use rtmp only vhost, low latecy, without gop cache.  
24 -function srs_get_player_chat_vhost(src_vhost) { return (src_vhost != srs_get_player_vhost())? src_vhost:(src_vhost + "_pub_rtmp"); }  
25 -  
26 -//////////////////////////////////////////////////////////////////////////////////  
27 -//////////////////////////////////////////////////////////////////////////////////  
28 -//////////////////////////////////////////////////////////////////////////////////  
29 -/**  
30 -* padding the output.  
31 -* padding(3, 5, '0') is 00003  
32 -* padding(3, 5, 'x') is xxxx3  
33 -* @see http://blog.csdn.net/win_lin/article/details/12065413  
34 -*/  
35 -function padding(number, length, prefix) {  
36 - if(String(number).length >= length){  
37 - return String(number);  
38 - }  
39 - return padding(prefix+number, length, prefix);  
40 -}  
41 -  
42 -/**  
43 -* update the navigator, add same query string.  
44 -*/  
45 -function update_nav() {  
46 - $("#nav_srs_player").attr("href", "srs_player.html" + window.location.search);  
47 - $("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search);  
48 - $("#nav_srs_chat").attr("href", "srs_chat.html" + window.location.search);  
49 - $("#nav_srs_bwt").attr("href", "srs_bwt.html" + window.location.search);  
50 - $("#nav_jwplayer6").attr("href", "jwplayer6.html" + window.location.search);  
51 - $("#nav_osmf").attr("href", "osmf.html" + window.location.search);  
52 - $("#nav_vlc").attr("href", "vlc.html" + window.location.search);  
53 -}  
54 -  
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.  
82 -*/  
83 -function parse_query_string(){  
84 - var obj = {};  
85 -  
86 - // parse the host(hostname:http_port), pathname(dir/filename)  
87 - obj.host = window.location.host;  
88 - obj.hostname = window.location.hostname;  
89 - obj.http_port = (window.location.port == "")? 80:window.location.port;  
90 - obj.pathname = window.location.pathname;  
91 - if (obj.pathname.lastIndexOf("/") <= 0) {  
92 - obj.dir = "/";  
93 - obj.filename = "";  
94 - } else {  
95 - obj.dir = obj.pathname.substr(0, obj.pathname.lastIndexOf("/"));  
96 - obj.filename = obj.pathname.substr(obj.pathname.lastIndexOf("/"));  
97 - }  
98 -  
99 - // parse the query string.  
100 - var query_string = String(window.location.search).replace(" ", "").split("?")[1];  
101 - if(query_string == undefined){  
102 - return obj;  
103 - }  
104 -  
105 - var queries = query_string.split("&");  
106 - $(queries).each(function(){  
107 - var query = this.split("=");  
108 - obj[query[0]] = query[1];  
109 - });  
110 -  
111 - return obj;  
112 -}  
113 -  
114 -/**  
115 -@param server the ip of server. default to window.location.hostname  
116 -@param vhost the vhost of rtmp. default to window.location.hostname  
117 -@param port the port of rtmp. default to 1935  
118 -@param app the app of rtmp. default to live.  
119 -@param stream the stream of rtmp. default to livestream.  
120 -*/  
121 -function build_default_rtmp_url() {  
122 - var query = parse_query_string();  
123 -  
124 - var server = (query.server == undefined)? window.location.hostname:query.server;  
125 - var port = (query.port == undefined)? 1935:query.port;  
126 - var vhost = (query.vhost == undefined)? window.location.hostname:query.vhost;  
127 - var app = (query.app == undefined)? "live":query.app;  
128 - var stream = (query.stream == undefined)? "livestream":query.stream;  
129 -  
130 - if (server == vhost || vhost == "") {  
131 - return "rtmp://" + server + ":" + port + "/" + app + "/" + stream;  
132 - } else {  
133 - return "rtmp://" + server + ":" + port + "/" + app + "...vhost..." + vhost + "/" + stream;  
134 - }  
135 -}  
136 -// for the chat to init the publish url.  
137 -function build_default_publish_rtmp_url() {  
138 - var query = parse_query_string();  
139 -  
140 - var server = (query.server == undefined)? window.location.hostname:query.server;  
141 - var port = (query.port == undefined)? 1935:query.port;  
142 - var vhost = (query.vhost == undefined)? window.location.hostname:query.vhost;  
143 - var app = (query.app == undefined)? "live":query.app;  
144 - var stream = (query.stream == undefined)? "livestream":query.stream;  
145 -  
146 - if (server == vhost || vhost == "") {  
147 - return "rtmp://" + server + ":" + port + "/" + app + "/" + stream;  
148 - } else {  
149 - vhost = srs_get_player_chat_vhost(vhost);  
150 - return "rtmp://" + server + ":" + port + "/" + app + "...vhost..." + vhost + "/" + stream;  
151 - }  
152 -}  
153 -  
154 -/**  
155 -@param server the ip of server. default to window.location.hostname  
156 -@param vhost the vhost of hls. default to window.location.hostname  
157 -@param hls_vhost the vhost of hls. override the server if specified.  
158 -@param hls_port the port of hls. default to window.location.port  
159 -@param app the app of hls. default to live.  
160 -@param stream the stream of hls. default to livestream.  
161 -*/  
162 -function build_default_hls_url() {  
163 - var query = parse_query_string();  
164 -  
165 - // for http, use hls_vhost to override server if specified.  
166 - var server = window.location.hostname;  
167 - if (query.server != undefined) {  
168 - server = query.server;  
169 - } else if (query.hls_vhost != undefined) {  
170 - server = query.hls_vhost;  
171 - }  
172 -  
173 - var port = (query.hls_port == undefined)? window.location.port:query.hls_port;  
174 - var app = (query.app == undefined)? "live":query.app;  
175 - var stream = (query.stream == undefined)? "livestream":query.stream;  
176 -  
177 - if (port == "" || port == null || port == undefined) {  
178 - port = 80;  
179 - }  
180 -  
181 - return "http://" + server + ":" + port + "/" + app + "/" + stream + ".m3u8";  
182 -}  
183 -  
184 -/**  
185 -* parse the rtmp url,  
186 -* for example: rtmp://demo.srs.com:1935/live...vhost...players/livestream  
187 -* @return object {server, port, vhost, app, stream}  
188 -*/  
189 -function srs_parse_rtmp_url(rtmp_url) {  
190 - // @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri  
191 - var a = document.createElement("a");  
192 - a.href = rtmp_url.replace("rtmp://", "http://");  
193 -  
194 - var vhost = a.hostname;  
195 - var port = (a.port == "")? "1935":a.port;  
196 - var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);  
197 - var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);  
198 -  
199 - // parse the vhost in the params of app, that srs supports.  
200 - app = app.replace("...vhost...", "?vhost=");  
201 - if (app.indexOf("?") >= 0) {  
202 - var params = app.substr(app.indexOf("?"));  
203 - app = app.substr(0, app.indexOf("?"));  
204 -  
205 - if (params.indexOf("vhost=") > 0) {  
206 - vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);  
207 - if (vhost.indexOf("&") > 0) {  
208 - vhost = vhost.substr(0, vhost.indexOf("&"));  
209 - }  
210 - }  
211 - }  
212 -  
213 - var ret = {  
214 - server: a.hostname, port: port,  
215 - vhost: vhost, app: app, stream: stream  
216 - };  
217 -  
218 - return ret;  
219 -}  
220 -  
221 -/**  
222 -* initialize the page.  
223 -* @param rtmp_url the div id contains the rtmp stream url to play  
224 -* @param hls_url the div id contains the hls stream url to play  
225 -* @param modal_player the div id contains the modal player  
226 -*/  
227 -function srs_init(rtmp_url, hls_url, modal_player) {  
228 - update_nav();  
229 -  
230 - if (rtmp_url) {  
231 - $(rtmp_url).val(build_default_rtmp_url());  
232 - }  
233 - if (hls_url) {  
234 - $(hls_url).val(build_default_hls_url());  
235 - }  
236 - if (modal_player) {  
237 - $(modal_player).width(srs_get_player_modal() + "px");  
238 - $(modal_player).css("margin-left", "-" + srs_get_player_modal() / 2 +"px");  
239 - }  
240 -}  
241 -  
242 -// for the chat to init the publish url.  
243 -function srs_init_publish(rtmp_url) {  
244 - update_nav();  
245 -  
246 - if (rtmp_url) {  
247 - $(rtmp_url).val(build_default_publish_rtmp_url());  
248 - }  
249 -}  
250 -  
251 -// for bw to init url  
252 -// url: scheme://host:port/path?query#fragment  
253 -function srs_init_bwt(rtmp_url, hls_url) {  
254 - update_nav();  
255 -  
256 - if (rtmp_url) {  
257 - //var query = parse_query_string();  
258 - var search_filed = String(window.location.search).replace(" ", "").split("?")[1];  
259 - $(rtmp_url).val("rtmp://" + window.location.host + ":" + 1935 + "/app?" + search_filed);  
260 - }  
261 - if (hls_url) {  
262 - $(hls_url).val(build_default_hls_url());  
263 - }  
264 -}  
265 -  
266 -function srs_bwt_check_url(url) {  
267 - if (url.indexOf("key") != -1 && url.indexOf("vhost") != -1) {  
268 - return true;  
269 - }  
270 -  
271 - return false;  
272 -}  
273 -  
274 -function srs_bwt_build_default_url() {  
275 - var url_default = "rtmp://" + window.location.host + ":" + 1935 + "/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com";  
276 - return url_default;  
277 -}  
278 -  
279 -/**  
280 -* when publisher ready, init the page elements.  
281 -*/  
282 -function srs_publisher_initialize_page(  
283 - cameras, microphones,  
284 - sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate  
285 -) {  
286 - $(sl_cameras).empty();  
287 - for (var i = 0; i < cameras.length; i++) {  
288 - $(sl_cameras).append("<option value='" + i + "'>" + cameras[i] + "</option");  
289 - }  
290 - // optional: select the first no "virtual" signed.  
291 - for (var i = 0; i < cameras.length; i++) {  
292 - if (cameras[i].toLowerCase().indexOf("virtual") == -1) {  
293 - $(sl_cameras + " option[value='" + i + "']").attr("selected", true);  
294 - break;  
295 - }  
296 - }  
297 -  
298 - $(sl_microphones).empty();  
299 - for (var i = 0; i < microphones.length; i++) {  
300 - $(sl_microphones).append("<option value='" + i + "'>" + microphones[i] + "</option");  
301 - }  
302 -  
303 - $(sl_vcodec).empty();  
304 - var vcodecs = ["h264", "vp6"];  
305 - for (var i = 0; i < vcodecs.length; i++) {  
306 - $(sl_vcodec).append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option");  
307 - }  
308 -  
309 - $(sl_profile).empty();  
310 - var profiles = ["baseline", "main"];  
311 - for (var i = 0; i < profiles.length; i++) {  
312 - $(sl_profile).append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option");  
313 - }  
314 - $(sl_profile + " option[value='main']").attr("selected", true);  
315 -  
316 - $(sl_level).empty();  
317 - var levels = ["1", "1b", "1.1", "1.2", "1.3",  
318 - "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];  
319 - for (var i = 0; i < levels.length; i++) {  
320 - $(sl_level).append("<option value='" + levels[i] + "'>" + levels[i] + "</option");  
321 - }  
322 - $(sl_level + " option[value='4.1']").attr("selected", true);  
323 -  
324 - $(sl_gop).empty();  
325 - var gops = ["0.3", "0.5", "1", "2", "3", "4",  
326 - "5", "6", "7", "8", "9", "10", "15", "20"];  
327 - for (var i = 0; i < gops.length; i++) {  
328 - $(sl_gop).append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option");  
329 - }  
330 - $(sl_gop + " option[value='10']").attr("selected", true);  
331 -  
332 - $(sl_size).empty();  
333 - var sizes = ["176x144", "320x240", "352x240",  
334 - "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",  
335 - "1024x768", "1280x720", "1360x768", "1920x1080"];  
336 - for (i = 0; i < sizes.length; i++) {  
337 - $(sl_size).append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option");  
338 - }  
339 - $(sl_size + " option[value='640x480']").attr("selected", true);  
340 -  
341 - $(sl_fps).empty();  
342 - var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];  
343 - for (i = 0; i < fpses.length; i++) {  
344 - $(sl_fps).append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option");  
345 - }  
346 - $(sl_fps + " option[value='20']").attr("selected", true);  
347 -  
348 - $(sl_bitrate).empty();  
349 - var bitrates = ["50", "200", "350", "500", "650", "800",  
350 - "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];  
351 - for (i = 0; i < bitrates.length; i++) {  
352 - $(sl_bitrate).append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option");  
353 - }  
354 - $(sl_bitrate + " option[value='500']").attr("selected", true);  
355 -}  
356 -/**  
357 -* for chat, use low latecy settings.  
358 -*/  
359 -function srs_chat_initialize_page(  
360 - cameras, microphones,  
361 - sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate  
362 -) {  
363 - $(sl_cameras).empty();  
364 - for (var i = 0; i < cameras.length; i++) {  
365 - $(sl_cameras).append("<option value='" + i + "'>" + cameras[i] + "</option");  
366 - }  
367 - // optional: select the first no "virtual" signed.  
368 - for (var i = 0; i < cameras.length; i++) {  
369 - if (cameras[i].toLowerCase().indexOf("virtual") == -1) {  
370 - $(sl_cameras + " option[value='" + i + "']").attr("selected", true);  
371 - break;  
372 - }  
373 - }  
374 -  
375 - $(sl_microphones).empty();  
376 - for (var i = 0; i < microphones.length; i++) {  
377 - $(sl_microphones).append("<option value='" + i + "'>" + microphones[i] + "</option");  
378 - }  
379 -  
380 - $(sl_vcodec).empty();  
381 - var vcodecs = ["h264", "vp6"];  
382 - for (var i = 0; i < vcodecs.length; i++) {  
383 - $(sl_vcodec).append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option");  
384 - }  
385 -  
386 - $(sl_profile).empty();  
387 - var profiles = ["baseline", "main"];  
388 - for (var i = 0; i < profiles.length; i++) {  
389 - $(sl_profile).append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option");  
390 - }  
391 - $(sl_profile + " option[value='baseline']").attr("selected", true);  
392 -  
393 - $(sl_level).empty();  
394 - var levels = ["1", "1b", "1.1", "1.2", "1.3",  
395 - "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];  
396 - for (var i = 0; i < levels.length; i++) {  
397 - $(sl_level).append("<option value='" + levels[i] + "'>" + levels[i] + "</option");  
398 - }  
399 - $(sl_level + " option[value='3.1']").attr("selected", true);  
400 -  
401 - $(sl_gop).empty();  
402 - var gops = ["0.3", "0.5", "1", "2", "3", "4",  
403 - "5", "6", "7", "8", "9", "10", "15", "20"];  
404 - for (var i = 0; i < gops.length; i++) {  
405 - $(sl_gop).append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option");  
406 - }  
407 - $(sl_gop + " option[value='0.5']").attr("selected", true);  
408 -  
409 - $(sl_size).empty();  
410 - var sizes = ["176x144", "320x240", "352x240",  
411 - "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",  
412 - "1024x768", "1280x720", "1360x768", "1920x1080"];  
413 - for (i = 0; i < sizes.length; i++) {  
414 - $(sl_size).append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option");  
415 - }  
416 - $(sl_size + " option[value='460x240']").attr("selected", true);  
417 -  
418 - $(sl_fps).empty();  
419 - var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];  
420 - for (i = 0; i < fpses.length; i++) {  
421 - $(sl_fps).append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option");  
422 - }  
423 - $(sl_fps + " option[value='15']").attr("selected", true);  
424 -  
425 - $(sl_bitrate).empty();  
426 - var bitrates = ["50", "200", "350", "500", "650", "800",  
427 - "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];  
428 - for (i = 0; i < bitrates.length; i++) {  
429 - $(sl_bitrate).append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option");  
430 - }  
431 - $(sl_bitrate + " option[value='350']").attr("selected", true);  
432 -}  
433 -/**  
434 -* get the vcodec and acodec.  
435 -*/  
436 -function srs_publiser_get_codec(  
437 - vcodec, acodec,  
438 - sl_cameras, sl_microphones, sl_vcodec, sl_profile, sl_level, sl_gop, sl_size, sl_fps, sl_bitrate  
439 -) {  
440 - acodec.device_code = $(sl_microphones).val();  
441 - acodec.device_name = $(sl_microphones).text();  
442 -  
443 - vcodec.device_code = $(sl_cameras).find("option:selected").val();  
444 - vcodec.device_name = $(sl_cameras).find("option:selected").text();  
445 -  
446 - vcodec.codec = $(sl_vcodec).find("option:selected").val();  
447 - vcodec.profile = $(sl_profile).find("option:selected").val();  
448 - vcodec.level = $(sl_level).find("option:selected").val();  
449 - vcodec.fps = $(sl_fps).find("option:selected").val();  
450 - vcodec.gop = $(sl_gop).find("option:selected").val();  
451 - vcodec.size = $(sl_size).find("option:selected").val();  
452 - vcodec.bitrate = $(sl_bitrate).find("option:selected").val();  
453 -}  
454 -  
455 -//////////////////////////////////////////////////////////////////////////////////  
456 -//////////////////////////////////////////////////////////////////////////////////  
457 -//////////////////////////////////////////////////////////////////////////////////  
458 -/**  
459 -* the SrsPlayer object.  
460 -* @param container the html container id.  
461 -* @param width a float value specifies the width of player.  
462 -* @param height a float value specifies the height of player.  
463 -* @param private_object [optional] an object that used as private object,  
464 -* for example, the logic chat object which owner this player.  
465 -*/  
466 -function SrsPlayer(container, width, height, private_object) {  
467 - if (!SrsPlayer.__id) {  
468 - SrsPlayer.__id = 100;  
469 - }  
470 - if (!SrsPlayer.__players) {  
471 - SrsPlayer.__players = [];  
472 - }  
473 -  
474 - SrsPlayer.__players.push(this);  
475 -  
476 - this.private_object = private_object;  
477 - this.container = container;  
478 - this.width = width;  
479 - this.height = height;  
480 - this.id = SrsPlayer.__id++;  
481 - this.stream_url = null;  
482 - this.buffer_time = 0.8; // default to 0.8  
483 - this.callbackObj = null;  
484 -  
485 - // callback set the following values.  
486 - this.meatadata = {}; // for on_player_metadata  
487 - this.time = 0; // current stream time.  
488 - this.buffer_length = 0; // current stream buffer length.  
489 -}  
490 -/**  
491 -* user can set some callback, then start the player.  
492 -* @param url the default url.  
493 -* callbacks:  
494 -* on_player_ready():int, when srs player ready, user can play.  
495 -* on_player_metadata(metadata:Object):int, when srs player get metadata.  
496 -*/  
497 -SrsPlayer.prototype.start = function(url) {  
498 - if (url) {  
499 - this.stream_url = url;  
500 - }  
501 -  
502 - // embed the flash.  
503 - var flashvars = {};  
504 - flashvars.id = this.id;  
505 - flashvars.on_player_ready = "__srs_on_player_ready";  
506 - flashvars.on_player_metadata = "__srs_on_player_metadata";  
507 - flashvars.on_player_timer = "__srs_on_player_timer";  
508 -  
509 - var params = {};  
510 - params.wmode = "opaque";  
511 - params.allowFullScreen = "true";  
512 - params.allowScriptAccess = "always";  
513 -  
514 - var attributes = {};  
515 -  
516 - var self = this;  
517 -  
518 - swfobject.embedSWF(  
519 - "srs_player/release/srs_player.swf?_version="+srs_get_version_code(),  
520 - this.container,  
521 - this.width, this.height,  
522 - "11.1", "js/AdobeFlashPlayerInstall.swf",  
523 - flashvars, params, attributes,  
524 - function(callbackObj){  
525 - self.callbackObj = callbackObj;  
526 - }  
527 - );  
528 -  
529 - return this;  
530 -}  
531 -/**  
532 -* play the stream.  
533 -* @param stream_url the url of stream, rtmp or http.  
534 -*/  
535 -SrsPlayer.prototype.play = function(url) {  
536 - if (url) {  
537 - this.stream_url = url;  
538 - }  
539 - this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time);  
540 -}  
541 -SrsPlayer.prototype.stop = function() {  
542 - for (var i = 0; i < SrsPlayer.__players.length; i++) {  
543 - var player = SrsPlayer.__players[i];  
544 -  
545 - if (player.id != this.id) {  
546 - continue;  
547 - }  
548 -  
549 - SrsPlayer.__players.splice(i, 1);  
550 - break;  
551 - }  
552 -  
553 - this.callbackObj.ref.__stop();  
554 -}  
555 -SrsPlayer.prototype.pause = function() {  
556 - this.callbackObj.ref.__pause();  
557 -}  
558 -SrsPlayer.prototype.resume = function() {  
559 - this.callbackObj.ref.__resume();  
560 -}  
561 -/**  
562 -* to set the DAR, for example, DAR=16:9  
563 -* @param num, for example, 9.  
564 -* use metadata height if 0.  
565 -* use user specified height if -1.  
566 -* @param den, for example, 16.  
567 -* use metadata width if 0.  
568 -* use user specified width if -1.  
569 -*/  
570 -SrsPlayer.prototype.dar = function(num, den) {  
571 - this.callbackObj.ref.__dar(num, den);  
572 -}  
573 -/**  
574 -* set the fullscreen size data.  
575 -* @refer the refer fullscreen mode. it can be:  
576 -* video: use video orignal size.  
577 -* screen: use screen size to rescale video.  
578 -* @param percent, the rescale percent, where  
579 -* 100 means 100%.  
580 -*/  
581 -SrsPlayer.prototype.set_fs = function(refer, percent) {  
582 - this.callbackObj.ref.__set_fs(refer, percent);  
583 -}  
584 -/**  
585 -* set the stream buffer time in seconds.  
586 -* @buffer_time the buffer time in seconds.  
587 -*/  
588 -SrsPlayer.prototype.set_bt = function(buffer_time) {  
589 - this.buffer_time = buffer_time;  
590 - this.callbackObj.ref.__set_bt(buffer_time);  
591 -}  
592 -SrsPlayer.prototype.on_player_ready = function() {  
593 -}  
594 -SrsPlayer.prototype.on_player_metadata = function(metadata) {  
595 - // ignore.  
596 -}  
597 -SrsPlayer.prototype.on_player_timer = function(time, buffer_length) {  
598 - // ignore.  
599 -}  
600 -function __srs_find_player(id) {  
601 - for (var i = 0; i < SrsPlayer.__players.length; i++) {  
602 - var player = SrsPlayer.__players[i];  
603 -  
604 - if (player.id != id) {  
605 - continue;  
606 - }  
607 -  
608 - return player;  
609 - }  
610 -  
611 - throw new Error("player not found. id=" + id);  
612 -}  
613 -function __srs_on_player_ready(id) {  
614 - var player = __srs_find_player(id);  
615 - player.on_player_ready();  
616 -}  
617 -function __srs_on_player_metadata(id, metadata) {  
618 - var player = __srs_find_player(id);  
619 -  
620 - // user may override the on_player_metadata,  
621 - // so set the data before invoke it.  
622 - player.metadata = metadata;  
623 -  
624 - player.on_player_metadata(metadata);  
625 -}  
626 -function __srs_on_player_timer(id, time, buffer_length) {  
627 - var player = __srs_find_player(id);  
628 -  
629 - buffer_length = Math.max(0, buffer_length);  
630 - buffer_length = Math.min(player.buffer_time, buffer_length);  
631 -  
632 - time = Math.max(0, time);  
633 -  
634 - // user may override the on_player_timer,  
635 - // so set the data before invoke it.  
636 - player.time = time;  
637 - player.buffer_length = buffer_length;  
638 -  
639 - player.on_player_timer(time, buffer_length);  
640 -}  
641 -  
642 -//////////////////////////////////////////////////////////////////////////////////  
643 -//////////////////////////////////////////////////////////////////////////////////  
644 -//////////////////////////////////////////////////////////////////////////////////  
645 -/**  
646 -* the SrsPublisher object.  
647 -* @param container the html container id.  
648 -* @param width a float value specifies the width of publisher.  
649 -* @param height a float value specifies the height of publisher.  
650 -* @param private_object [optional] an object that used as private object,  
651 -* for example, the logic chat object which owner this publisher.  
652 -*/  
653 -function SrsPublisher(container, width, height, private_object) {  
654 - if (!SrsPublisher.__id) {  
655 - SrsPublisher.__id = 100;  
656 - }  
657 - if (!SrsPublisher.__publishers) {  
658 - SrsPublisher.__publishers = [];  
659 - }  
660 -  
661 - SrsPublisher.__publishers.push(this);  
662 -  
663 - this.private_object = private_object;  
664 - this.container = container;  
665 - this.width = width;  
666 - this.height = height;  
667 - this.id = SrsPublisher.__id++;  
668 - this.callbackObj = null;  
669 -  
670 - // set the values when publish.  
671 - this.url = null;  
672 - this.vcodec = {};  
673 - this.acodec = {};  
674 -  
675 - // callback set the following values.  
676 - this.cameras = [];  
677 - this.microphones = [];  
678 - this.code = 0;  
679 -  
680 - // error code defines.  
681 - this.errors = {  
682 - "100": "无法获取指定的摄像头", //error_camera_get  
683 - "101": "无法获取指定的麦克风", //error_microphone_get  
684 - "102": "摄像头为禁用状态,推流时请允许flash访问摄像头", //error_camera_muted  
685 - };  
686 -}  
687 -/**  
688 -* user can set some callback, then start the publisher.  
689 -* callbacks:  
690 -* on_publisher_ready(cameras, microphones):int, when srs publisher ready, user can publish.  
691 -* on_publisher_error(code, desc):int, when srs publisher error, callback this method.  
692 -* on_publisher_warn(code, desc):int, when srs publisher warn, callback this method.  
693 -*/  
694 -SrsPublisher.prototype.start = function() {  
695 - // embed the flash.  
696 - var flashvars = {};  
697 - flashvars.id = this.id;  
698 - flashvars.on_publisher_ready = "__srs_on_publisher_ready";  
699 - flashvars.on_publisher_error = "__srs_on_publisher_error";  
700 - flashvars.on_publisher_warn = "__srs_on_publisher_warn";  
701 -  
702 - var params = {};  
703 - params.wmode = "opaque";  
704 - params.allowFullScreen = "true";  
705 - params.allowScriptAccess = "always";  
706 -  
707 - var attributes = {};  
708 -  
709 - var self = this;  
710 -  
711 - swfobject.embedSWF(  
712 - "srs_publisher/release/srs_publisher.swf?_version="+srs_get_version_code(),  
713 - this.container,  
714 - this.width, this.height,  
715 - "11.1", "js/AdobeFlashPlayerInstall.swf",  
716 - flashvars, params, attributes,  
717 - function(callbackObj){  
718 - self.callbackObj = callbackObj;  
719 - }  
720 - );  
721 -  
722 - return this;  
723 -}  
724 -/**  
725 -* publish stream to server.  
726 -* @param url a string indicates the rtmp url to publish.  
727 -* @param vcodec an object contains the video codec info.  
728 -* @param acodec an object contains the audio codec info.  
729 -*/  
730 -SrsPublisher.prototype.publish = function(url, vcodec, acodec) {  
731 - this.url = url;  
732 - this.vcodec = vcodec;  
733 - this.acodec = acodec;  
734 -  
735 - this.callbackObj.ref.__publish(url, this.width, this.height, vcodec, acodec);  
736 -}  
737 -SrsPublisher.prototype.stop = function() {  
738 - this.callbackObj.ref.__stop();  
739 -}  
740 -/**  
741 -* when publisher ready.  
742 -* @param cameras a string array contains the names of cameras.  
743 -* @param microphones a string array contains the names of microphones.  
744 -*/  
745 -SrsPublisher.prototype.on_publisher_ready = function(cameras, microphones) {  
746 -}  
747 -/**  
748 -* when publisher error.  
749 -* @code the error code.  
750 -* @desc the error desc message.  
751 -*/  
752 -SrsPublisher.prototype.on_publisher_error = function(code, desc) {  
753 - throw new Error("publisher error. code=" + code + ", desc=" + desc);  
754 -}  
755 -SrsPublisher.prototype.on_publisher_warn = function(code, desc) {  
756 - throw new Error("publisher warn. code=" + code + ", desc=" + desc);  
757 -}  
758 -function __srs_find_publisher(id) {  
759 - for (var i = 0; i < SrsPublisher.__publishers.length; i++) {  
760 - var publisher = SrsPublisher.__publishers[i];  
761 -  
762 - if (publisher.id != id) {  
763 - continue;  
764 - }  
765 -  
766 - return publisher;  
767 - }  
768 -  
769 - throw new Error("publisher not found. id=" + id);  
770 -}  
771 -function __srs_on_publisher_ready(id, cameras, microphones) {  
772 - var publisher = __srs_find_publisher(id);  
773 -  
774 - publisher.cameras = cameras;  
775 - publisher.microphones = microphones;  
776 -  
777 - publisher.on_publisher_ready(cameras, microphones);  
778 -}  
779 -function __srs_on_publisher_error(id, code) {  
780 - var publisher = __srs_find_publisher(id);  
781 -  
782 - publisher.code = code;  
783 -  
784 - publisher.on_publisher_error(code, publisher.errors[""+code]);  
785 -}  
786 -function __srs_on_publisher_warn(id, code) {  
787 - var publisher = __srs_find_publisher(id);  
788 -  
789 - publisher.code = code;  
790 -  
791 - publisher.on_publisher_warn(code, publisher.errors[""+code]);  
792 -}  
793 -