正在显示
5 个修改的文件
包含
485 行增加
和
225 行删除
trunk/research/players/img/tooltip.png
0 → 100644
783 字节
1 | +/** | ||
2 | +* update the navigator, add same query string. | ||
3 | +*/ | ||
1 | function update_nav() { | 4 | function update_nav() { |
2 | $("#nav_srs_player").attr("href", "srs_player.html" + window.location.search); | 5 | $("#nav_srs_player").attr("href", "srs_player.html" + window.location.search); |
3 | $("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search); | 6 | $("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search); |
@@ -7,6 +10,9 @@ function update_nav() { | @@ -7,6 +10,9 @@ function update_nav() { | ||
7 | $("#nav_vlc").attr("href", "vlc.html" + window.location.search); | 10 | $("#nav_vlc").attr("href", "vlc.html" + window.location.search); |
8 | } | 11 | } |
9 | 12 | ||
13 | +/** | ||
14 | +* parse the query string to object. | ||
15 | +*/ | ||
10 | function parse_query_string(){ | 16 | function parse_query_string(){ |
11 | var query_string = String(window.location.search).replace(" ", "").split("?")[1]; | 17 | var query_string = String(window.location.search).replace(" ", "").split("?")[1]; |
12 | if(query_string == undefined){ | 18 | if(query_string == undefined){ |
@@ -60,6 +66,11 @@ function build_default_hls_url() { | @@ -60,6 +66,11 @@ function build_default_hls_url() { | ||
60 | return "http://" + vhost + ":" + port + "/" + app + "/" + stream + ".m3u8"; | 66 | return "http://" + vhost + ":" + port + "/" + app + "/" + stream + ".m3u8"; |
61 | } | 67 | } |
62 | 68 | ||
69 | +/** | ||
70 | +* initialize the page. | ||
71 | +* @param rtmp_url the rtmp stream url to play | ||
72 | +* @param hls_url the hls stream url to play | ||
73 | +*/ | ||
63 | function srs_init(rtmp_url, hls_url) { | 74 | function srs_init(rtmp_url, hls_url) { |
64 | update_nav(); | 75 | update_nav(); |
65 | 76 | ||
@@ -70,3 +81,146 @@ function srs_init(rtmp_url, hls_url) { | @@ -70,3 +81,146 @@ function srs_init(rtmp_url, hls_url) { | ||
70 | $(hls_url).val(build_default_hls_url()); | 81 | $(hls_url).val(build_default_hls_url()); |
71 | } | 82 | } |
72 | } | 83 | } |
84 | + | ||
85 | +////////////////////////////////////////////////////////////////////////////////// | ||
86 | +////////////////////////////////////////////////////////////////////////////////// | ||
87 | +////////////////////////////////////////////////////////////////////////////////// | ||
88 | +/** | ||
89 | +* the SrsPlayer object. | ||
90 | +*/ | ||
91 | +function SrsPlayer(container, stream_url, width, height, buffer_time) { | ||
92 | + if (!SrsPlayer.__id) { | ||
93 | + SrsPlayer.__id = 100; | ||
94 | + } | ||
95 | + if (!SrsPlayer.__players) { | ||
96 | + SrsPlayer.__players = []; | ||
97 | + } | ||
98 | + | ||
99 | + SrsPlayer.__players.push(this); | ||
100 | + | ||
101 | + this.container = container; | ||
102 | + this.stream_url = stream_url; | ||
103 | + this.width = width; | ||
104 | + this.height = height; | ||
105 | + this.buffer_time = buffer_time; | ||
106 | + this.id = SrsPlayer.__id++; | ||
107 | + this.callbackObj = null; | ||
108 | + | ||
109 | + // callback set the following values. | ||
110 | + this.meatadata = {}; // for on_player_metadata | ||
111 | +} | ||
112 | +/** | ||
113 | +* user can set some callback, then start the player. | ||
114 | +* callbacks: | ||
115 | +* on_player_ready():int, when srs player ready, user can play. | ||
116 | +* on_player_metadata(metadata:Object):int, when srs player get metadata. | ||
117 | +*/ | ||
118 | +SrsPlayer.prototype.start = function() { | ||
119 | + // embed the flash. | ||
120 | + var flashvars = {}; | ||
121 | + flashvars.id = this.id; | ||
122 | + flashvars.on_player_ready = "__srs_on_player_ready"; | ||
123 | + flashvars.on_player_metadata = "__srs_on_player_metadata"; | ||
124 | + | ||
125 | + var params = {}; | ||
126 | + params.wmode = "opaque"; | ||
127 | + params.allowFullScreen = "true"; | ||
128 | + params.allowScriptAccess = "always"; | ||
129 | + | ||
130 | + var attributes = {}; | ||
131 | + | ||
132 | + var self = this; | ||
133 | + | ||
134 | + swfobject.embedSWF( | ||
135 | + "srs_player/release/srs_player.swf", this.container, | ||
136 | + this.width, this.height, | ||
137 | + "11.1", "js/AdobeFlashPlayerInstall.swf", | ||
138 | + flashvars, params, attributes, | ||
139 | + function(callbackObj){ | ||
140 | + self.callbackObj = callbackObj; | ||
141 | + } | ||
142 | + ); | ||
143 | + | ||
144 | + return this; | ||
145 | +} | ||
146 | +SrsPlayer.prototype.play = function() { | ||
147 | + return this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time); | ||
148 | +} | ||
149 | +SrsPlayer.prototype.stop = function() { | ||
150 | + for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
151 | + var player = SrsPlayer.__players[i]; | ||
152 | + | ||
153 | + if (player.id != this.id) { | ||
154 | + continue; | ||
155 | + } | ||
156 | + | ||
157 | + SrsPlayer.__players.splice(i, 1); | ||
158 | + break; | ||
159 | + } | ||
160 | + return this.callbackObj.ref.__stop(); | ||
161 | +} | ||
162 | +SrsPlayer.prototype.pause = function() { | ||
163 | + return this.callbackObj.ref.__pause(); | ||
164 | +} | ||
165 | +SrsPlayer.prototype.resume = function() { | ||
166 | + return this.callbackObj.ref.__resume(); | ||
167 | +} | ||
168 | +/** | ||
169 | +* to set the DAR, for example, DAR=16:9 | ||
170 | +* @param num, for example, 9. | ||
171 | +* use metadata height if 0. | ||
172 | +* use user specified height if -1. | ||
173 | +* @param den, for example, 16. | ||
174 | +* use metadata width if 0. | ||
175 | +* use user specified width if -1. | ||
176 | +*/ | ||
177 | +SrsPlayer.prototype.dar = function(num, den) { | ||
178 | + return this.callbackObj.ref.__dar(num, den); | ||
179 | +} | ||
180 | +/** | ||
181 | +* set the fullscreen size data. | ||
182 | +* @refer the refer fullscreen mode. it can be: | ||
183 | +* video: use video orignal size. | ||
184 | +* screen: use screen size to rescale video. | ||
185 | +* @param percent, the rescale percent, where | ||
186 | +* 100 means 100%. | ||
187 | +*/ | ||
188 | +SrsPlayer.prototype.set_fs = function(refer, percent) { | ||
189 | + return this.callbackObj.ref.__set_fs(refer, percent); | ||
190 | +} | ||
191 | +SrsPlayer.prototype.on_player_ready = function() { | ||
192 | + return this.play(); | ||
193 | +} | ||
194 | +SrsPlayer.prototype.on_player_metadata = function(metadata) { | ||
195 | + return 0; | ||
196 | +} | ||
197 | +function __srs_on_player_ready(id) { | ||
198 | + for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
199 | + var player = SrsPlayer.__players[i]; | ||
200 | + | ||
201 | + if (player.id != id) { | ||
202 | + continue; | ||
203 | + } | ||
204 | + | ||
205 | + return player.on_player_ready(); | ||
206 | + } | ||
207 | + | ||
208 | + throw new Error("player not found. id=" + id); | ||
209 | +} | ||
210 | +function __srs_on_player_metadata(id, metadata) { | ||
211 | + for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
212 | + var player = SrsPlayer.__players[i]; | ||
213 | + | ||
214 | + if (player.id != id) { | ||
215 | + continue; | ||
216 | + } | ||
217 | + | ||
218 | + // user may override the on_player_metadata, | ||
219 | + // so set the data before invoke it. | ||
220 | + player.metadata = metadata; | ||
221 | + | ||
222 | + return player.on_player_metadata(metadata); | ||
223 | + } | ||
224 | + | ||
225 | + throw new Error("player not found. id=" + id); | ||
226 | +} |
@@ -14,13 +14,30 @@ | @@ -14,13 +14,30 @@ | ||
14 | } | 14 | } |
15 | </style> | 15 | </style> |
16 | <script type="text/javascript"> | 16 | <script type="text/javascript"> |
17 | - var active_dar = null; | ||
18 | - function select_dar(dar_id) { | ||
19 | - if (active_dar) { | ||
20 | - active_dar.removeClass("active"); | 17 | + var srs_player = null; |
18 | + | ||
19 | + var __active_dar = null; | ||
20 | + function select_dar(dar_id, num, den) { | ||
21 | + srs_player.dar(num, den); | ||
22 | + | ||
23 | + if (__active_dar) { | ||
24 | + __active_dar.removeClass("active"); | ||
21 | } | 25 | } |
22 | - active_dar = $(dar_id).parent(); | ||
23 | - active_dar.addClass("active"); | 26 | + |
27 | + __active_dar = $(dar_id).parent(); | ||
28 | + __active_dar.addClass("active"); | ||
29 | + } | ||
30 | + | ||
31 | + var __active_size = null; | ||
32 | + function select_fs_size(size_id, refer, percent) { | ||
33 | + srs_player.set_fs(refer, percent); | ||
34 | + | ||
35 | + if (__active_size) { | ||
36 | + __active_size.removeClass("active"); | ||
37 | + } | ||
38 | + | ||
39 | + __active_size = $(size_id).parent(); | ||
40 | + __active_size.addClass("active"); | ||
24 | } | 41 | } |
25 | 42 | ||
26 | $(function(){ | 43 | $(function(){ |
@@ -29,9 +46,15 @@ | @@ -29,9 +46,15 @@ | ||
29 | // url set to: rtmp://demo:1935/live/livestream | 46 | // url set to: rtmp://demo:1935/live/livestream |
30 | srs_init($("#txt_url")); | 47 | srs_init($("#txt_url")); |
31 | 48 | ||
32 | - var srs_player = null; | ||
33 | - | 49 | + $("#fs_tips").tooltip({ |
50 | + title: "点击视频进入或退出全屏" | ||
51 | + }); | ||
52 | + | ||
34 | $("#main_modal").on("show", function(){ | 53 | $("#main_modal").on("show", function(){ |
54 | + if (srs_player) { | ||
55 | + return; | ||
56 | + } | ||
57 | + | ||
35 | $("#div_container").remove(); | 58 | $("#div_container").remove(); |
36 | 59 | ||
37 | var obj = $("<div/>"); | 60 | var obj = $("<div/>"); |
@@ -51,16 +74,22 @@ | @@ -51,16 +74,22 @@ | ||
51 | } | 74 | } |
52 | srs_player.on_player_metadata = function(metadata) { | 75 | srs_player.on_player_metadata = function(metadata) { |
53 | $("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")"); | 76 | $("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")"); |
54 | - srs_player.dar(0, 0); | ||
55 | - select_dar("#btn_dar_original"); | ||
56 | - | 77 | + select_dar("#btn_dar_original", 0, 0); |
78 | + select_fs_size("#btn_fs_size_screen_100", "screen", 100); | ||
57 | return 0; | 79 | return 0; |
58 | } | 80 | } |
59 | srs_player.start(); | 81 | srs_player.start(); |
60 | }); | 82 | }); |
61 | 83 | ||
62 | $("#main_modal").on("hide", function(){ | 84 | $("#main_modal").on("hide", function(){ |
63 | - srs_player.stop(); | 85 | + if ($("#main_modal").is(":visible")) { |
86 | + return; | ||
87 | + } | ||
88 | + | ||
89 | + if (srs_player) { | ||
90 | + srs_player.stop(); | ||
91 | + srs_player = null; | ||
92 | + } | ||
64 | }); | 93 | }); |
65 | 94 | ||
66 | $("#btn_play").click(function(){ | 95 | $("#btn_play").click(function(){ |
@@ -68,177 +97,54 @@ | @@ -68,177 +97,54 @@ | ||
68 | }); | 97 | }); |
69 | 98 | ||
70 | $("#btn_pause").click(function(){ | 99 | $("#btn_pause").click(function(){ |
71 | - if ($("#btn_pause").text() == "暂停") { | ||
72 | - $("#btn_pause").text("继续"); | 100 | + if ($("#btn_pause").text() == "暂停播放") { |
101 | + $("#btn_pause").text("继续播放"); | ||
73 | srs_player.pause(); | 102 | srs_player.pause(); |
74 | } else { | 103 | } else { |
75 | - $("#btn_pause").text("暂停"); | 104 | + $("#btn_pause").text("暂停播放"); |
76 | srs_player.resume(); | 105 | srs_player.resume(); |
77 | } | 106 | } |
78 | }); | 107 | }); |
79 | 108 | ||
80 | - $("#btn_dar_original").click(function(){ | ||
81 | - srs_player.dar(0, 0); | ||
82 | - select_dar("#btn_dar_original"); | ||
83 | - }); | ||
84 | - $("#btn_dar_21_9").click(function(){ | ||
85 | - srs_player.dar(9, 21); | ||
86 | - select_dar("#btn_dar_21_9"); | ||
87 | - }); | ||
88 | - $("#btn_dar_16_9").click(function(){ | ||
89 | - srs_player.dar(9, 16); | ||
90 | - select_dar("#btn_dar_16_9"); | ||
91 | - }); | ||
92 | - $("#btn_dar_4_3").click(function(){ | ||
93 | - srs_player.dar(3, 4); | ||
94 | - select_dar("#btn_dar_4_3"); | ||
95 | - }); | ||
96 | - $("#btn_dar_fill").click(function(){ | ||
97 | - srs_player.dar(-1, -1); | ||
98 | - select_dar("#btn_dar_fill"); | ||
99 | - }); | ||
100 | - }); | ||
101 | - | ||
102 | - /* | ||
103 | - * the SrsPlayer object. | ||
104 | - */ | ||
105 | - function SrsPlayer(container, stream_url, width, height, buffer_time) { | ||
106 | - if (!SrsPlayer.__id) { | ||
107 | - SrsPlayer.__id = 100; | ||
108 | - } | ||
109 | - if (!SrsPlayer.__players) { | ||
110 | - SrsPlayer.__players = []; | ||
111 | - } | ||
112 | - | ||
113 | - SrsPlayer.__players.push(this); | ||
114 | - | ||
115 | - this.container = container; | ||
116 | - this.stream_url = stream_url; | ||
117 | - this.width = width; | ||
118 | - this.height = height; | ||
119 | - this.buffer_time = buffer_time; | ||
120 | - this.id = SrsPlayer.__id++; | ||
121 | - this.callbackObj = null; | ||
122 | - | ||
123 | - // callback set the following values. | ||
124 | - this.meatadata = {}; // for on_player_metadata | ||
125 | - } | ||
126 | - /* | ||
127 | - * user can set some callback, then start the player. | ||
128 | - * callbacks: | ||
129 | - * on_player_ready():int, when srs player ready, user can play. | ||
130 | - * on_player_metadata(metadata:Object):int, when srs player get metadata. | ||
131 | - */ | ||
132 | - SrsPlayer.prototype.start = function() { | ||
133 | - // embed the flash. | ||
134 | - var flashvars = {}; | ||
135 | - flashvars.id = this.id; | ||
136 | - flashvars.on_player_ready = "__srs_on_player_ready"; | ||
137 | - flashvars.on_player_metadata = "__srs_on_player_metadata"; | ||
138 | - | ||
139 | - var params = {}; | ||
140 | - params.wmode = "opaque"; | ||
141 | - params.allowFullScreen = true; | ||
142 | - params.allowScriptAccess = "always"; | ||
143 | - | ||
144 | - var attributes = {}; | ||
145 | - | ||
146 | - var self = this; | ||
147 | - | ||
148 | - swfobject.embedSWF( | ||
149 | - "srs_player/release/srs_player.swf", this.container, | ||
150 | - this.width, this.height, | ||
151 | - "11.1", "js/AdobeFlashPlayerInstall.swf", | ||
152 | - flashvars, params, attributes, | ||
153 | - function(callbackObj){ | ||
154 | - self.callbackObj = callbackObj; | ||
155 | - } | ||
156 | - ); | ||
157 | - | ||
158 | - return this; | ||
159 | - } | ||
160 | - SrsPlayer.prototype.play = function() { | ||
161 | - return this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time); | ||
162 | - } | ||
163 | - SrsPlayer.prototype.stop = function() { | ||
164 | - for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
165 | - var player = SrsPlayer.__players[i]; | ||
166 | - | ||
167 | - if (player.id != this.id) { | ||
168 | - continue; | ||
169 | - } | ||
170 | - | ||
171 | - SrsPlayer.__players.splice(i, 1); | ||
172 | - break; | ||
173 | - } | ||
174 | - return this.callbackObj.ref.__stop(); | ||
175 | - } | ||
176 | - SrsPlayer.prototype.pause = function() { | ||
177 | - return this.callbackObj.ref.__pause(); | ||
178 | - } | ||
179 | - SrsPlayer.prototype.resume = function() { | ||
180 | - return this.callbackObj.ref.__resume(); | ||
181 | - } | ||
182 | - /* | ||
183 | - * to set the DAR, for example, DAR=16:9 | ||
184 | - * @param num, for example, 9. | ||
185 | - * use metadata height if 0. | ||
186 | - * use user specified height if -1. | ||
187 | - * @param den, for example, 16. | ||
188 | - * use metadata width if 0. | ||
189 | - * use user specified width if -1. | ||
190 | - */ | ||
191 | - SrsPlayer.prototype.dar = function(num, den) { | ||
192 | - if (num == 0 && this.metadata) { | ||
193 | - num = this.metadata.height; | ||
194 | - } else if (num == -1) { | ||
195 | - num = this.height; | 109 | + if (true) { |
110 | + $("#btn_dar_original").click(function(){ | ||
111 | + select_dar("#btn_dar_original", 0, 0); | ||
112 | + }); | ||
113 | + $("#btn_dar_21_9").click(function(){ | ||
114 | + select_dar("#btn_dar_21_9", 9, 21); | ||
115 | + }); | ||
116 | + $("#btn_dar_16_9").click(function(){ | ||
117 | + select_dar("#btn_dar_16_9", 9, 16); | ||
118 | + }); | ||
119 | + $("#btn_dar_4_3").click(function(){ | ||
120 | + select_dar("#btn_dar_4_3", 3, 4); | ||
121 | + }); | ||
122 | + $("#btn_dar_fill").click(function(){ | ||
123 | + select_dar("#btn_dar_fill", -1, -1); | ||
124 | + }); | ||
196 | } | 125 | } |
197 | 126 | ||
198 | - if (den == 0 && this.metadata) { | ||
199 | - den = this.metadata.width; | ||
200 | - } else if (den == -1) { | ||
201 | - den = this.width; | 127 | + if (true) { |
128 | + $("#btn_fs_size_video_100").click(function(){ | ||
129 | + select_fs_size("#btn_fs_size_video_100", "video", 100); | ||
130 | + }); | ||
131 | + $("#btn_fs_size_video_75").click(function(){ | ||
132 | + select_fs_size("#btn_fs_size_video_75", "video", 75); | ||
133 | + }); | ||
134 | + $("#btn_fs_size_video_50").click(function(){ | ||
135 | + select_fs_size("#btn_fs_size_video_50", "video", 50); | ||
136 | + }); | ||
137 | + $("#btn_fs_size_screen_100").click(function(){ | ||
138 | + select_fs_size("#btn_fs_size_screen_100", "screen", 100); | ||
139 | + }); | ||
140 | + $("#btn_fs_size_screen_75").click(function(){ | ||
141 | + select_fs_size("#btn_fs_size_screen_75", "screen", 75); | ||
142 | + }); | ||
143 | + $("#btn_fs_size_screen_50").click(function(){ | ||
144 | + select_fs_size("#btn_fs_size_screen_50", "screen", 50); | ||
145 | + }); | ||
202 | } | 146 | } |
203 | - | ||
204 | - return this.callbackObj.ref.__dar(num, den); | ||
205 | - } | ||
206 | - SrsPlayer.prototype.on_player_ready = function() { | ||
207 | - return this.play(); | ||
208 | - } | ||
209 | - SrsPlayer.prototype.on_player_metadata = function(metadata) { | ||
210 | - return 0; | ||
211 | - } | ||
212 | - function __srs_on_player_ready(id) { | ||
213 | - for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
214 | - var player = SrsPlayer.__players[i]; | ||
215 | - | ||
216 | - if (player.id != id) { | ||
217 | - continue; | ||
218 | - } | ||
219 | - | ||
220 | - return player.on_player_ready(); | ||
221 | - } | ||
222 | - | ||
223 | - throw new Error("player not found. id=" + id); | ||
224 | - } | ||
225 | - function __srs_on_player_metadata(id, metadata) { | ||
226 | - for (var i = 0; i < SrsPlayer.__players.length; i++) { | ||
227 | - var player = SrsPlayer.__players[i]; | ||
228 | - | ||
229 | - if (player.id != id) { | ||
230 | - continue; | ||
231 | - } | ||
232 | - | ||
233 | - // user may override the on_player_metadata, | ||
234 | - // so set the data before invoke it. | ||
235 | - player.metadata = metadata; | ||
236 | - | ||
237 | - return player.on_player_metadata(metadata); | ||
238 | - } | ||
239 | - | ||
240 | - throw new Error("player not found. id=" + id); | ||
241 | - } | 147 | + }); |
242 | </script> | 148 | </script> |
243 | </head> | 149 | </head> |
244 | <body> | 150 | <body> |
@@ -278,17 +184,37 @@ | @@ -278,17 +184,37 @@ | ||
278 | </div> | 184 | </div> |
279 | <div class="modal-footer"> | 185 | <div class="modal-footer"> |
280 | <div class="btn-group dropup"> | 186 | <div class="btn-group dropup"> |
281 | - <button class="btn dropdown-toggle" data-toggle="dropdown">宽高比 <span class="caret"></span></button> | 187 | + <button class="btn dropdown-toggle" data-toggle="dropdown"> |
188 | + <a id="fs_tips" href="#" data-toggle="tooltip" data-placement="top" title=""> | ||
189 | + <img src="img/tooltip.png"/> | ||
190 | + </a> | ||
191 | + 全屏大小<span class="caret"></span> | ||
192 | + </button> | ||
193 | + <ul class="dropdown-menu"> | ||
194 | + <li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li> | ||
195 | + <li><a id="btn_fs_size_screen_75" href="#">屏幕大小(75%)</a></li> | ||
196 | + <li><a id="btn_fs_size_screen_50" href="#">屏幕大小(50%)</a></li> | ||
197 | + <li><a id="btn_fs_size_video_100" href="#">视频大小(100%)</a></li> | ||
198 | + <li><a id="btn_fs_size_video_75" href="#">视频大小(75%)</a></li> | ||
199 | + <li><a id="btn_fs_size_video_50" href="#">视频大小(50%)</a></li> | ||
200 | + </ul> | ||
201 | + </div> | ||
202 | + <div class="btn-group dropup"> | ||
203 | + <button class="btn dropdown-toggle" data-toggle="dropdown">显示比例<span class="caret"></span></button> | ||
282 | <ul class="dropdown-menu"> | 204 | <ul class="dropdown-menu"> |
283 | <li><a id="btn_dar_original" href="#">视频原始比例</a></li> | 205 | <li><a id="btn_dar_original" href="#">视频原始比例</a></li> |
284 | <li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li> | 206 | <li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li> |
285 | <li><a id="btn_dar_16_9" href="#">宽屏电影(16:9)</a></li> | 207 | <li><a id="btn_dar_16_9" href="#">宽屏电影(16:9)</a></li> |
286 | <li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li> | 208 | <li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li> |
287 | - <li><a id="btn_dar_fill" href="#">填充</a></li> | 209 | + <li><a id="btn_dar_fill" href="#">填充(容器比例)</a></li> |
288 | </ul> | 210 | </ul> |
289 | </div> | 211 | </div> |
290 | - <button id="btn_pause" class="btn">暂停</button> | ||
291 | - <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭</button> | 212 | + <div class="btn-group dropup"> |
213 | + <button id="btn_pause" class="btn">暂停播放</button> | ||
214 | + </div> | ||
215 | + <div class="btn-group dropup"> | ||
216 | + <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭</button> | ||
217 | + </div> | ||
292 | </div> | 218 | </div> |
293 | </div> | 219 | </div> |
294 | <hr> | 220 | <hr> |
@@ -2,13 +2,17 @@ package | @@ -2,13 +2,17 @@ package | ||
2 | { | 2 | { |
3 | import flash.display.Sprite; | 3 | import flash.display.Sprite; |
4 | import flash.display.StageAlign; | 4 | import flash.display.StageAlign; |
5 | + import flash.display.StageDisplayState; | ||
5 | import flash.display.StageScaleMode; | 6 | import flash.display.StageScaleMode; |
6 | import flash.events.Event; | 7 | import flash.events.Event; |
8 | + import flash.events.FullScreenEvent; | ||
9 | + import flash.events.MouseEvent; | ||
7 | import flash.events.NetStatusEvent; | 10 | import flash.events.NetStatusEvent; |
8 | import flash.external.ExternalInterface; | 11 | import flash.external.ExternalInterface; |
9 | import flash.media.Video; | 12 | import flash.media.Video; |
10 | import flash.net.NetConnection; | 13 | import flash.net.NetConnection; |
11 | import flash.net.NetStream; | 14 | import flash.net.NetStream; |
15 | + import flash.system.Security; | ||
12 | import flash.ui.ContextMenu; | 16 | import flash.ui.ContextMenu; |
13 | import flash.ui.ContextMenuItem; | 17 | import flash.ui.ContextMenuItem; |
14 | import flash.utils.setTimeout; | 18 | import flash.utils.setTimeout; |
@@ -23,18 +27,29 @@ package | @@ -23,18 +27,29 @@ package | ||
23 | 27 | ||
24 | // play param url. | 28 | // play param url. |
25 | private var url:String = null; | 29 | private var url:String = null; |
26 | - // play param, user set width | 30 | + // play param, user set width and height |
27 | private var w:int = 0; | 31 | private var w:int = 0; |
28 | - // play param, user set height. | ||
29 | private var h:int = 0; | 32 | private var h:int = 0; |
33 | + // user set dar den:num | ||
34 | + private var dar_num:int = 0; | ||
35 | + private var dar_den:int = 0; | ||
36 | + // user set fs(fullscreen) refer and percent. | ||
37 | + private var fs_refer:String = null; | ||
38 | + private var fs_percent:int = 0; | ||
30 | 39 | ||
31 | private var conn:NetConnection = null; | 40 | private var conn:NetConnection = null; |
32 | private var stream:NetStream = null; | 41 | private var stream:NetStream = null; |
33 | private var video:Video = null; | 42 | private var video:Video = null; |
34 | private var metadata:Object = {}; | 43 | private var metadata:Object = {}; |
35 | 44 | ||
45 | + // flash donot allow js to set to fullscreen, | ||
46 | + // only allow user click to enter fullscreen. | ||
47 | + private var fs_mask:Sprite = new Sprite(); | ||
48 | + | ||
36 | public function srs_player() | 49 | public function srs_player() |
37 | { | 50 | { |
51 | + flash.system.Security.allowDomain("*"); | ||
52 | + | ||
38 | if (!this.stage) { | 53 | if (!this.stage) { |
39 | this.addEventListener(Event.ADDED_TO_STAGE, this.onAddToStage); | 54 | this.addEventListener(Event.ADDED_TO_STAGE, this.onAddToStage); |
40 | } else { | 55 | } else { |
@@ -46,6 +61,12 @@ package | @@ -46,6 +61,12 @@ package | ||
46 | this.stage.align = StageAlign.TOP_LEFT; | 61 | this.stage.align = StageAlign.TOP_LEFT; |
47 | this.stage.scaleMode = StageScaleMode.NO_SCALE; | 62 | this.stage.scaleMode = StageScaleMode.NO_SCALE; |
48 | 63 | ||
64 | + this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, this.on_stage_fullscreen); | ||
65 | + | ||
66 | + this.addChild(this.fs_mask); | ||
67 | + this.fs_mask.buttonMode = true; | ||
68 | + this.fs_mask.addEventListener(MouseEvent.CLICK, on_user_click_video); | ||
69 | + | ||
49 | this.contextMenu = new ContextMenu(); | 70 | this.contextMenu = new ContextMenu(); |
50 | this.contextMenu.hideBuiltInItems(); | 71 | this.contextMenu.hideBuiltInItems(); |
51 | 72 | ||
@@ -62,13 +83,21 @@ package | @@ -62,13 +83,21 @@ package | ||
62 | this.on_player_ready = flashvars.on_player_ready; | 83 | this.on_player_ready = flashvars.on_player_ready; |
63 | this.on_player_metadata = flashvars.on_player_metadata; | 84 | this.on_player_metadata = flashvars.on_player_metadata; |
64 | 85 | ||
65 | - flash.utils.setTimeout(this.onJsReady, 0); | 86 | + flash.utils.setTimeout(this.on_js_ready, 0); |
66 | } | 87 | } |
67 | 88 | ||
68 | - private function onJsReady():void { | 89 | + private function on_stage_fullscreen(evt:FullScreenEvent):void { |
90 | + if (!evt.fullScreen) { | ||
91 | + execute_user_set_dar(); | ||
92 | + } else { | ||
93 | + execute_user_enter_fullscreen(); | ||
94 | + } | ||
95 | + } | ||
96 | + | ||
97 | + private function on_js_ready():void { | ||
69 | if (!flash.external.ExternalInterface.available) { | 98 | if (!flash.external.ExternalInterface.available) { |
70 | trace("js not ready, try later."); | 99 | trace("js not ready, try later."); |
71 | - flash.utils.setTimeout(this.onJsReady, 100); | 100 | + flash.utils.setTimeout(this.on_js_ready, 100); |
72 | return; | 101 | return; |
73 | } | 102 | } |
74 | 103 | ||
@@ -77,6 +106,7 @@ package | @@ -77,6 +106,7 @@ package | ||
77 | flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause); | 106 | flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause); |
78 | flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume); | 107 | flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume); |
79 | flash.external.ExternalInterface.addCallback("__dar", this.js_call_dar); | 108 | flash.external.ExternalInterface.addCallback("__dar", this.js_call_dar); |
109 | + flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size); | ||
80 | 110 | ||
81 | var code:int = flash.external.ExternalInterface.call(this.on_player_ready, this.id); | 111 | var code:int = flash.external.ExternalInterface.call(this.on_player_ready, this.id); |
82 | if (code != 0) { | 112 | if (code != 0) { |
@@ -84,14 +114,14 @@ package | @@ -84,14 +114,14 @@ package | ||
84 | } | 114 | } |
85 | } | 115 | } |
86 | 116 | ||
87 | - public function js_call_pause():int { | 117 | + private function js_call_pause():int { |
88 | if (this.stream) { | 118 | if (this.stream) { |
89 | this.stream.pause(); | 119 | this.stream.pause(); |
90 | } | 120 | } |
91 | return 0; | 121 | return 0; |
92 | } | 122 | } |
93 | 123 | ||
94 | - public function js_call_resume():int { | 124 | + private function js_call_resume():int { |
95 | if (this.stream) { | 125 | if (this.stream) { |
96 | this.stream.resume(); | 126 | this.stream.resume(); |
97 | } | 127 | } |
@@ -99,34 +129,54 @@ package | @@ -99,34 +129,54 @@ package | ||
99 | } | 129 | } |
100 | 130 | ||
101 | /** | 131 | /** |
102 | - * to set the DAR, for example, DAR=16:9 | ||
103 | - * @param num, for example, 9. | ||
104 | - * @param den, for example, 16. | 132 | + * to set the DAR, for example, DAR=16:9 |
133 | + * @param num, for example, 9. | ||
134 | + * use metadata height if 0. | ||
135 | + * use user specified height if -1. | ||
136 | + * @param den, for example, 16. | ||
137 | + * use metadata width if 0. | ||
138 | + * use user specified width if -1. | ||
139 | + */ | ||
140 | + private function js_call_dar(num:int, den:int):int { | ||
141 | + dar_num = num; | ||
142 | + dar_den = den; | ||
143 | + | ||
144 | + flash.utils.setTimeout(execute_user_set_dar, 0); | ||
145 | + return 0; | ||
146 | + } | ||
147 | + | ||
148 | + /** | ||
149 | + * set the fullscreen size data. | ||
150 | + * @refer the refer fullscreen mode. it can be: | ||
151 | + * video: use video orignal size. | ||
152 | + * screen: use screen size to rescale video. | ||
153 | + * @param percent, the rescale percent, where | ||
154 | + * 100 means 100%. | ||
155 | + */ | ||
156 | + private function js_call_set_fs_size(refer:String, percent:int):int { | ||
157 | + fs_refer = refer; | ||
158 | + fs_percent = percent; | ||
159 | + | ||
160 | + return 0; | ||
161 | + } | ||
162 | + /** | ||
163 | + * js cannot enter the fullscreen mode, user must click to. | ||
105 | */ | 164 | */ |
106 | - public function js_call_dar(num:int, den:int):int { | ||
107 | - if (this.video && num > 0 && den > 0 && this.video.width > 0) { | ||
108 | - // set DAR. | ||
109 | - // calc the height by DAR | ||
110 | - var _height:int = this.w * num / den; | ||
111 | - if (_height <= this.h) { | ||
112 | - this.video.width = this.w; | ||
113 | - this.video.height = _height; | ||
114 | - } else { | ||
115 | - // height overflow, calc the width by DAR | ||
116 | - var _width:int = this.h * den / num; | ||
117 | - | ||
118 | - this.video.width = _width; | ||
119 | - this.video.height = this.h; | ||
120 | - } | ||
121 | - | ||
122 | - // align center. | ||
123 | - this.video.y = (this.h - this.video.height) / 2; | ||
124 | - this.video.x = (this.w - this.video.width) / 2; | 165 | + private function on_user_click_video(evt:MouseEvent):void { |
166 | + if (!this.stage.allowsFullScreen) { | ||
167 | + trace("donot allow fullscreen."); | ||
168 | + return; | ||
169 | + } | ||
170 | + | ||
171 | + // enter fullscreen to get the fullscreen size correctly. | ||
172 | + if (this.stage.displayState == StageDisplayState.FULL_SCREEN) { | ||
173 | + this.stage.displayState = StageDisplayState.NORMAL; | ||
174 | + } else { | ||
175 | + this.stage.displayState = StageDisplayState.FULL_SCREEN; | ||
125 | } | 176 | } |
126 | - return 0; | ||
127 | } | 177 | } |
128 | 178 | ||
129 | - public function js_call_stop():int { | 179 | + private function js_call_stop():int { |
130 | if (this.stream) { | 180 | if (this.stream) { |
131 | this.stream.close(); | 181 | this.stream.close(); |
132 | this.stream = null; | 182 | this.stream = null; |
@@ -143,17 +193,24 @@ package | @@ -143,17 +193,24 @@ package | ||
143 | return 0; | 193 | return 0; |
144 | } | 194 | } |
145 | 195 | ||
146 | - public function js_call_play(url:String, _width:int, _height:int, _buffer_time:Number):int { | 196 | + private function draw_black_background(_width:int, _height:int):void { |
197 | + // draw black bg. | ||
198 | + this.graphics.beginFill(0x00, 1.0); | ||
199 | + this.graphics.drawRect(0, 0, _width, _height); | ||
200 | + this.graphics.endFill(); | ||
201 | + | ||
202 | + // draw the fs mask. | ||
203 | + this.fs_mask.graphics.beginFill(0xff0000, 0); | ||
204 | + this.fs_mask.graphics.drawRect(0, 0, _width, _height); | ||
205 | + this.fs_mask.graphics.endFill(); | ||
206 | + } | ||
207 | + | ||
208 | + private function js_call_play(url:String, _width:int, _height:int, _buffer_time:Number):int { | ||
147 | this.url = url; | 209 | this.url = url; |
148 | this.w = _width; | 210 | this.w = _width; |
149 | this.h = _height; | 211 | this.h = _height; |
150 | trace("start to play url: " + this.url + ", w=" + this.w + ", h=" + this.h); | 212 | trace("start to play url: " + this.url + ", w=" + this.w + ", h=" + this.h); |
151 | 213 | ||
152 | - // draw black bg. | ||
153 | - this.graphics.beginFill(0x00, 1.0); | ||
154 | - this.graphics.drawRect(0, 0, this.w, this.h); | ||
155 | - this.graphics.endFill(); | ||
156 | - | ||
157 | js_call_stop(); | 214 | js_call_stop(); |
158 | 215 | ||
159 | this.conn = new NetConnection(); | 216 | this.conn = new NetConnection(); |
@@ -184,6 +241,11 @@ package | @@ -184,6 +241,11 @@ package | ||
184 | video.attachNetStream(stream); | 241 | video.attachNetStream(stream); |
185 | video.smoothing = true; | 242 | video.smoothing = true; |
186 | addChild(video); | 243 | addChild(video); |
244 | + | ||
245 | + draw_black_background(_width, _height); | ||
246 | + | ||
247 | + // lowest layer, for mask to cover it. | ||
248 | + setChildIndex(video, 0); | ||
187 | }); | 249 | }); |
188 | this.conn.connect(this.url.substr(0, this.url.lastIndexOf("/"))); | 250 | this.conn.connect(this.url.substr(0, this.url.lastIndexOf("/"))); |
189 | 251 | ||
@@ -204,13 +266,37 @@ package | @@ -204,13 +266,37 @@ package | ||
204 | contextMenu.customItems = customItems; | 266 | contextMenu.customItems = customItems; |
205 | 267 | ||
206 | // for js. | 268 | // for js. |
269 | + var obj:Object = get_video_size_object(); | ||
270 | + | ||
271 | + obj.server = 'srs'; | ||
272 | + obj.contributor = 'winlin'; | ||
273 | + | ||
274 | + if (metadata.hasOwnProperty("server")) { | ||
275 | + obj.server = metadata.server; | ||
276 | + } | ||
277 | + if (metadata.hasOwnProperty("contributor")) { | ||
278 | + obj.contributor = metadata.contributor; | ||
279 | + } | ||
280 | + | ||
281 | + var code:int = flash.external.ExternalInterface.call(on_player_metadata, id, obj); | ||
282 | + if (code != 0) { | ||
283 | + throw new Error("callback on_player_metadata failed. code=" + code); | ||
284 | + } | ||
285 | + } | ||
286 | + | ||
287 | + /** | ||
288 | + * get the "right" size of video, | ||
289 | + * 1. initialize with the original video object size. | ||
290 | + * 2. override with metadata size if specified. | ||
291 | + * 3. override with codec size if specified. | ||
292 | + */ | ||
293 | + private function get_video_size_object():Object { | ||
207 | var obj:Object = { | 294 | var obj:Object = { |
208 | width: video.width, | 295 | width: video.width, |
209 | - height: video.height, | ||
210 | - server: 'srs', | ||
211 | - contributor: 'winlin' | 296 | + height: video.height |
212 | }; | 297 | }; |
213 | 298 | ||
299 | + // override with metadata size. | ||
214 | if (metadata.hasOwnProperty("width")) { | 300 | if (metadata.hasOwnProperty("width")) { |
215 | obj.width = metadata.width; | 301 | obj.width = metadata.width; |
216 | } | 302 | } |
@@ -218,6 +304,7 @@ package | @@ -218,6 +304,7 @@ package | ||
218 | obj.height = metadata.height; | 304 | obj.height = metadata.height; |
219 | } | 305 | } |
220 | 306 | ||
307 | + // override with codec size. | ||
221 | if (video.videoWidth > 0) { | 308 | if (video.videoWidth > 0) { |
222 | obj.width = video.videoWidth; | 309 | obj.width = video.videoWidth; |
223 | } | 310 | } |
@@ -225,17 +312,110 @@ package | @@ -225,17 +312,110 @@ package | ||
225 | obj.height = video.videoHeight; | 312 | obj.height = video.videoHeight; |
226 | } | 313 | } |
227 | 314 | ||
228 | - if (metadata.hasOwnProperty("server")) { | ||
229 | - obj.server = metadata.server; | 315 | + return obj; |
316 | + } | ||
317 | + | ||
318 | + /** | ||
319 | + * execute the enter fullscreen action. | ||
320 | + */ | ||
321 | + private function execute_user_enter_fullscreen():void { | ||
322 | + if (!fs_refer || fs_percent <= 0) { | ||
323 | + return; | ||
230 | } | 324 | } |
231 | - if (metadata.hasOwnProperty("contributor")) { | ||
232 | - obj.contributor = metadata.contributor; | 325 | + |
326 | + // change to video size if refer to video. | ||
327 | + var obj:Object = get_video_size_object(); | ||
328 | + | ||
329 | + // get the DAR | ||
330 | + var num:int = dar_num; | ||
331 | + var den:int = dar_den; | ||
332 | + | ||
333 | + if (num == 0) { | ||
334 | + num = obj.height; | ||
335 | + } | ||
336 | + if (num == -1) { | ||
337 | + num = this.stage.fullScreenHeight; | ||
233 | } | 338 | } |
234 | 339 | ||
235 | - var code:int = flash.external.ExternalInterface.call(on_player_metadata, id, obj); | ||
236 | - if (code != 0) { | ||
237 | - throw new Error("callback on_player_metadata failed. code=" + code); | 340 | + if (den == 0) { |
341 | + den = obj.width; | ||
342 | + } | ||
343 | + if (den == -1) { | ||
344 | + den = this.stage.fullScreenWidth; | ||
345 | + } | ||
346 | + | ||
347 | + // for refer is screen. | ||
348 | + if (fs_refer == "screen") { | ||
349 | + obj = { | ||
350 | + width: this.stage.fullScreenWidth, | ||
351 | + height: this.stage.fullScreenHeight | ||
352 | + }; | ||
238 | } | 353 | } |
354 | + | ||
355 | + // rescale to fs | ||
356 | + update_video_size(num, den, obj.width * fs_percent / 100, obj.height * fs_percent / 100, this.stage.fullScreenWidth, this.stage.fullScreenHeight); | ||
357 | + } | ||
358 | + | ||
359 | + /** | ||
360 | + * for user set dar, or leave fullscreen to recover the dar. | ||
361 | + */ | ||
362 | + private function execute_user_set_dar():void { | ||
363 | + // get the DAR | ||
364 | + var num:int = dar_num; | ||
365 | + var den:int = dar_den; | ||
366 | + | ||
367 | + var obj:Object = get_video_size_object(); | ||
368 | + | ||
369 | + if (num == 0) { | ||
370 | + num = obj.height; | ||
371 | + } | ||
372 | + if (num == -1) { | ||
373 | + num = this.h; | ||
374 | + } | ||
375 | + | ||
376 | + if (den == 0) { | ||
377 | + den = obj.width; | ||
378 | + } | ||
379 | + if (den == -1) { | ||
380 | + den = this.w; | ||
381 | + } | ||
382 | + | ||
383 | + update_video_size(num, den, this.w, this.h, this.w, this.h); | ||
384 | + } | ||
385 | + | ||
386 | + /** | ||
387 | + * update the video width and height, | ||
388 | + * according to the specifies DAR(den:num) and max size(w:h). | ||
389 | + * set the position of video(x,y) specifies by size(sw:sh), | ||
390 | + * and update the bg to size(sw:sh). | ||
391 | + * @param _num/_den the DAR. use to rescale the player together with paper size. | ||
392 | + * @param _w/_h the video draw paper size. used to rescale the player together with DAR. | ||
393 | + * @param _sw/_wh the stage size, >= paper size. used to center the player. | ||
394 | + */ | ||
395 | + private function update_video_size(_num:int, _den:int, _w:int, _h:int, _sw:int, _sh:int):void { | ||
396 | + if (!this.video || _num <= 0 || _den <= 0) { | ||
397 | + return; | ||
398 | + } | ||
399 | + | ||
400 | + // set DAR. | ||
401 | + // calc the height by DAR | ||
402 | + var _height:int = _w * _num / _den; | ||
403 | + if (_height <= _h) { | ||
404 | + this.video.width = _w; | ||
405 | + this.video.height = _height; | ||
406 | + } else { | ||
407 | + // height overflow, calc the width by DAR | ||
408 | + var _width:int = _h * _den / _num; | ||
409 | + | ||
410 | + this.video.width = _width; | ||
411 | + this.video.height = _h; | ||
412 | + } | ||
413 | + | ||
414 | + // align center. | ||
415 | + this.video.x = (_sw - this.video.width) / 2; | ||
416 | + this.video.y = (_sh - this.video.height) / 2; | ||
417 | + | ||
418 | + draw_black_background(_sw, _sh); | ||
239 | } | 419 | } |
240 | } | 420 | } |
241 | } | 421 | } |
-
请 注册 或 登录 后发表评论