1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 */
18
19 /*
20 * Plays an external FLV video
21 * Should be used with the MovieTester to test if the video decoder works.
22 *
23 * Expected behaviour:
24 *
25 * Shows a 54x54 pixels red square moving from left to right over
26 * a 152x120 yellow background. The whole thing rotated by 45 degrees clockwise.
27 */
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <ming.h>
32
33 #include "ming_utils.h"
34
35 #define OUTPUT_VERSION 7
36 #define OUTPUT_FILENAME "NetStream-SquareTest.swf"
37
38 const char* mediadir=".";
39 char filename[256];
40 char filename2[256];
41 char filename3[256];
42
43
44 int
main(int argc,char ** argv)45 main(int argc, char** argv)
46 {
47 SWFMovie mo;
48 SWFMovieClip dejagnuclip;
49 SWFVideoStream stream;
50 SWFDisplayItem item;
51 SWFAction a;
52 SWFAction b;
53 char buffer_a[2024];
54 char buffer_b[2024];
55 char buffer_c[2024];
56
57 // This is different from the real video width to make sure that
58 // Video.width returns the actual width (128).
59 int video_width = 130;
60 int video_height = 96;
61
62 if ( argc>1 ) mediadir=argv[1];
63 else
64 {
65 fprintf(stderr, "Usage: %s <mediadir>\n", argv[0]);
66 return 1;
67 }
68
69 sprintf(filename, "%s/square.flv", mediadir);
70 sprintf(filename2, "%s/square.ogg", mediadir);
71 sprintf(filename3, "%s/audio_timewarp.flv", mediadir);
72
73 // Some online examples...
74 //
75 // 'ffdec_vp6f'
76 //sprintf(filename, "http://www.helpexamples.com/flash/video/water.flv");
77 //sprintf(filename, "http://www.helpexamples.com/flash/video/clouds.flv");
78 //sprintf(filename, "http://www.helpexamples.com/flash/video/typing_long.flv");
79 //
80 // This ones work
81 //sprintf(filename, "http://www.helpexamples.com/flash/video/caption_video.flv");
82 //sprintf(filename, "http://www.helpexamples.com/flash/video/sheep.flv");
83 //
84 //
85
86 sprintf(buffer_a,
87 "note(System.capabilities.version);"
88 "note('SWF version %d');"
89 "nc=new NetConnection();"
90 "check(!nc.isConnected, 'newly created NetConnection is not connected');"
91 "nc.connect(null);"
92 "check(nc.isConnected, 'NetConnection is connected after .connect(null)');"
93 "check(!NetStream.prototype.hasOwnProperty('currentFPS'));" // version 7 here
94 "check(!NetStream.prototype.hasOwnProperty('currentFps'));"
95 "stream = new NetStream();"
96 "check_equals ( typeof(stream.bytesTotal), 'undefined' );" // not connected..
97 "stream.play('fake');" // just test not to segfault..
98 "stream = new NetStream(nc);"
99 "check_equals ( typeof(stream.bytesTotal), 'number' );"
100 "stream.bytesTotal = 'string';"
101 "check_equals ( typeof(stream.bytesTotal), 'number' );"
102 "stream2 = new NetStream(nc);"
103 "stream3 = new NetStream(nc);"
104 , OUTPUT_VERSION);
105
106 sprintf(buffer_b,
107 // bytesTotal (read-only)
108 "MovieClip.prototype.addBytesLoadedProgress = function(v, s) {"
109 " var nam = 'blprogress_'+v;"
110 " var dep = this.getNextHighestDepth();"
111 " var pc = this.createEmptyMovieClip(nam, dep);"
112 " pc.stream = s;"
113 " pc.video = v;"
114 " var pcp = pc.createEmptyMovieClip('bar', pc.getNextHighestDepth());"
115 " var x = v._x;"
116 " var y = v._y+v._height+10;"
117 " var w = v._width;"
118 " var h = 10;"
119 " with(pcp) {"
120 " _x = x;"
121 " _y = y;"
122 " moveTo(0,0);"
123 " beginFill(0xFF0000,50);"
124 " lineTo(0, h);"
125 " lineTo(w, h);"
126 " lineTo(w, 0);"
127 " lineTo(0, 0);"
128 " endFill();"
129 " };"
130 " pc.onEnterFrame = function() {"
131 " pcp._xscale = 100*(this.stream.bytesLoaded/this.stream.bytesTotal);"
132 " };"
133 "};");
134
135 sprintf(buffer_c,
136 "MovieClip.prototype.addBufferLoadedProgress = function(v, s) {"
137 " var nam = 'blprogress_'+v;"
138 " var dep = this.getNextHighestDepth();"
139 " var pc = this.createEmptyMovieClip(nam, dep);"
140 " pc.stream = s;"
141 " pc.video = v;"
142 " var pcp = pc.createEmptyMovieClip('bar', pc.getNextHighestDepth());"
143 " var x = v._x;"
144 " var y = v._y+v._height+22;"
145 " var w = v._width;"
146 " var h = 10;"
147 " with(pcp) {"
148 " _x = x;"
149 " _y = y;"
150 " moveTo(0,0);"
151 " beginFill(0x00FF00,50);"
152 " lineTo(0, h);"
153 " lineTo(w, h);"
154 " lineTo(w, 0);"
155 " lineTo(0, 0);"
156 " endFill();"
157 " };"
158 " pc.onEnterFrame = function() {"
159 //" _root.note(this.video._x+': bufferloaded: '+this.stream.bufferLength+'/'+this.stream.bufferTime);"
160 " pcp._xscale = 100*(this.stream.bufferLength/this.stream.bufferTime);"
161 // when bufferLength > bufferTime (common):
162 " if ( pcp._xscale > 100 ) {"
163 " pcp._xscale = 100;"
164 " pcp._alpha = 100;"
165 " } else {"
166 " pcp._alpha = 50;"
167 " }"
168 " };"
169 "};"
170 "stream.play('%s');"
171 "stream2.play('%s');"
172 "stream3.play('%s');"
173 "stream.pause(true);"
174 "stream.paused=true;"
175 "_root.metadataNotified=0;"
176 "_root.startNotified=0;"
177 "_root.stopNotified=0;"
178 "stop();",
179 filename, filename2, filename3);
180
181 Ming_init();
182 Ming_useSWFVersion (OUTPUT_VERSION);
183
184
185 mo = newSWFMovie();
186 SWFMovie_setDimension(mo, 800, 600);
187
188 // We also want to test that 1FPS of SWF rate doesn't influence
189 // rate of video playback, but for now it's more useful to actually
190 // have something rendered, so check_pixel can eventually do something,
191 // so we run fast...
192 SWFMovie_setRate(mo, 32);
193
194 dejagnuclip = get_dejagnu_clip((SWFBlock)get_default_font(mediadir), 10, 0, 0, 800, 600);
195 item = SWFMovie_add(mo, (SWFBlock)dejagnuclip);
196 SWFDisplayItem_moveTo(item, 0, 250);
197 SWFMovie_nextFrame(mo);
198
199 stream = newSWFVideoStream();
200 SWFVideoStream_setDimension(stream, video_width, video_height);
201 item = SWFMovie_add(mo, (SWFBlock)stream);
202 /* SWFDisplayItem_moveTo(item, 0, 200); */
203 SWFDisplayItem_setName(item, "video");
204
205 stream = newSWFVideoStream();
206 SWFVideoStream_setDimension(stream, video_width, video_height);
207 item = SWFMovie_add(mo, (SWFBlock)stream);
208 SWFDisplayItem_moveTo(item, 400, 0);
209 SWFDisplayItem_setName(item, "video2");
210
211 stream = newSWFVideoStream();
212 SWFVideoStream_setDimension(stream, video_width, video_height);
213 item = SWFMovie_add(mo, (SWFBlock)stream);
214 SWFDisplayItem_setName(item, "video3");
215
216 a = newSWFAction(buffer_a);
217 if(a == NULL) return -1;
218 SWFMovie_add(mo, (SWFBlock)a);
219
220 /* Check that properties exist here
221 See actionscript.all/NetStream.as for checks before
222 NetStream is attached to a connection */
223
224 check(mo, "NetStream.prototype.hasOwnProperty('currentFps')"); // currentFps
225 check(mo, "NetStream.prototype.hasOwnProperty('bufferLength')"); // check bufferLength
226 check(mo, "NetStream.prototype.hasOwnProperty('bufferTime')"); // check bufferTime
227 check(mo, "NetStream.prototype.hasOwnProperty('liveDelay')"); // check liveDelay
228 check(mo, "NetStream.prototype.hasOwnProperty('time')"); // check time
229 check(mo, "NetStream.prototype.hasOwnProperty('bytesLoaded')"); // check bytesLoaded
230 check(mo, "NetStream.prototype.hasOwnProperty('bytesTotal')"); // check bytesTotal
231
232 //-----------------------------------------
233 // Dynamic volume tests using Sound object
234 //-----------------------------------------
235
236 // create a movieclip to use as sound controller
237 add_actions(mo, "createEmptyMovieClip('dv1', 1);");
238
239 // attach Sound s1 to DisplayObject dv1
240 add_actions(mo, "s1 = new Sound(dv1);");
241 // Sound.getVolume fetches volume from dv1 (see s2 below)
242 check_equals(mo, "s1.getVolume()", "100");
243
244 // Change volume of Sound s1 (will change volume of attached DisplayObject, see below)
245 add_actions(mo, "s1.setVolume(1000);");
246 check_equals(mo, "s1.getVolume()", "1000");
247
248 // attach Sound s2 to DisplayObject dv2
249 add_actions(mo, "s2 = new Sound(dv1);");
250 // Sound s2 finds volume of dv1 being 1000
251 check_equals(mo, "s2.getVolume()", "1000");
252
253 // This shows that setVolume/getVolume make callbacks
254 // to attached DisplayObject as changing volume of one Sound
255 // influence the other attached sound...
256 add_actions(mo, "s2.setVolume(5);");
257 check_equals(mo, "s2.getVolume()", "5");
258 check_equals(mo, "s1.getVolume()", "5");
259 add_actions(mo, "s1.setVolume(80);");
260 check_equals(mo, "s2.getVolume()", "80");
261 check_equals(mo, "s1.getVolume()", "80");
262 // btw, negative volume is fine..
263 add_actions(mo, "s1.setVolume(-20);");
264 check_equals(mo, "s2.getVolume()", "-20");
265 check_equals(mo, "s1.getVolume()", "-20");
266
267 // If the attached-to DisplayObject gets unloaded,
268 // getVolume returns undefined...
269 add_actions(mo, "dv1.removeMovieClip();");
270 check_equals(mo, "typeof(s2.getVolume())", "'undefined'");
271 check_equals(mo, "typeof(s1.getVolume())", "'undefined'");
272 // even if you reset it explicitly
273 add_actions(mo, "s2.setVolume(50);");
274 check_equals(mo, "typeof(s2.getVolume())", "'undefined'");
275 check_equals(mo, "typeof(s1.getVolume())", "'undefined'");
276 // but you get it back when you create a replacement..
277 add_actions(mo, "createEmptyMovieClip('dv1', 2);");
278 check_equals(mo, "s2.getVolume()", "100");
279 check_equals(mo, "s1.getVolume()", "100");
280 add_actions(mo, "s1.setVolume(80);");
281 check_equals(mo, "s2.getVolume()", "80");
282 check_equals(mo, "s1.getVolume()", "80");
283
284 // And you can attach a Sound to any DisplayObject, not
285 // just MovieClip ones.
286 // This is against a video instance
287 add_actions(mo, "s1 = new Sound(video); s2 = new Sound(video);");
288 check_equals(mo, "s2.getVolume()", "100");
289 check_equals(mo, "s1.getVolume()", "100");
290 add_actions(mo, "s1.setVolume(80);");
291 check_equals(mo, "s2.getVolume()", "80");
292 check_equals(mo, "s1.getVolume()", "80");
293
294 // Here's a 3 level volume controller. Our square.flv doesn't have sound
295 // so you can't really see if it's working or not... Anyway, change
296 // the code to load a movie with sound and see what happens changing the volumes
297 // below
298 add_actions(mo,
299 "dv1.createEmptyMovieClip('dv2', 1);"
300 "dv1.dv2.createEmptyMovieClip('dv3', 1);"
301 "dv1.dv2.dv3.attachAudio(stream);" // attach stream to 3rd level
302 "s1 = new Sound(dv1);"
303 "s2 = new Sound(dv1.dv2);"
304 "s3 = new Sound(dv1.dv2.dv3);"
305 "s3.setVolume(50);" // ---------- level1 volume (change me for tests)
306 "s1.setVolume(50);" // ---------- level2 volume (change me for tests)
307 "s2.setVolume(400);" // --------- level3 volume (change me for tests)
308 );
309
310 //------------------------------------------
311 // Now attach video to the video DisplayObjects
312 //------------------------------------------
313 check(mo, "Video.prototype.hasOwnProperty('attachVideo')");
314 check(mo, "Video.prototype.hasOwnProperty('smoothing')");
315 check(mo, "Video.prototype.hasOwnProperty('deblocking')");
316 check(mo, "Video.prototype.hasOwnProperty('clear')");
317 check(mo, "Video.prototype.hasOwnProperty('height')");
318 check(mo, "Video.prototype.hasOwnProperty('width')");
319 check_equals(mo, "video.height", "0");
320 check_equals(mo, "video.width", "0");
321 check_equals(mo, "video2.height", "0");
322 check_equals(mo, "video2.width", "0");
323
324 add_actions(mo, "video.attachVideo(stream);");
325 add_actions(mo, "video2.attachVideo(stream2);");
326 add_actions(mo, "video3.attachVideo(stream3);");
327
328 check_equals(mo, "video.height", "0");
329 check_equals(mo, "video.width", "0");
330 check_equals(mo, "video2.height", "0");
331 check_equals(mo, "video2.width", "0");
332
333 // currentFps (read-only)
334 check_equals (mo, "typeof(stream.currentFps)", "'number'" );
335 add_actions(mo, "stream.currentFps = 'string';");
336 check_equals (mo, "typeof(stream.currentFps)", "'number'" );
337 add_actions(mo, "stream.currentFps = false;");
338 check_equals (mo, "typeof(stream.currentFps)", "'number'" );
339
340 // bufferLength (read-only)
341 check_equals (mo, "typeof(stream.bufferLength)", "'number'" );
342 add_actions(mo, "stream.bufferLength = 'string';");
343 check_equals (mo, "typeof(stream.bufferLength)", "'number'" );
344 add_actions(mo, "stream.bufferLength = false;");
345 check_equals (mo, "typeof(stream.bufferLength)", "'number'" );
346
347 // bufferTime
348 check_equals (mo, "typeof(stream.bufferTime)", "'number'" );
349 add_actions(mo, "stream.setBufferTime(2);");
350 check_equals (mo, "stream.bufferTime", "2");
351 add_actions(mo,"stream.bufferTime = 20;");
352 check_equals (mo, "stream.bufferTime", "2");
353 add_actions(mo,"stream.setBufferTime = 30;");
354 check_equals (mo, "stream.bufferTime", "2");
355 add_actions(mo,"stream.setBufferTime(false);");
356 check_equals (mo, "stream.bufferTime", "2");
357 add_actions(mo,"stream.setBufferTime('string');");
358 check_equals (mo, "stream.bufferTime", "2");
359 add_actions(mo,"stream.setBufferTime('5');");
360 check_equals (mo, "stream.bufferTime", "2");
361 add_actions(mo,"stream.setBufferTime(10);"); // can't change it once set ...
362 check_equals (mo, "stream.bufferTime", "2");
363
364 // liveDelay (read-only)
365 xcheck_equals (mo, "typeof(stream.liveDelay)", "'number'");
366 add_actions(mo, "stream.liveDelay = 'string';");
367 xcheck_equals (mo, "typeof(stream.liveDelay)", "'number'");
368
369 // time (read-only)
370 check_equals (mo, "typeof(stream.time)", "'number'" );
371 add_actions(mo, "stream.time = 'string';");
372 check_equals (mo, "typeof(stream.time)", "'number'" );
373
374 // bytesLoaded (read-only)
375 check_equals (mo, "typeof(stream.bytesLoaded)", "'number'" );
376 add_actions(mo, "stream.bytesLoaded = 'string';");
377 check_equals (mo, "typeof(stream.bytesLoaded)", "'number'" );
378
379 check_equals (mo, "stream.currentFps", "0" );
380
381 /* Play video */
382 b = newSWFAction(buffer_b);
383 if(b == NULL) return -1;
384 SWFMovie_add(mo, (SWFBlock)b);
385 b = newSWFAction(buffer_c);
386 if(b == NULL) return -1;
387 SWFMovie_add(mo, (SWFBlock)b);
388
389 check_equals (mo, "stream.currentFps", "0" );
390
391 /* Publisher Methods */
392
393 // These are documented as player methods for connections
394 // to a media server.
395 // Possibly they are only defined if the connection is to
396 // such a server; at this point, they should be undefined in
397 // any case.
398
399 check_equals (mo, "typeof(stream.attachAudio())", "'undefined'");
400 check_equals (mo, "typeof(stream.attachVideo())", "'undefined'");
401 check_equals (mo, "typeof(stream.publish())", "'undefined'");
402 check_equals (mo, "typeof(stream.send())", "'undefined'");
403 check_equals (mo, "typeof(stream.receiveAudio())", "'undefined'");
404 check_equals (mo, "typeof(stream.receiveVideo())", "'undefined'");
405
406 /* Video checks */
407
408 check_equals(mo, "video._xscale", "100");
409 check_equals(mo, "video._yscale", "100");
410 check_equals(mo, "video._rotation", "0");
411 check_equals(mo, "video._target", "'/video'");
412 check_equals(mo, "video.height", "0");
413 check_equals(mo, "video.width", "0");
414 check_equals(mo, "video2.height", "0");
415 check_equals(mo, "video2.width", "0");
416
417 check(mo, "Video.prototype.hasOwnProperty('attachVideo')");
418 check(mo, "Video.prototype.hasOwnProperty('smoothing')");
419 check(mo, "Video.prototype.hasOwnProperty('deblocking')");
420 check(mo, "Video.prototype.hasOwnProperty('clear')");
421 check(mo, "Video.prototype.hasOwnProperty('height')");
422 check(mo, "Video.prototype.hasOwnProperty('width')");
423
424 check(mo, "!Video.prototype.hasOwnProperty('_alpha')");
425 check(mo, "!Video.prototype.hasOwnProperty('_height')");
426 check(mo, "!Video.prototype.hasOwnProperty('_name')");
427 check(mo, "!Video.prototype.hasOwnProperty('_parent')");
428 check(mo, "!Video.prototype.hasOwnProperty('_rotation')");
429 check(mo, "!Video.prototype.hasOwnProperty('_visible')");
430 check(mo, "!Video.prototype.hasOwnProperty('_width')");
431 check(mo, "!Video.prototype.hasOwnProperty('_x')");
432 check(mo, "!Video.prototype.hasOwnProperty('_xmouse')");
433 check(mo, "!Video.prototype.hasOwnProperty('_xscale')");
434 check(mo, "!Video.prototype.hasOwnProperty('_y')");
435 check(mo, "!Video.prototype.hasOwnProperty('_ymouse')");
436 check(mo, "!Video.prototype.hasOwnProperty('_yscale')");
437 check(mo, "!Video.prototype.hasOwnProperty('_xmouse')");
438
439 check(mo, "!video.hasOwnProperty('_alpha')");
440 check(mo, "!video.hasOwnProperty('_height')");
441 check(mo, "!video.hasOwnProperty('_name')");
442 check(mo, "!video.hasOwnProperty('_parent')");
443 check(mo, "!video.hasOwnProperty('_rotation')");
444 check(mo, "!video.hasOwnProperty('_visible')");
445 check(mo, "!video.hasOwnProperty('_width')");
446 check(mo, "!video.hasOwnProperty('_x')");
447 check(mo, "!video.hasOwnProperty('_xmouse')");
448 check(mo, "!video.hasOwnProperty('_xscale')");
449 check(mo, "!video.hasOwnProperty('_y')");
450 check(mo, "!video.hasOwnProperty('_ymouse')");
451 check(mo, "!video.hasOwnProperty('_yscale')");
452 check(mo, "!video.hasOwnProperty('_xmouse')");
453
454 add_actions(mo,
455 "video._x = 100;"
456 "video._xscale = 120;"
457 "video._yscale = 120;"
458 "video._rotation = 45;"
459 "_root.addBytesLoadedProgress(video, stream);"
460 "_root.addBytesLoadedProgress(video2, stream2);"
461 "_root.addBufferLoadedProgress(video, stream);"
462 "_root.addBufferLoadedProgress(video2, stream2);"
463 );
464
465 check_equals(mo, "video._x", "100") ;
466 check_equals(mo, "Math.round(video._xscale*100)/100", "120");
467 check_equals(mo, "Math.round(video._yscale*100)/100", "120");
468 check_equals(mo, "Math.round(video._rotation*100)/100", "45");
469
470
471 // How can I test props here ?
472 check_equals(mo, "typeof(video.hitTest)", "'undefined'");
473 check_equals(mo, "typeof(video.getBounds)", "'undefined'");
474
475 SWFMovie_add(mo, (SWFBlock)newSWFAction(
476 "note('The video on the right is an OGG theora stream. It will appear "
477 "in Gnash, but not the Adobe player');"
478 "_root.onKeyDown = function() {"
479 " _root.note(' bufferLength:'+stream.bufferLength+"
480 " ' bytesLoaded:'+stream.bytesLoaded+"
481 " ' currentFps:'+stream.currentFps+' time:'+stream.time);"
482 " var ascii = Key.getAscii();"
483 " trace('Key down: '+ascii);"
484 " if ( ascii == 32 ) {" // ' ' - pause(toggle)
485 " stream.paused = !stream.paused;"
486 " stream.pause();" // stream.paused);"
487 " }"
488 " else if ( ascii == 112 ) {" // 'p' - play()
489 " stream.play();"
490 " _root.note(\"2. Verify video hasn't started, then press space to continue.\");"
491 " }"
492 " else if ( ascii == 99 ) {" // 'c' - play()
493 " _root.check(nc.isConnected, 'NetConnection is connected');"
494 " _root.nc.close();"
495 " _root.note(\"Closed netconnection\");"
496 " _root.check(!nc.isConnected, 'NetConnection is not connected');"
497 " }"
498 "};"
499 "Key.addListener(_root);"
500
501 "\n"
502
503 "stream.onStatus = function(info) {"
504
505 " if ( ! _root.enumerableStatusInfoChecked ) {"
506 " _root.check(info.code != undefined);"
507 " _root.check(info.level != undefined);"
508 " var tmp = new Array();"
509 " for (var e in info) tmp.push(e);"
510 " tmp.sort();"
511 " _root.check_equals(tmp.length, 2);"
512 " _root.check_equals(tmp[0], 'code');"
513 " _root.check_equals(tmp[1], 'level');"
514 " _root.enumerableStatusInfoChecked=true;"
515 " var backup = info.code; info.code = 65;"
516 " _root.check_equals(info.code, 65);"
517 " _root.check(delete info.code);"
518 " _root.check_equals(info.code, undefined);"
519 " info.code = backup;"
520 " var backup = info.level; info.level = 66;"
521 " _root.check_equals(info.level, 66);"
522 " _root.check(delete info.level);"
523 " _root.check_equals(info.level, undefined);"
524 " info.level = backup;"
525 " }"
526
527 "\n"
528
529 // Ignore Buffer.Flush for now
530 " if ( info.code == 'NetStream.Buffer.Flush' ) return; "
531
532 // Print some info
533 " _root.note('onStatus('+info.code+') called'); "
534
535 "\n"
536
537 " if ( info.code == 'NetStream.Play.Start' )"
538 " {"
539 " check(!_root.startNotified, 'No duplicated Play.Start notification');"
540 " _root.startNotified++;"
541 " }"
542
543 " else if ( info.code == 'NetStream.Play.Stop' )"
544 " {"
545 " if ( ! _root.stopNotified )"
546 " {"
547 " _root.stopNotified++;"
548 " stream.seek(0);"
549 " } else {"
550 " _root.stopNotified++;"
551 " _root.check(this instanceOf NetStream); "
552 " _root.check_equals(this.bufferTime, 2); "
553 " _root.check_equals(this.bytesTotal, 21482); "
554 " _root.nextFrame();"
555 " }"
556 " }"
557 #if 0
558 " else if ( info.code == 'NetStream.Buffer.Empty' && this.stopNotified ) "
559 " {"
560 " check ( this.stopNotified )"
561 " this.close();"
562 " _root.nextFrame();"
563 " }"
564 #endif
565
566 "};"
567
568 "\n"
569
570 "stream.onCuePoint = function(info) {"
571 " _root.note('onCuePoint('+info+') called'); "
572 "};"
573 "stream.onMetaData = function(info) {"
574
575 // debugging
576 " var s='';"
577 " for (e in info) { "
578 " s += e+':'+info[e]+' ';"
579 " }"
580 " _root.note('onMetaData: '+s);"
581
582
583 " _root.metadataNotified++;"
584
585 // don't run other tests if already done
586 // BTW: should be called once, gnash (gst) calls this twice
587 // and would succeed in composition checking in second call.
588 " if ( _root.metadataNotified > 1 ) return;"
589
590 " check(_root.startNotified, 'onMetaData should be notified after Play.Start');"
591 " check_equals(arguments.length, 1, 'single argument');"
592 " check(info instanceof Array, 'onMetaData argument sent from square.flv should be instanceof Array');"
593 " check_equals(info.length, 11);"
594
595 // Test enumeration
596 " var enu = new Array;"
597 " for (e in info) { "
598 " enu.push(e);"
599 " }"
600 " check_equals(enu.length, 11);" // this is actual (not virtual) composition
601
602 "\n"
603
604
605 // Test composision
606
607 " check(info.hasOwnProperty('length'), 'metadata has length');" // it's an array...
608
609 " check(info.hasOwnProperty('filesize'), 'metadata has filesize');"
610 " check_equals(typeof(info.filesize), 'number', 'filesize is a number');"
611 " check_equals(info.filesize, '21482', 'actual filesize');"
612 " info.filesize = 'changed';"
613 " check_equals(info.filesize, 'changed');" // can be overridden
614 " delete info.filesize;"
615 " check(!info.hasOwnProperty('filesize'), 'metadata filesize can be deleted');"
616
617 " check(info.hasOwnProperty('audiocodecid'), 'metadata has audiocodecid');"
618 " check_equals(typeof(info.audiocodecid), 'number', 'audiocodecid is a number');"
619 " check_equals(info.audiocodecid, 2, 'actual audiocodecid');"
620 " info.audiocodecid = 'changed';"
621 " check_equals(info.audiocodecid, 'changed');" // can be overridden
622 " delete info.audiocodecid;"
623 " check(!info.hasOwnProperty('audiocodecid'), 'metadata audiocodecid can be deleted');"
624
625 "\n"
626
627 " check(info.hasOwnProperty('stereo'), 'metadata has stereo');"
628 " check_equals(typeof(info.stereo), 'boolean', 'stereo is boolean');"
629 " check_equals(info.stereo, false, 'actual stereo');"
630 " info.stereo = 'changed';"
631 " check_equals(info.stereo, 'changed');" // can be overridden
632 " delete info.stereo;"
633 " check(!info.hasOwnProperty('stereo'), 'metadata stereo can be deleted');"
634
635 " check(info.hasOwnProperty('audiosamplesize'), 'metadata has audiosamplesize');"
636 " check_equals(typeof(info.audiosamplesize), 'number', 'audiosamplesize is a number');"
637 " check_equals(info.audiosamplesize, 16, 'actual audiosamplesize');"
638 " info.audiosamplesize = 'changed';"
639 " check_equals(info.audiosamplesize, 'changed');" // can be overridden
640 " delete info.audiosamplesize;"
641 " check(!info.hasOwnProperty('audiosamplesize'), 'metadata audiosamplesize can be deleted');"
642
643 "\n"
644
645 " check(info.hasOwnProperty('audiosamplerate'), 'metadata has audiosamplerate');"
646 " check_equals(typeof(info.audiosamplerate), 'number', 'audiosamplerate is a number');"
647 " check_equals(info.audiosamplerate, 44100, 'actual audiosamplerate');"
648 " info.audiosamplerate = 'changed';"
649 " check_equals(info.audiosamplerate, 'changed');" // can be overridden
650 " delete info.audiosamplerate;"
651 " check(!info.hasOwnProperty('audiosamplerate'), 'metadata audiosamplerate can be deleted');"
652
653 " check(info.hasOwnProperty('videocodecid'), 'metadata has videocodecid');"
654 " check_equals(typeof(info.videocodecid), 'number', 'videocodecid is a number');"
655 " check_equals(info.videocodecid, 2, 'actual videocodecid');"
656 " info.videocodecid = 'changed';"
657 " check_equals(info.videocodecid, 'changed');" // can be overridden
658 " delete info.videocodecid;"
659 " check(!info.hasOwnProperty('videocodecid'), 'metadata videocodecid can be deleted');"
660
661 "\n"
662
663 " check(info.hasOwnProperty('height'), 'metadata has height');"
664 " check_equals(typeof(info.height), 'number', 'height is a number');"
665 " check_equals(info.height, 96, 'actual height');"
666 " info.height = 'changed';"
667 " check_equals(info.height, 'changed');" // can be overridden
668 " delete info.height;"
669 " check(!info.hasOwnProperty('height'), 'metadata height can be deleted');"
670
671 " check(info.hasOwnProperty('width'), 'metadata has width');"
672 " check_equals(typeof(info.width), 'number', 'width is a number');"
673 " check_equals(info.width, 128, 'actual width');"
674 " info.width = 'changed';"
675 " check_equals(info.width, 'changed');" // can be overridden
676 " delete info.width;"
677 " check(!info.hasOwnProperty('width'), 'metadata width can be deleted');"
678
679 "\n"
680
681 " check(info.hasOwnProperty('duration'), 'metadata has duration');"
682 " check_equals(typeof(info.duration), 'number', 'duration is a number');"
683 " check_equals(info.duration, 2.299, 'actual duration');" // seconds, rounded to milliseconds
684 " info.duration = 'changed';"
685 " check_equals(info.duration, 'changed');" // can be overridden
686 " delete info.duration;"
687 " check(!info.hasOwnProperty('duration'), 'metadata duration can be deleted');"
688 " _root.note('1. Press \"p\" key');"
689 "};"
690 ));
691
692 SWFMovie_nextFrame(mo);
693
694 check_equals(mo, "video.height", "96");
695 check_equals(mo, "video.width", "128");
696
697
698 // See https://savannah.gnu.org/bugs/?26687
699 SWFMovie_add(mo, (SWFBlock)newSWFAction(
700 //"note('VM.time:'+getTimer()+' stream3.time:'+stream3.time);"
701 "check(stream3.time > 4150, 'stream3.time '+stream3.time+' > 4150');"
702 ));
703
704
705 //add_actions(mo, "note('This is an OGG stream, so the Adobe player "
706 // "will fail the next two tests.');");
707 // gstreamer also fails, so let's not test this.
708 //check_equals(mo, "video2.height", "96");
709 //check_equals(mo, "video2.width", "128");
710
711 check_equals(mo, "metadataNotified", "1");
712 check_equals(mo, "stopNotified", "2");
713 check_equals(mo, "startNotified", "1");
714 SWFMovie_add(mo, (SWFBlock)newSWFAction("totals(197); stop(); end_of_test=true;"));
715
716 SWFMovie_nextFrame(mo);
717
718
719 /* Output movie */
720 puts("Saving " OUTPUT_FILENAME );
721 SWFMovie_save(mo, OUTPUT_FILENAME);
722
723 return 0;
724 }
725