PageRenderTime 3019ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/eyesee360/VideoDisplaySprite.as

http://panosalado.googlecode.com/
ActionScript | 1560 lines | 535 code | 201 blank | 824 comment | 86 complexity | 58475072116118068cbad28c9d674292 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // EYESEE360 INCORPORATED
  4. // Based on the VideoDisplay class in the Flex SDK.
  5. //
  6. // ADOBE SYSTEMS INCORPORATED
  7. // Copyright 2005-2007 Adobe Systems Incorporated
  8. // All Rights Reserved.
  9. //
  10. // NOTICE: Adobe permits you to use, modify, and distribute this file
  11. // in accordance with the terms of the license agreement accompanying it.
  12. //
  13. ////////////////////////////////////////////////////////////////////////////////
  14. package com.eyesee360
  15. {
  16. import flash.display.Sprite;
  17. import flash.events.Event;
  18. import flash.events.ProgressEvent;
  19. import flash.media.Camera;
  20. import mx.controls.videoClasses.VideoPlayer;
  21. import mx.events.CuePointEvent;
  22. import mx.events.FlexEvent;
  23. import mx.events.MetadataEvent;
  24. import mx.events.VideoEvent;
  25. import mx.styles.ISimpleStyleClient;
  26. import mx.utils.LoaderUtil;
  27. import com.eyesee360.materials.VideoPlayerMaterial;
  28. /**
  29. * Dispatched when the NetConnection object is closed, whether by timing
  30. * out or by calling the <code>close()</code> method.
  31. * You use this event when working with Flash Media Server.
  32. *
  33. * @eventType mx.events.VideoEvent.CLOSE
  34. */
  35. [Event(name="close", type="mx.events.VideoEvent")]
  36. /**
  37. * Dispatched when the playhead reaches the end of the FLV file.
  38. *
  39. * @eventType mx.events.VideoEvent.COMPLETE
  40. */
  41. [Event(name="complete", type="mx.events.VideoEvent")]
  42. /**
  43. * Dispatched when the value of a cue point's <code>time</code> property
  44. * is equal to the current playhead location.
  45. *
  46. * @eventType mx.events.CuePointEvent.CUE_POINT
  47. */
  48. [Event(name="cuePoint", type="mx.events.CuePointEvent")]
  49. /**
  50. * Dispatched the first time metadata in the FLV file is reached.
  51. *
  52. * @eventType mx.events.MetadataEvent.METADATA_RECEIVED
  53. */
  54. [Event(name="metadataReceived", type="mx.events.MetadataEvent")]
  55. /**
  56. * Dispatched continuosly while the video is playing.
  57. * The interval between events, in milliseconds, is specified by the
  58. * <code>playheadUpdateInterval</code> property, which defaults to 250 ms.
  59. * This event is not dispatched when the video is in a paused or stopped
  60. * state.
  61. *
  62. * @eventType mx.events.VideoEvent.PLAYHEAD_UPDATE
  63. */
  64. [Event(name="playheadUpdate", type="mx.events.VideoEvent")]
  65. /**
  66. * Dispatched continuously until the FLV file has downloaded completely.
  67. *
  68. * <p>You can use this event to check the number of bytes loaded
  69. * or the number of bytes in the buffer.
  70. * This event starts getting dispatched when the <code>load()</code> or
  71. * <code>play()</code> method is called first and ends when all bytes are
  72. * loaded or if there is a network error.</p>
  73. *
  74. * @eventType flash.events.ProgressEvent.PROGRESS
  75. */
  76. [Event(name="progress", type="flash.events.ProgressEvent")]
  77. /**
  78. * Dispatched when the FLV file is loaded and ready to play.
  79. *
  80. * <p>This event is dispatched the first time the VideoDisplay control
  81. * enters a responsive state after a new FLV file is loaded by the
  82. * <code>load()</code> or <code>play()</code> method.
  83. * It is dispatched only once for each FLV file loaded.</p>
  84. *
  85. * @eventType mx.events.VideoEvent.READY
  86. */
  87. [Event(name="ready", type="mx.events.VideoEvent")]
  88. /**
  89. * Dispatched when the control autorewinds.
  90. *
  91. * @see #autoRewind
  92. *
  93. * @eventType mx.events.VideoEvent.REWIND
  94. */
  95. [Event(name="rewind", type="mx.events.VideoEvent")]
  96. /**
  97. * Dispatched when the state of the control changes.
  98. *
  99. * <p>You can use this event to track when playback enters and leaves
  100. * the unresponsive state (for example, in the middle of connecting,
  101. * resizing, or rewinding), during which time calls to the
  102. * <code>play()</code>, <code>pause()</code>, and <code>stop()</code> methods
  103. * and writes to the <code>playHeadTime</code> property are queued, and then
  104. * executed when the player enters the responsive state.</p>
  105. *
  106. * @eventType mx.events.VideoEvent.STATE_CHANGE
  107. */
  108. [Event(name="stateChange", type="mx.events.VideoEvent")]
  109. /**
  110. * The VideoDisplay control lets you play an FLV file in a Flex application.
  111. * It supports progressive download over HTTP, streaming from the Flash Media
  112. * Server, and streaming from a Camera object.
  113. *
  114. * @mxml
  115. *
  116. * <p>The <code>&lt;mx:VideoDisplay&gt;</code> tag inherits all the tag
  117. * attributes of its superclass, and adds the following tag attributes:</p>
  118. *
  119. * <pre>
  120. * &lt;mx:VideoDisplay
  121. * <strong>Properties</strong>
  122. * autoBandWidthDetection="false|true"
  123. * autoPlay="true|false"
  124. * autoRewind="true|false"
  125. * bufferTime="0.1"
  126. * cuePointManagerClass=""
  127. * cuePoints=""
  128. * idleTimeout="300000"
  129. * live="false|true"
  130. * maintainAspectRatio="true|false"
  131. * playheadTime=""
  132. * playheadUpdateInterval="250"
  133. * progressInterval="250"
  134. * source=""
  135. * totalTime=""
  136. * volume="0.75"
  137. *
  138. * <b>Styles</b>
  139. * backgroundAlpha="1.0"
  140. * backgroundColor="0x000000"
  141. * backgroundImage="undefined"
  142. * backgroundSize="undefined"
  143. * borderColor="undefined"
  144. * borderSides="left top right bottom"
  145. * borderSkin="ClassReference('mx.skins.halo.HaloBorder')"
  146. * borderStyle="none"
  147. * borderThickness="1"
  148. * cornerRadius="0"
  149. * dropShadowColor="0x000000"
  150. * dropShadowEnabled="false|true"
  151. * shadowDirection="center"
  152. * shadowDistance="2"
  153. *
  154. * <strong>Events</strong>
  155. * close="<i>No default</i>"
  156. * complete="<i>No default</i>"
  157. * cuePoint="<i>No default</i>"
  158. * playheadUpdate="<i>No default</i>"
  159. * progress="<i>No default</i>"
  160. * ready="<i>No default</i>"
  161. * rewind="<i>No default</i>"
  162. * stateChange="<i>No default</i>"
  163. *
  164. * /&gt;
  165. * </pre>
  166. *
  167. */
  168. public class VideoDisplaySprite extends Sprite
  169. {
  170. /**
  171. * @private
  172. * Internal VideoPlayer instance.
  173. */
  174. private var videoPlayer:VideoPlayer = null;
  175. /**
  176. * @private
  177. * Internal CuePointManager instance associated with the VideoPlayer.
  178. */
  179. private var _cuePointManager:Object = null;
  180. /**
  181. * @private
  182. * Flag indicating whether the value of source changed. Checked in
  183. * play()
  184. */
  185. private var sourceChanged:Boolean = false;
  186. /**
  187. * @private
  188. * Flag indicating whether close has been called. Checked in
  189. * play()
  190. */
  191. private var closeCalled:Boolean = false;
  192. //--------------------------------------------------------------------------
  193. //
  194. // Constants
  195. //
  196. //--------------------------------------------------------------------------
  197. /**
  198. * @private
  199. * The default width if none is specified and no width information is
  200. * available from the video.
  201. */
  202. private static const DEFAULT_WIDTH:Number = 10;
  203. /**
  204. * @private
  205. * The default height if none is specified and no height information is
  206. * available from the video.
  207. */
  208. private static const DEFAULT_HEIGHT:Number = 10;
  209. //--------------------------------------------------------------------------
  210. //
  211. // Constructor
  212. //
  213. //--------------------------------------------------------------------------
  214. /**
  215. * Constructor.
  216. */
  217. public function VideoDisplaySprite()
  218. {
  219. super();
  220. addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
  221. }
  222. //--------------------------------------------------------------------------
  223. //
  224. // Variables
  225. //
  226. //--------------------------------------------------------------------------
  227. /**
  228. * @private
  229. */
  230. private var asCuePointIndexResetPending:Boolean = false;
  231. /**
  232. * @private
  233. */
  234. private var creationCompleted:Boolean = false;
  235. //--------------------------------------------------------------------------
  236. //
  237. // Properties
  238. //
  239. //--------------------------------------------------------------------------
  240. //----------------------------------
  241. // autoBandWidthDetection
  242. //----------------------------------
  243. private var _autoBandWidthDetection:Boolean = false;
  244. [Bindable("autoBandWidthDetection")]
  245. [Inspectable(defaultValue="false")]
  246. /**
  247. * Specifies whether the VideoDisplay control should use the built-in
  248. * automatic bandwidth detection feature.
  249. *
  250. * When <code>false</code>, you do not require a main.asc file
  251. * on Flash Media Server (FMS) 2 to connect to FMS.
  252. * When <code>true</code>, you need to implement a main.asc
  253. * and store it in the directory structure of FMS.
  254. * The main.asc file must define the following functions:
  255. *
  256. * <ul>
  257. * <li><pre>
  258. * application.onConnect = function(p_client, p_autoSenseBW)
  259. * {
  260. * //Add security code here.
  261. * this.acceptConnection(p_client);
  262. * if (p_autoSenseBW)
  263. * this.calculateClientBw(p_client);
  264. * else
  265. * p_client.call("onBWDone");
  266. * }</pre></li>
  267. *
  268. * <li><pre>
  269. * application.calculateClientBw = function(p_client)
  270. * {
  271. * // Add code to set the clients BandWidth.
  272. * // Use p_client.getStats() which returns bytes_in
  273. * // and bytes_Out and check your bandWidth using
  274. * // p_client.call("onBWCheck", result, p_client.payload).
  275. * p_client.call("onBWDone");
  276. * }
  277. * </pre>
  278. * </li>
  279. *
  280. * <li><pre>
  281. * Client.prototype.getStreamLength = function(p_streamName)
  282. * {
  283. * return Stream.length(p_streamName);
  284. * }</pre>
  285. * </li>
  286. * </ul>
  287. *
  288. * For more information on writing main.asc, see the FMS documentation.
  289. *
  290. * @default false
  291. */
  292. public function get autoBandWidthDetection():Boolean
  293. {
  294. return _autoBandWidthDetection;
  295. }
  296. /**
  297. * @private
  298. */
  299. public function set autoBandWidthDetection(value:Boolean):void
  300. {
  301. if (_autoBandWidthDetection != value)
  302. {
  303. _autoBandWidthDetection = value;
  304. if (videoPlayer)
  305. videoPlayer.autoBandWidthDetection = value;
  306. dispatchEvent(new Event("autoBandWidthDetectionChanged"));
  307. }
  308. }
  309. //----------------------------------
  310. // autoRewind
  311. //----------------------------------
  312. /**
  313. * @private
  314. * Storage for autoRewind property.
  315. */
  316. private var _autoRewind:Boolean = true;
  317. [Bindable("autoRewindChanged")]
  318. [Inspectable(category="General", defaultValue="true")]
  319. /**
  320. * Specifies whether the FLV file should be rewound to the first frame
  321. * when play stops, either by calling the <code>stop()</code> method or by
  322. * reaching the end of the stream.
  323. *
  324. * This property has no effect for live streaming video.
  325. *
  326. * @default true
  327. */
  328. public function get autoRewind():Boolean
  329. {
  330. return _autoRewind;
  331. }
  332. /**
  333. * @private
  334. */
  335. public function set autoRewind(value:Boolean):void
  336. {
  337. if (_autoRewind != value)
  338. {
  339. _autoRewind = value;
  340. if (videoPlayer)
  341. videoPlayer.autoRewind = value;
  342. dispatchEvent(new Event("autoRewindChanged"));
  343. }
  344. }
  345. //----------------------------------
  346. // bufferTime
  347. //----------------------------------
  348. /**
  349. * @private
  350. * Storage for bufferTime property.
  351. */
  352. private var _bufferTime:Number = 0.1;
  353. [Bindable("bufferTimeChanged")]
  354. [Inspectable(category="General", defaultValue="0.1")]
  355. /**
  356. * Number of seconds of video to buffer in memory before starting to play
  357. * the video file.
  358. * For slow connections streaming over RTMP, it is important to increase
  359. * this property from the default.
  360. *
  361. * @default 0.1
  362. */
  363. public function get bufferTime():Number
  364. {
  365. return _bufferTime;
  366. }
  367. /**
  368. * @private
  369. */
  370. public function set bufferTime(value:Number):void
  371. {
  372. if (_bufferTime != value)
  373. {
  374. _bufferTime = value;
  375. if (videoPlayer)
  376. videoPlayer.bufferTime = value;
  377. dispatchEvent(new Event("bufferTimeChanged"));
  378. }
  379. }
  380. //----------------------------------
  381. // autoPlay
  382. //----------------------------------
  383. /**
  384. * @private
  385. * Storage for autoPlay property.
  386. */
  387. private var _autoPlay:Boolean = true;
  388. [Inspectable(category="General", defaultValue="true")]
  389. /**
  390. * Specifies whether the video should start playing immediately when the
  391. * <code>source</code> property is set.
  392. * If <code>true</code>, the video file immediately begins to buffer and
  393. * play.
  394. *
  395. * <p>Even if <code>autoPlay</code> is set to <code>false</code>, Flex
  396. * starts loading the video after the <code>initialize()</code> method is
  397. * called.
  398. * For Flash Media Server, this means creating the stream and loading
  399. * the first frame to display (and loading more if
  400. * <code>autoSize</code> or <code>aspectRatio</code> is set to
  401. * <code>true</code>).
  402. * In the case of an HTTP download, Flex starts downloading the stream
  403. * and shows the first frame.</p>
  404. *
  405. * @default true
  406. */
  407. public function get autoPlay():Boolean
  408. {
  409. return _autoPlay;
  410. }
  411. /**
  412. * @private
  413. */
  414. public function set autoPlay(value:Boolean):void
  415. {
  416. _autoPlay = value;
  417. }
  418. //----------------------------------
  419. // bytesLoaded
  420. //----------------------------------
  421. [Bindable("complete")]
  422. [Bindable("progress")]
  423. /**
  424. * Number of bytes already loaded that are available for playing.
  425. * The value is only useful for media loaded using HTTP.
  426. *
  427. * <p>Contains -1 when there
  428. * is no input stream, when the stream is from Flash Media Server,
  429. * or if the information is not yet available. </p>
  430. */
  431. public function get bytesLoaded():int
  432. {
  433. if (videoPlayer)
  434. return videoPlayer.bytesLoaded;
  435. return -1;
  436. }
  437. //----------------------------------
  438. // bytesTotal
  439. //----------------------------------
  440. [Bindable("complete")]
  441. [Bindable("progress")]
  442. /**
  443. * Total number of bytes to load.
  444. * The value is only useful for media loaded using HTTP.
  445. *
  446. * <p>Contains -1 when there
  447. * is no input stream, when the stream is from Flash Media Server,
  448. * or if the information is not yet available. </p>
  449. */
  450. public function get bytesTotal():int
  451. {
  452. if (videoPlayer)
  453. return videoPlayer.bytesTotal;
  454. return -1;
  455. }
  456. //----------------------------------
  457. // cuePointManager
  458. //----------------------------------
  459. /**
  460. * The instance of the CuePointManager class associated with
  461. * the VideoPlayer control.
  462. * You can use this object to control cue points, or use the
  463. * <code>cuePoints</code> property.
  464. *
  465. * <p>You use cue points to trigger <code>cuePoint</code> events when the
  466. * playback of your video reaches a specified location.
  467. * To set cue points, you use methods of the CuePointManager class. </p>
  468. *
  469. * <p>Cue points embedded in the FLV are not available via <code>cuePoints</code> or
  470. * <code>cuePointManager</code>. In order to retrieve them, you can access the
  471. * <code>metadata</code> property or the <code>metadataReceived</code> event.</p>
  472. *
  473. * @see mx.controls.videoClasses.CuePointManager
  474. */
  475. public function get cuePointManager():Object
  476. {
  477. return _cuePointManager;
  478. }
  479. //----------------------------------
  480. // cuePointManagerClass
  481. //----------------------------------
  482. /**
  483. * @private
  484. * Storage for cuePointManagerClass property.
  485. */
  486. private var _cuePointManagerClass:Class = null;
  487. /**
  488. * Cue point manager to use.
  489. * Set this to mx.controls.videoClasses.CuePointManager to enable cue
  490. * point management.
  491. *
  492. * @see mx.controls.videoClasses.CuePointManager
  493. */
  494. public function get cuePointManagerClass():Class
  495. {
  496. return _cuePointManagerClass;
  497. }
  498. /**
  499. * @private
  500. */
  501. public function set cuePointManagerClass(value:Class):void
  502. {
  503. _cuePointManagerClass = value;
  504. }
  505. //----------------------------------
  506. // cuePoints
  507. //----------------------------------
  508. /**
  509. * @private
  510. * Storage for cuePoints property.
  511. */
  512. private var _cuePoints:Array = null;
  513. [Bindable("cuePointsChanged")]
  514. [Inspectable(defaultValue="null")]
  515. /**
  516. * The Array of cue points associated with the control.
  517. * You can use this property to control cue points, or use the
  518. * <code>cuePointManager</code> property.
  519. *
  520. * <p>You use cue points to trigger <code>cuePoint</code> events when the
  521. * playback of your video reaches a specified location.
  522. * To set cue points, you pass an Array to the <code>cuePoints</code>
  523. * property. </p>
  524. *
  525. * <p>Cue points embedded in the FLV are not available via <code>cuePoints</code> or
  526. * <code>cuePointManager</code>. In order to retrieve them, you can access the
  527. * <code>metadata</code> property or the <code>metadataReceived</code> event.</p>
  528. *
  529. * <p>Each element of the Array contains two fields:</p>
  530. * <ul>
  531. * <li>The <code>name</code> field
  532. * contains an arbitrary name of the cue point.</li>
  533. * <li>The <code>time</code> field
  534. * contains the playhead location, in seconds, of the VideoDisplay
  535. * control with which the cue point is associated.</li>
  536. * </ul>
  537. */
  538. public function get cuePoints():Array
  539. {
  540. if (!_cuePointManager)
  541. return _cuePoints;
  542. else
  543. return _cuePointManager.getCuePoints();
  544. }
  545. /**
  546. * @private
  547. */
  548. public function set cuePoints(value:Array):void
  549. {
  550. _cuePoints = value;
  551. if (_cuePointManager)
  552. setCuePoints(value);
  553. }
  554. //----------------------------------
  555. // idleTimeout
  556. //----------------------------------
  557. /**
  558. * @private
  559. * Storage for idleTimeout property.
  560. */
  561. private var _idleTimeout:int = -1;
  562. [Inspectable(defaultValue="300000")]
  563. /**
  564. * Specifies the amount of time, in milliseconds, that the connection is
  565. * idle (playing is paused or stopped) before the connection to the Flash
  566. * Media Server is stopped.
  567. * This property has no effect on the HTTP download of FLV files.
  568. *
  569. * If this property is set when the stream is already idle,
  570. * it restarts the idle timeout with a new value.
  571. *
  572. * @default 300000 (five minutes)
  573. */
  574. public function get idleTimeout():int
  575. {
  576. if (videoPlayer)
  577. return videoPlayer.idleTimeout;
  578. else
  579. return (_idleTimeout == -1)
  580. ? VideoPlayer.DEFAULT_IDLE_TIMEOUT_INTERVAL
  581. : _idleTimeout;
  582. }
  583. /**
  584. * @private
  585. */
  586. public function set idleTimeout(value:int):void
  587. {
  588. if (_idleTimeout != value)
  589. {
  590. _idleTimeout = value;
  591. if (videoPlayer)
  592. videoPlayer.idleTimeout = value;
  593. }
  594. }
  595. //----------------------------------
  596. // live
  597. //----------------------------------
  598. /**
  599. * @private
  600. * Storage for live property.
  601. */
  602. private var _live:Boolean = false;
  603. [Inspectable(category="General", defaultValue="false")]
  604. /**
  605. * Specifies whether the control is streaming a live feed.
  606. * Set this property to <code>true</code> when streaming a
  607. * live feed from Flash Media Server.
  608. *
  609. * @default false
  610. */
  611. public function get live():Boolean
  612. {
  613. return _live;
  614. }
  615. /**
  616. * @private
  617. */
  618. public function set live(value:Boolean):void
  619. {
  620. _live = value;
  621. }
  622. //----------------------------------
  623. // material
  624. //----------------------------------
  625. private var _material:VideoPlayerMaterial = null;
  626. [Bindable("materialAvailable")]
  627. /**
  628. * A PaperVision3D material object that can be used as a surface material for models.
  629. *
  630. */
  631. public function get material():VideoPlayerMaterial
  632. {
  633. return _material;
  634. }
  635. //----------------------------------
  636. // metadata
  637. //----------------------------------
  638. [Bindable("metadataReceived")]
  639. /**
  640. * An object that contains a metadata information packet that is received from a call to
  641. * the <code>NetSteam.onMetaData()</code> callback method, if available.
  642. * Ready when the <code>metadataReceived</code> event is dispatched.
  643. *
  644. * <p>If the FLV file is encoded with the Flash 8 encoder, the <code>metadata</code>
  645. * property contains the following information. Older FLV files contain
  646. * only the <code>height</code>, <code>width</code>, and <code>duration</code> values.</p>
  647. *
  648. * <table class="innertable" width="100%">
  649. * <tr><th><b>Parameter</b></th><th><b>Description</b></th></tr>
  650. * <tr><td><code>canSeekToEnd</code></td><td>A Boolean value that is <code>true</code> if the FLV file is encoded with a keyframe on the last frame that allows seeking to the end of a progressive download movie clip. It is <code>false</code> if the FLV file is not encoded with a keyframe on the last frame.</td></tr>
  651. * <tr><td><code>cuePoints</code></td><td>An Array of objects, one for each cue point embedded in the FLV file. Value is undefined if the FLV file does not contain any cue points. Each object has the following properties:
  652. *
  653. * <ul>
  654. * <li><code>type</code>&#x2014;A String that specifies the type of cue point as either "navigation" or "event".</li>
  655. * <li><code>name</code>&#x2014;A String that is the name of the cue point.</li>
  656. * <li><code>time</code>&#x2014;A Number that is the time of the cue point in seconds with a precision of three decimal places (milliseconds).</li>
  657. * <li><code>parameters</code>&#x2014;An optional Object that has name-value pairs that are designated by the user when creating the cue points.</li>
  658. * </ul>
  659. * </td></tr>
  660. * <tr><td><code>audiocodecid</code></td><td>A Number that indicates the audio codec (code/decode technique) that was used.</td></tr>
  661. * <tr><td><code>audiodelay</code></td><td> A Number that represents time <code>0</code> in the source file from which the FLV file was encoded.
  662. * <p>Video content is delayed for the short period of time that is required to synchronize the audio. For example, if the <code>audiodelay</code> value is <code>.038</code>, the video that started at time <code>0</code> in the source file starts at time <code>.038</code> in the FLV file.</p>
  663. * <p>Note that the VideoDisplay class compensates for this delay in its time settings. This means that you can continue to use the time settings that you used in your the source file.</p>
  664. </td></tr>
  665. * <tr><td><code>audiodatarate</code></td><td>A Number that is the kilobytes per second of audio.</td></tr>
  666. * <tr><td><code>videocodecid</code></td><td>A Number that is the codec version that was used to encode the video.</td></tr>
  667. * <tr><td><code>framerate</code></td><td>A Number that is the frame rate of the FLV file.</td></tr>
  668. * <tr><td><code>videodatarate</code></td><td>A Number that is the video data rate of the FLV file.</td></tr>
  669. * <tr><td><code>height</code></td><td>A Number that is the height of the FLV file.</td></tr>
  670. * <tr><td><code>width</code></td><td>A Number that is the width of the FLV file.</td></tr>
  671. * <tr><td><code>duration</code></td><td>A Number that specifies the duration of the FLV file in seconds.</td></tr>
  672. * </table>
  673. */
  674. public function get metadata():Object
  675. {
  676. return videoPlayer != null ? videoPlayer.metadata : null;
  677. }
  678. //----------------------------------
  679. // ncManagerClass
  680. //----------------------------------
  681. /**
  682. * @private
  683. * Storage for ncManagerClass property.
  684. */
  685. private var _ncManagerClass:Class = null;
  686. /**
  687. * @private
  688. * Name of the INCManager implementation class to use to
  689. * download the video. The default value is <code>"mx.controls.videoClasses.NCManager"</code>.
  690. */
  691. private function get ncManagerClass():Class
  692. {
  693. return _ncManagerClass != null
  694. ? _ncManagerClass : VideoPlayer.DEFAULT_INCMANAGER;
  695. }
  696. /**
  697. * @private
  698. */
  699. private function set ncManagerClass(value:Class):void
  700. {
  701. _ncManagerClass = value;
  702. }
  703. //----------------------------------
  704. // playheadTime
  705. //----------------------------------
  706. /**
  707. * @private
  708. * Storage for playheadTime property.
  709. */
  710. private var _playheadTime:Number = NaN;
  711. [Bindable("change")]
  712. [Bindable("playheadTimeChanged")]
  713. [Bindable("playheadUpdate")]
  714. [Inspectable(defaultValue="0")]
  715. /**
  716. * Playhead position, measured in seconds, since the video starting
  717. * playing.
  718. * The event object for many of the VideoPlay events include the playhead
  719. * position so that you can determine the location in the video file where
  720. * the event occurred.
  721. *
  722. * <p>Setting this property to a value in seconds performs a seek
  723. * operation.
  724. * If the video is currently playing,
  725. * it continues playing from the new playhead position.
  726. * If the video is paused, it seeks to
  727. * the new playhead position and remains paused.
  728. * If the video is stopped, it seeks to
  729. * the new playhead position and enters the paused state.
  730. * Setting this property has no effect with live video streams.</p>
  731. *
  732. * <p>If the new playhead position is less than 0 or NaN,
  733. * the control throws an exception. If the new playhead position
  734. * is past the end of the video, or past the amount of the video file
  735. * downloaded so far, then the control still attempts the seek.</p>
  736. *
  737. * <p>For an FLV file, setting the <code>playheadTime</code> property seeks
  738. * to the keyframe closest to the specified position, where
  739. * keyframes are specified in the FLV file at the time of encoding.
  740. * Therefore, you might not seek to the exact time if there
  741. * is no keyframe specified at that position.</p>
  742. *
  743. * <p>If player is in an unresponsive state, it queues the request.</p>
  744. *
  745. * <p>This property throws an exception if set when no stream is
  746. * connected. Use the <code>stateChange</code> event and the
  747. * <code>connected</code> property to determine when it is
  748. * safe to set this property.</p>
  749. *
  750. * @default NaN
  751. */
  752. public function get playheadTime():Number
  753. {
  754. return videoPlayer != null ? videoPlayer.playheadTime : _playheadTime;
  755. }
  756. /**
  757. * @private
  758. */
  759. public function set playheadTime(value:Number):void
  760. {
  761. _playheadTime = value;
  762. asCuePointIndexResetPending = true;
  763. if (videoPlayer)
  764. {
  765. videoPlayer.playheadTime = value;
  766. dispatchEvent(new Event("playheadTimeChanged"));
  767. }
  768. }
  769. //----------------------------------
  770. // playheadUpdateInterval
  771. //----------------------------------
  772. /**
  773. * @private
  774. * Storage for playheadUpdateInterval property.
  775. */
  776. private var _playheadUpdateInterval:int = -1;
  777. [Inspectable(defaultValue="250")]
  778. /**
  779. * Specifies the amount of time, in milliseconds,
  780. * between each <code>playheadUpdate</code> event.
  781. *
  782. * <p>If you set this property when the video is playing,
  783. * the timer restarts at 0, and the next <code>playheadUpdate</code>
  784. * event occurs after the new time interval.</p>
  785. *
  786. * @default 250
  787. */
  788. public function get playheadUpdateInterval():int
  789. {
  790. if (videoPlayer)
  791. return videoPlayer.playheadUpdateInterval;
  792. else
  793. return (_playheadUpdateInterval == -1)
  794. ? VideoPlayer.DEFAULT_UPDATE_TIME_INTERVAL
  795. : _playheadUpdateInterval;
  796. }
  797. /**
  798. * @private
  799. */
  800. public function set playheadUpdateInterval(value:int):void
  801. {
  802. if (_playheadUpdateInterval != value)
  803. {
  804. _playheadUpdateInterval = value;
  805. if (videoPlayer)
  806. videoPlayer.playheadUpdateInterval = value;
  807. }
  808. }
  809. //----------------------------------
  810. // playing
  811. //----------------------------------
  812. [Bindable("stateChange")]
  813. /**
  814. * If <code>true</code>, the media is currently playing.
  815. */
  816. public function get playing():Boolean
  817. {
  818. return videoPlayer != null
  819. && videoPlayer.state == VideoPlayer.PLAYING;
  820. }
  821. //----------------------------------
  822. // progressInterval
  823. //----------------------------------
  824. /**
  825. * @private
  826. * Storage for progressInterval property.
  827. */
  828. private var _progressInterval:int = -1;
  829. [Inspectable(defaultValue="250")]
  830. /**
  831. * Specifies the amount of time, in milliseconds,
  832. * between each <code>progress</code> event.
  833. * The <code>progress</code> event occurs continuously
  834. * until the video file downloads completely.
  835. *
  836. * <p>If you set this property when the video is downloading,
  837. * the timer restarts at 0, and the next <code>progress</code>
  838. * event occurs after the new time interval.</p>
  839. *
  840. * @default 250
  841. */
  842. public function get progressInterval():int
  843. {
  844. if (videoPlayer)
  845. return videoPlayer.progressInterval;
  846. else
  847. return (_progressInterval == -1)
  848. ? VideoPlayer.DEFAULT_UPDATE_PROGRESS_INTERVAL
  849. : _progressInterval;
  850. }
  851. /**
  852. * @private
  853. */
  854. public function set progressInterval(value:int):void
  855. {
  856. if (_progressInterval != value)
  857. {
  858. _progressInterval = value;
  859. if (videoPlayer)
  860. videoPlayer.progressInterval = value;
  861. }
  862. }
  863. //----------------------------------
  864. // state
  865. //----------------------------------
  866. [Bindable("stateChange")]
  867. /**
  868. * The current state of the VideoDisplay control.
  869. * You set this property by calls to the <code>load()</code>,
  870. * <code>play()</code>, <code>stop()</code>, and <code>pause()</code>
  871. * methods, and setting the <code>playHeadTime</code> property.
  872. *
  873. * <p>This property can have the following values defined in the
  874. * VideoEvent class:
  875. * <code>VideoEvent.BUFFERING</code>,
  876. * <code>VideoEvent.CONNECTION_ERROR</code>,
  877. * <code>VideoEvent.DISCONNECTED</code>,
  878. * <code>VideoEvent.EXEC_QUEUED_CMD</code>,
  879. * <code>VideoEvent.LOADING</code>, <code>VideoEvent.PAUSED</code>,
  880. * <code>VideoEvent.PLAYING</code>, <code>VideoEvent.RESIZING</code>,
  881. * <code>VideoEvent.REWINDING</code>, <code>VideoEvent.SEEKING</code>,
  882. * and <code>VideoEvent.STOPPED</code>. </p>
  883. *
  884. * @default VideoEvent.DISCONNECTED
  885. *
  886. * @see mx.events.VideoEvent
  887. */
  888. public function get state():String
  889. {
  890. return videoPlayer ? videoPlayer.state : VideoPlayer.DISCONNECTED;
  891. }
  892. //----------------------------------
  893. // stateResponsive
  894. //----------------------------------
  895. [Bindable("stateChange")]
  896. /**
  897. * Specifies whether the VideoDisplay control is in a responsive state,
  898. * <code>true</code>, or in the unresponsive state, <code>false</code>.
  899. * The control enters the unresponsive state when video is being loaded
  900. * or is rewinding.
  901. *
  902. * <p>The control is also in a responsive state when the
  903. * <code>state</code> property is:
  904. * <code>VideoEvent.CONNECTION_ERROR</code>,
  905. * <code>VideoEvent.EXEC_QUEUED_CMD</code>,
  906. * <code>VideoEvent.RESIZING</code>, or
  907. * <code>VideoEvent.SEEKING</code>. </p>
  908. *
  909. * <p>If the control is unresponsive, calls to the
  910. * <code>play()</code>, <code>load()</code>, <code>stop()</code>,
  911. * and <code>pause()</code> methods are queued,
  912. * and then executed when the control changes to the responsive state.</p>
  913. */
  914. public function get stateResponsive():Boolean
  915. {
  916. return videoPlayer ? videoPlayer.stateResponsive : true;
  917. }
  918. //----------------------------------
  919. // totalTime
  920. //----------------------------------
  921. /**
  922. * @private
  923. * Storage for totalTime property.
  924. */
  925. private var _totalTime:Number = NaN;
  926. [Bindable("complete")]
  927. [Bindable("totalTimeUpdated")]
  928. [Bindable("metadataReceived")]
  929. [Inspectable(defaultValue="NaN")]
  930. /**
  931. * Total length of the media, in seconds.
  932. * For FLV 1.0 video files, you manually set this property.
  933. * For FLV 1.1 and later, the control calculates this value automatically.
  934. */
  935. public function get totalTime():Number
  936. {
  937. if (!isNaN(_totalTime))
  938. // totalTime was set manually, return the same value.
  939. return _totalTime;
  940. else
  941. return videoPlayer != null ? videoPlayer.totalTime : NaN;
  942. }
  943. /**
  944. * @private
  945. */
  946. public function set totalTime(value:Number):void
  947. {
  948. if (_totalTime != value)
  949. {
  950. _totalTime = value;
  951. dispatchEvent(new Event("totalTimeUpdated"));
  952. }
  953. }
  954. //----------------------------------
  955. // source
  956. //----------------------------------
  957. /**
  958. * @private
  959. * Storage for source property.
  960. */
  961. private var _source:String = null;
  962. [Bindable("sourceChanged")]
  963. [Inspectable(category="General", defaultValue="null")]
  964. /**
  965. * Relative path and filename of the FLV file to stream.
  966. */
  967. public function get source():String
  968. {
  969. return _source;
  970. }
  971. /**
  972. * @private
  973. */
  974. public function set source(value:String):void
  975. {
  976. if (_source != value)
  977. {
  978. _source = value;
  979. sourceChanged = true;
  980. dispatchEvent(new Event("sourceChanged"));
  981. if (_autoPlay && creationCompleted)
  982. autoPlaying();
  983. }
  984. }
  985. //----------------------------------
  986. // videoHeight
  987. //----------------------------------
  988. [Bindable("resize")]
  989. /**
  990. * Height of the loaded FLV file.
  991. * <code>-1</code> if no FLV file loaded yet.
  992. */
  993. public function get videoHeight():int
  994. {
  995. return videoPlayer ? videoPlayer.videoHeight : -1;
  996. }
  997. //----------------------------------
  998. // videoWidth
  999. //----------------------------------
  1000. [Bindable("resize")]
  1001. /**
  1002. * Width of the loaded FLV file.
  1003. * <code>-1</code> if no FLV file loaded yet.
  1004. */
  1005. public function get videoWidth():int
  1006. {
  1007. return videoPlayer ? videoPlayer.videoWidth : -1;
  1008. }
  1009. //----------------------------------
  1010. // volume
  1011. //----------------------------------
  1012. /**
  1013. * @private
  1014. * Storage for volume property.
  1015. */
  1016. private var _volume:Number = 0.75;
  1017. [Bindable("volumeChanged")]
  1018. [Inspectable(category="General", defaultValue="0.75")]
  1019. /**
  1020. * The volume level, specified as an value between 0 and 1.
  1021. *
  1022. * @default 0.75
  1023. */
  1024. public function get volume():Number
  1025. {
  1026. return videoPlayer ? videoPlayer.volume : _volume;
  1027. }
  1028. /**
  1029. * @private
  1030. */
  1031. public function set volume(value:Number):void
  1032. {
  1033. if (_volume != value)
  1034. {
  1035. _volume = value;
  1036. if (videoPlayer)
  1037. videoPlayer.volume = value;
  1038. dispatchEvent(new Event("volumeChanged"));
  1039. }
  1040. }
  1041. //--------------------------------------------------------------------------
  1042. //
  1043. // Public methods
  1044. //
  1045. //--------------------------------------------------------------------------
  1046. /**
  1047. * Specifies whether to play a video stream from a camera.
  1048. * The video is displayed within the boundaries of the
  1049. * control in the application window.
  1050. *
  1051. * @param camera A Camera object that
  1052. * is capturing video data.
  1053. */
  1054. public function attachCamera(camera:Camera):void
  1055. {
  1056. if (!videoPlayer)
  1057. createVideoPlayer();
  1058. videoPlayer.attachCamera(camera);
  1059. videoPlayer.visible = true;
  1060. }
  1061. /**
  1062. * Forces the close of an input stream and connection to Flash Media
  1063. * Server.
  1064. * Calling this method dispatches the <code>close</code> event.
  1065. * Typically calling this method directly is not necessary
  1066. * because the connection is automatically closed when the idle period
  1067. * times out, as defined by the <code>idleTimeout</code> property.
  1068. */
  1069. public function close():void
  1070. {
  1071. if (!videoPlayer)
  1072. return;
  1073. videoPlayer.close();
  1074. closeCalled = true;
  1075. }
  1076. /**
  1077. * Loads the media file without playing it.
  1078. *
  1079. * <p>This method is similar to the <code>play()</code> method,
  1080. * but it causes the file to be loaded without
  1081. * playing. Autoresizing will occur if appropriate.
  1082. * After the load and autoresize, the state of the control is set to
  1083. * <code>VideoEvent.PAUSED</code>.</p>
  1084. */
  1085. public function load():void
  1086. {
  1087. if (!videoPlayer)
  1088. createVideoPlayer();
  1089. if (sourceChanged)
  1090. {
  1091. sourceChanged = false;
  1092. videoPlayer.load(getActualURL(_source), false,
  1093. isNaN(_totalTime) ? -1 : _totalTime);
  1094. }
  1095. }
  1096. /**
  1097. * Pauses playback without moving the playhead.
  1098. * If playback is already is paused or is stopped, this method has no
  1099. * effect.
  1100. *
  1101. * <p>To start playback again, call the <code>play()</code> method.</p>
  1102. *
  1103. * <p>If the control is in an unresponsive state, the request is queued.</p>
  1104. */
  1105. public function pause():void
  1106. {
  1107. if (!videoPlayer)
  1108. return;
  1109. videoPlayer.pause();
  1110. }
  1111. /**
  1112. * Plays the media file.
  1113. * If the file has not been loaded, it loads it.
  1114. * You can call this method while playback is paused, stopped, or while
  1115. * the control is playing.
  1116. *
  1117. * <p>If the control is in an unresponsive state, the request is
  1118. * queued.</p>
  1119. */
  1120. public function play():void
  1121. {
  1122. if (!videoPlayer)
  1123. createVideoPlayer();
  1124. if (videoPlayer.playheadTime >= 0)
  1125. asCuePointIndexResetPending = true;
  1126. if (sourceChanged || closeCalled)
  1127. {
  1128. sourceChanged = false;
  1129. closeCalled = false;
  1130. videoPlayer.play(getActualURL(_source), _live,
  1131. isNaN(_totalTime) ? -1 : _totalTime);
  1132. }
  1133. else
  1134. // Don't pass source, to avoid reconnect.
  1135. videoPlayer.play(null, _live,
  1136. isNaN(_totalTime) ? -1 : _totalTime);
  1137. }
  1138. /**
  1139. * Stops playback.
  1140. * If the <code>autoRewind</code> property is set to
  1141. * <code>true</code>, rewind to the first frame.
  1142. *
  1143. * <p>To start playback again, call the <code>play()</code> method.</p>
  1144. *
  1145. * <p>If playback is already stopped, this method has no effect.
  1146. * If the control is in an unresponsive state, the request is queued.</p>
  1147. */
  1148. public function stop():void
  1149. {
  1150. if (!videoPlayer)
  1151. return;
  1152. videoPlayer.stop();
  1153. }
  1154. //--------------------------------------------------------------------------
  1155. //
  1156. // Private methods
  1157. //
  1158. //--------------------------------------------------------------------------
  1159. private function getActualURL(url:String):String
  1160. {
  1161. // make relative paths relative to the SWF loading it, not the top-level SWF
  1162. if (!(url.indexOf(":") > -1 || url.indexOf("/") == 0 || url.indexOf("\\") == 0))
  1163. {
  1164. var rootURL:String;
  1165. if (root)
  1166. rootURL = LoaderUtil.normalizeURL(root.loaderInfo);
  1167. if (rootURL)
  1168. {
  1169. var lastIndex:int = Math.max(rootURL.lastIndexOf("\\"), rootURL.lastIndexOf("/"));
  1170. if (lastIndex != -1)
  1171. url = rootURL.substr(0, lastIndex + 1) + url;
  1172. }
  1173. }
  1174. return url;
  1175. }
  1176. /**
  1177. * @private
  1178. */
  1179. private function createVideoPlayer():void
  1180. {
  1181. videoPlayer = new VideoPlayer(1024, 512, _ncManagerClass);
  1182. videoPlayer.visible = false;
  1183. videoPlayer.autoBandWidthDetection = _autoBandWidthDetection;
  1184. videoPlayer.autoRewind = _autoRewind;
  1185. videoPlayer.bufferTime = _bufferTime;
  1186. videoPlayer.volume = _volume;
  1187. if (_idleTimeout != -1)
  1188. videoPlayer.idleTimeout = _idleTimeout;
  1189. if (_playheadUpdateInterval != -1)
  1190. videoPlayer.playheadUpdateInterval = _playheadUpdateInterval;
  1191. if (_progressInterval != -1)
  1192. videoPlayer.progressInterval = _progressInterval;
  1193. videoPlayer.addEventListener(VideoEvent.PLAYHEAD_UPDATE,
  1194. videoPlayer_playheadUpdateHandler);
  1195. videoPlayer.addEventListener(VideoEvent.COMPLETE,
  1196. videoPlayer_completeHandler);
  1197. videoPlayer.addEventListener(MetadataEvent.CUE_POINT,
  1198. videoPlayer_cuePointHandler);
  1199. videoPlayer.addEventListener(MetadataEvent.METADATA_RECEIVED,
  1200. videoPlayer_metadataHandler);
  1201. videoPlayer.addEventListener(ProgressEvent.PROGRESS,
  1202. videoPlayer_progressHandler);
  1203. videoPlayer.addEventListener(VideoEvent.READY,
  1204. videoPlayer_readyHandler);
  1205. videoPlayer.addEventListener(VideoEvent.REWIND,
  1206. videoPlayer_rewindHandler);
  1207. videoPlayer.addEventListener(VideoEvent.STATE_CHANGE,
  1208. videoPlayer_stateChangeHandler);
  1209. if (cuePointManagerClass)
  1210. {
  1211. _cuePointManager = new cuePointManagerClass(videoPlayer);
  1212. _cuePointManager.videoDisplay = this;
  1213. }
  1214. if (_cuePoints)
  1215. setCuePoints(_cuePoints);
  1216. _material = new VideoPlayerMaterial(videoPlayer, false);
  1217. }
  1218. /**
  1219. * @private
  1220. */
  1221. private function autoPlaying():void
  1222. {
  1223. if (_source)
  1224. {
  1225. // Start playing or loading.
  1226. if (_autoPlay)
  1227. play();
  1228. else
  1229. load();
  1230. // Seek to playheadTime now if specified.
  1231. if (!isNaN(_playheadTime))
  1232. {
  1233. asCuePointIndexResetPending = Boolean(_playheadTime >= 0);
  1234. videoPlayer.seek(_playheadTime);
  1235. }
  1236. }
  1237. }
  1238. /**
  1239. * @private
  1240. */
  1241. private function resizeVideo():void
  1242. {
  1243. var vw:Number = videoPlayer.videoWidth;
  1244. var vh:Number = videoPlayer.videoHeight;
  1245. if (vw > 0 && vh > 0 && videoPlayer.width != vw && videoPlayer.height != vh) {
  1246. // The video width and height have now become available.
  1247. // trace("Resizing video to " + vw + " x " + vh);
  1248. videoPlayer.setSize(vw, vh);
  1249. _material = null;
  1250. _material = new VideoPlayerMaterial(videoPlayer, false);
  1251. }
  1252. }
  1253. /**
  1254. * @private
  1255. * Creates and populates an array of cue points.
  1256. *
  1257. * @param cuePoints Array of cue points.
  1258. */
  1259. private function setCuePoints(cuePoints:Array):void
  1260. {
  1261. if (_cuePointManager)
  1262. _cuePointManager.setCuePoints(cuePoints);
  1263. _cuePoints = null;
  1264. dispatchEvent(new Event("cuePointsChanged"));
  1265. }
  1266. //--------------------------------------------------------------------------
  1267. //
  1268. // Event handlers
  1269. //
  1270. //--------------------------------------------------------------------------
  1271. /**
  1272. * @private
  1273. * Handler for "creationComplete" of this object.
  1274. */
  1275. private function creationCompleteHandler(event:FlexEvent):void
  1276. {
  1277. removeEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
  1278. creationCompleted = true;
  1279. autoPlaying();
  1280. }
  1281. /**
  1282. * @private
  1283. */
  1284. private function videoPlayer_playheadUpdateHandler(event:VideoEvent):void
  1285. {
  1286. dispatchEvent(event.clone());
  1287. if (_cuePointManager)
  1288. {
  1289. if (asCuePointIndexResetPending && videoPlayer.state != VideoPlayer.SEEKING)
  1290. {
  1291. asCuePointIndexResetPending = false;
  1292. _cuePointManager.resetCuePointIndex(event.playheadTime);
  1293. }
  1294. _cuePointManager.dispatchCuePoints();
  1295. }
  1296. }
  1297. /**
  1298. * @private
  1299. */
  1300. private function videoPlayer_completeHandler(event:VideoEvent):void
  1301. {
  1302. dispatchEvent(event.clone());
  1303. }
  1304. /**
  1305. * @private
  1306. */
  1307. private function videoPlayer_cuePointHandler(event:MetadataEvent):void
  1308. {
  1309. var info:Object = event.info;
  1310. var cuePointEvent:CuePointEvent = new CuePointEvent(CuePointEvent.CUE_POINT);
  1311. cuePointEvent.cuePointName = info.name;
  1312. cuePointEvent.cuePointTime = info.time;
  1313. cuePointEvent.cuePointType = info.type;
  1314. dispatchEvent(cuePointEvent);
  1315. }
  1316. /**
  1317. * @private
  1318. */
  1319. private function videoPlayer_metadataHandler(event:MetadataEvent):void
  1320. {
  1321. resizeVideo();
  1322. dispatchEvent(event.clone());
  1323. }
  1324. /**
  1325. * @private
  1326. */
  1327. private function videoPlayer_progressHandler(event:ProgressEvent):void
  1328. {
  1329. dispatchEvent(event.clone());
  1330. }
  1331. /**
  1332. * @private
  1333. */
  1334. private function videoPlayer_readyHandler(event:VideoEvent):void
  1335. {
  1336. resizeVideo();
  1337. dispatchEvent(event.clone());
  1338. }
  1339. /**
  1340. * @private
  1341. */
  1342. private function videoPlayer_rewindHandler(event:VideoEvent):void
  1343. {
  1344. dispatchEvent(event.clone());
  1345. }
  1346. /**
  1347. * @private
  1348. */
  1349. private function videoPlayer_stateChangeHandler(event:VideoEvent):void
  1350. {
  1351. // In some cases, the video width and height are updated only once the
  1352. // video has started playing.
  1353. if (videoPlayer.state == VideoPlayer.PLAYING)
  1354. resizeVideo();
  1355. dispatchEvent(event.clone());
  1356. }
  1357. }
  1358. }