< prev index next >

modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCMediaPlayerImpl.java

Print this page




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.webkit.prism;
  27 
  28 import java.net.URI;
  29 import java.util.List;
  30 import java.util.logging.Level;
  31 import com.sun.javafx.media.PrismMediaFrameHandler;
  32 import com.sun.media.jfxmedia.Media;
  33 import com.sun.media.jfxmedia.MediaManager;
  34 import com.sun.media.jfxmedia.MediaPlayer;
  35 import com.sun.media.jfxmedia.control.VideoDataBuffer;
  36 import com.sun.media.jfxmedia.events.BufferListener;
  37 import com.sun.media.jfxmedia.events.BufferProgressEvent;
  38 import com.sun.media.jfxmedia.events.MediaErrorListener;
  39 import com.sun.media.jfxmedia.events.NewFrameEvent;
  40 import com.sun.media.jfxmedia.events.PlayerStateEvent;
  41 import com.sun.media.jfxmedia.events.PlayerStateListener;
  42 import com.sun.media.jfxmedia.events.PlayerTimeListener;
  43 import com.sun.media.jfxmedia.events.VideoRendererListener;
  44 import com.sun.media.jfxmedia.events.VideoTrackSizeListener;
  45 import com.sun.media.jfxmedia.locator.Locator;
  46 import com.sun.media.jfxmedia.track.AudioTrack;
  47 import com.sun.media.jfxmedia.track.Track;
  48 import com.sun.media.jfxmedia.track.VideoTrack;
  49 import com.sun.prism.Graphics;
  50 import com.sun.prism.Texture;


  90             player = p;
  91             installListeners();
  92             frameHandler = PrismMediaFrameHandler.getHandler(player);
  93         }
  94 
  95         finished = 0;
  96     }
  97 
  98     private final class CreateThread extends Thread {
  99         private boolean cancelled = false;
 100         private final String url;
 101         private final String userAgent;
 102         private CreateThread(String url, String userAgent) {
 103             this.url = url;
 104             this.userAgent = userAgent;
 105             gotFirstFrame = false;
 106         }
 107 
 108         @Override
 109         public void run() {
 110             if (verbose) log.log(Level.FINE, "CreateThread: started, url={0}", url);
 111 
 112             notifyNetworkStateChanged(NETWORK_STATE_LOADING);
 113             notifyReadyStateChanged(READY_STATE_HAVE_NOTHING);
 114 
 115             MediaPlayer p = null;
 116 
 117             try {
 118                 Locator locator = new Locator(new URI(url));
 119                 if (userAgent != null) {
 120                     locator.setConnectionProperty("User-Agent", userAgent);
 121                 }
 122                 locator.init();
 123                 if (verbose) {
 124                     log.fine("CreateThread: locator created");
 125                 }
 126 
 127                 p = MediaManager.getPlayer(locator);
 128             } catch (Exception ex) {
 129                 if (verbose) {
 130                     log.log(Level.WARNING, "CreateThread ERROR: {0}", ex.toString());
 131                     ex.printStackTrace(System.out);
 132                 }
 133                 onError(this, 0, ex.getMessage());
 134                 return;
 135             }
 136 
 137             synchronized (lock) {
 138                 if (cancelled) {
 139                     if (verbose) log.log(Level.FINE, "CreateThread: cancelled");
 140                     p.dispose();
 141                     return;
 142                 }
 143                 createThread = null;
 144                 setPlayer(p);
 145             }
 146             if (verbose) log.log(Level.FINE, "CreateThread: completed");
 147         }
 148 
 149         private void cancel() {
 150             synchronized (lock) {
 151                 cancelled = true;
 152             }
 153         }
 154     }
 155 
 156 
 157     protected void load(String url, String userAgent) {
 158         synchronized (lock) {
 159             if (createThread != null) {
 160                 createThread.cancel();
 161             }
 162             disposePlayer();
 163             createThread = new CreateThread(url, userAgent);
 164         }
 165         // fx media player does not support loading only metadata,
 166         // so handle PRELOAD_METADATA as PRELOAD_AUTO (start loading)


 323         }
 324     }
 325 
 326     protected void setSize(int w, int h) {
 327         // nothing to do
 328     }
 329 
 330     protected void setPreservesPitch(boolean preserve) {
 331         // nothing to do
 332     }
 333 
 334     protected void renderCurrentFrame(WCGraphicsContext gc, int x, int y, int w, int h) {
 335         // TODO: need a render lock in MediaFrameHandler
 336         synchronized (lock) {
 337             renderImpl(gc, x, y, w, h);
 338         }
 339     }
 340 
 341 
 342     private void renderImpl(WCGraphicsContext gc, int x, int y, int w, int h) {
 343         if (verbose) log.log(Level.FINER, ">>(Prism)renderImpl");
 344         Graphics g = (Graphics)gc.getPlatformGraphics();
 345 
 346         Texture texture = null;
 347         VideoDataBuffer currentFrame = frameListener.getLatestFrame();
 348 
 349         if (null != currentFrame) {
 350             if (null != frameHandler) {
 351                 texture = frameHandler.getTexture(g, currentFrame);
 352             }
 353             currentFrame.releaseFrame();
 354         }
 355 
 356         if (texture != null) {
 357             g.drawTexture(texture,
 358                     x, y, x + w, y + h,
 359                     0f, 0f, texture.getContentWidth(), texture.getContentHeight());
 360             texture.unlock();
 361         } else {
 362             if (verbose) log.log(Level.FINEST, "  (Prism)renderImpl, texture is null, draw black rect");
 363             gc.fillRect(x, y, w, h, 0xFF000000);
 364         }
 365         if (verbose) log.log(Level.FINER, "<<(Prism)renderImpl");
 366     }
 367 
 368     // PlayerStateListener
 369     @Override
 370     public void onReady(PlayerStateEvent pse) {
 371         MediaPlayer p = getPlayer();
 372         if (verbose) log.log(Level.FINE, "onReady");
 373         Media media = p.getMedia();
 374         boolean hasVideo = false;
 375         boolean hasAudio = false;
 376         if (media != null) {
 377             List<Track> tracks = media.getTracks();
 378             if (tracks != null) {
 379                 if (verbose) log.log(Level.INFO, "{0} track(s) detected:", tracks.size());
 380                 for (Track track : tracks) {
 381                     if (track instanceof VideoTrack) {
 382                         hasVideo = true;
 383                     } else if (track instanceof AudioTrack) {
 384                         hasAudio = true;
 385                     }
 386                     if (verbose) log.log(Level.INFO, "track: {0}", track);
 387                 }
 388             } else {
 389                 if (verbose) log.log(Level.WARNING, "onReady, tracks IS NULL");
 390             }
 391         } else {
 392             if (verbose) log.log(Level.WARNING, "onReady, media IS NULL");
 393         }
 394         if (verbose) {
 395             log.log(Level.FINE, "onReady, hasVideo:{0}, hasAudio: {1}",
 396                     new Object[]{hasVideo, hasAudio});
 397         }

 398         notifyReady(hasVideo, hasAudio, (float)p.getDuration());
 399 
 400         // if we have no video, report READY_STATE_HAVE_ENOUGH_DATA right now
 401         if (!hasVideo) {
 402             notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 403         } else {
 404             if (getReadyState() < READY_STATE_HAVE_METADATA) {
 405                 if (gotFirstFrame) {
 406                     notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 407                 } else {
 408                     notifyReadyStateChanged(READY_STATE_HAVE_METADATA);
 409                 }
 410             }
 411         }
 412     }
 413 
 414     @Override
 415     public void onPlaying(PlayerStateEvent pse) {
 416         if (verbose) log.log(Level.FINE, "onPlaying");
 417         notifyPaused(false);
 418     }
 419 
 420     @Override
 421     public void onPause(PlayerStateEvent pse) {
 422         if (verbose) log.log(Level.FINE, "onPause, time: {0}", pse.getTime());
 423         notifyPaused(true);
 424     }
 425 
 426     @Override
 427     public void onStop(PlayerStateEvent pse) {
 428         if (verbose) log.log(Level.FINE, "onStop");
 429         notifyPaused(true);
 430     }
 431 
 432     @Override
 433     public void onStall(PlayerStateEvent pse) {
 434         if (verbose) log.log(Level.FINE, "onStall");
 435     }
 436 
 437     @Override
 438     public void onFinish(PlayerStateEvent pse) {
 439         MediaPlayer p = getPlayer();
 440         if (p != null) {
 441             finished = p.getRate() > 0 ? 1 : -1;
 442             if (verbose) log.log(Level.FINE, "onFinish, time: {0}", pse.getTime());
 443             notifyFinished();
 444         }
 445     }
 446 
 447     @Override
 448     public void onHalt(PlayerStateEvent pse) {
 449         if (verbose) log.log(Level.FINE, "onHalt");
 450     }
 451 
 452     // MediaErrorListener
 453     @Override
 454     public void onError(Object source, int errCode, String message) {
 455         //MediaPlayer p = getPlayer();
 456         if (verbose) {
 457             log.log(Level.WARNING, "onError, errCode={0}, msg={1}",
 458                     new Object[]{errCode, message});
 459         }
 460         // TODO: parse errCode to detect NETWORK_STATE_FORMAT_ERROR/
 461         // NETWORK_STATE_NETWORK_ERROR/NETWORK_STATE_DECODE_ERROR
 462         notifyNetworkStateChanged(NETWORK_STATE_NETWORK_ERROR);
 463         notifyReadyStateChanged(READY_STATE_HAVE_NOTHING);
 464     }
 465 
 466     //PlayerTimeListener
 467     @Override
 468     public void onDurationChanged(double duration) {
 469         if (verbose) log.log(Level.FINE, "onDurationChanged, duration={0}", duration);
 470         notifyDurationChanged((float)duration);
 471     }
 472 
 473     // VideoTrackSizeListener
 474     @Override
 475     public void onSizeChanged(int width, int height) {
 476         //MediaPlayer p = getPlayer();
 477         if (verbose) {
 478             log.log(Level.FINE, "onSizeChanged, new size = {0} x {1}",
 479                     new Object[]{width, height});
 480         }
 481         notifySizeChanged(width, height);
 482     }
 483 
 484     private void notifyFrameArrived() {
 485         if (!gotFirstFrame) {
 486             // this is the first frame
 487             // don't set HAVE_ENOUGH_DATA state before onReady
 488             if (getReadyState() >= READY_STATE_HAVE_METADATA) {
 489                 notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 490             }
 491             gotFirstFrame = true;
 492         }
 493         if (verbose && finished != 0) {
 494             log.log(Level.FINE, "notifyFrameArrived (after finished) time: {0}", getPlayer().getPresentationTime());
 495         }
 496         notifyNewFrame();
 497     }
 498 
 499     private float bufferedStart = 0f;
 500     private float bufferedEnd   = 0f;
 501     private boolean buffering   = false;
 502 
 503     private void updateBufferingStatus() {
 504         int newNetworkState =
 505                 buffering ? NETWORK_STATE_LOADING
 506                 : bufferedStart > 0 ? NETWORK_STATE_IDLE : NETWORK_STATE_LOADED;
 507         if (verbose) {
 508             log.log(Level.FINE, "updateBufferingStatus, buffered: [{0} - {1}], buffering = {2}",
 509                 new Object[]{bufferedStart, bufferedEnd, buffering});
 510         }
 511         notifyNetworkStateChanged(newNetworkState);
 512     }
 513 
 514     // BufferListener
 515     @Override
 516     public void onBufferProgress(BufferProgressEvent event) {
 517         /* event (in the current API):
 518          * double getDuration(): duration of the movie (seconds);
 519          * long getBufferStart(): start of the buffered data (bytes)
 520          * long getBufferStop(): end of the movie (bytes)
 521          * long getBufferPosition(): end of the buffered data (bytes)
 522          */
 523         // if duration is not yet known, we cannot calculate buffered ranges
 524         if (event.getDuration() < 0) {
 525             return;
 526         }
 527         double bytes2seconds = event.getDuration() / (double)event.getBufferStop();
 528         bufferedStart = (float)(bytes2seconds * event.getBufferStart());
 529         bufferedEnd = (float)(bytes2seconds * event.getBufferPosition());
 530         buffering = event.getBufferPosition() < event.getBufferStop();
 531 
 532         float ranges[] = new float[2];
 533         ranges[0] = bufferedStart;
 534         ranges[1] = bufferedEnd;
 535         int bytesLoaded = (int)(event.getBufferPosition() - event.getBufferStart());
 536         if (verbose) {
 537             log.log(Level.FINER, "onBufferProgress, "
 538                     + "bufferStart={0}, bufferStop={1}, bufferPos={2}, duration={3}; "
 539                     + "notify range [{4},[5]], bytesLoaded: {6}",
 540                     new Object[]{event.getBufferStart(), event.getBufferStop(),
 541                                  event.getBufferPosition(), event.getDuration(),
 542                                  ranges[0], ranges[1], bytesLoaded});
 543         }
 544         notifyBufferChanged(ranges, bytesLoaded);
 545         updateBufferingStatus();
 546     }
 547 
 548     /* Inner class that will listen for new frames from the jfxmedia player and
 549      * manage our own texture cache to remove the dependency on
 550      * PrismMediaFrameHandler
 551      */
 552     private final class MediaFrameListener implements VideoRendererListener {
 553         private final Object frameLock = new Object();
 554         private VideoDataBuffer currentFrame;
 555         private VideoDataBuffer nextFrame;
 556 
 557         public void videoFrameUpdated(NewFrameEvent nfe) {
 558             synchronized (frameLock) {
 559                 if (null != nextFrame) {
 560                     nextFrame.releaseFrame();
 561                 }
 562                 nextFrame = nfe.getFrameData();
 563                 if (null != nextFrame) {




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.webkit.prism;
  27 
  28 import java.net.URI;
  29 import java.util.List;
  30 
  31 import com.sun.javafx.media.PrismMediaFrameHandler;
  32 import com.sun.media.jfxmedia.Media;
  33 import com.sun.media.jfxmedia.MediaManager;
  34 import com.sun.media.jfxmedia.MediaPlayer;
  35 import com.sun.media.jfxmedia.control.VideoDataBuffer;
  36 import com.sun.media.jfxmedia.events.BufferListener;
  37 import com.sun.media.jfxmedia.events.BufferProgressEvent;
  38 import com.sun.media.jfxmedia.events.MediaErrorListener;
  39 import com.sun.media.jfxmedia.events.NewFrameEvent;
  40 import com.sun.media.jfxmedia.events.PlayerStateEvent;
  41 import com.sun.media.jfxmedia.events.PlayerStateListener;
  42 import com.sun.media.jfxmedia.events.PlayerTimeListener;
  43 import com.sun.media.jfxmedia.events.VideoRendererListener;
  44 import com.sun.media.jfxmedia.events.VideoTrackSizeListener;
  45 import com.sun.media.jfxmedia.locator.Locator;
  46 import com.sun.media.jfxmedia.track.AudioTrack;
  47 import com.sun.media.jfxmedia.track.Track;
  48 import com.sun.media.jfxmedia.track.VideoTrack;
  49 import com.sun.prism.Graphics;
  50 import com.sun.prism.Texture;


  90             player = p;
  91             installListeners();
  92             frameHandler = PrismMediaFrameHandler.getHandler(player);
  93         }
  94 
  95         finished = 0;
  96     }
  97 
  98     private final class CreateThread extends Thread {
  99         private boolean cancelled = false;
 100         private final String url;
 101         private final String userAgent;
 102         private CreateThread(String url, String userAgent) {
 103             this.url = url;
 104             this.userAgent = userAgent;
 105             gotFirstFrame = false;
 106         }
 107 
 108         @Override
 109         public void run() {
 110             log.fine("CreateThread: started, url={0}", url);
 111 
 112             notifyNetworkStateChanged(NETWORK_STATE_LOADING);
 113             notifyReadyStateChanged(READY_STATE_HAVE_NOTHING);
 114 
 115             MediaPlayer p = null;
 116 
 117             try {
 118                 Locator locator = new Locator(new URI(url));
 119                 if (userAgent != null) {
 120                     locator.setConnectionProperty("User-Agent", userAgent);
 121                 }
 122                 locator.init();

 123                     log.fine("CreateThread: locator created");

 124 
 125                 p = MediaManager.getPlayer(locator);
 126             } catch (Exception ex) {
 127                 log.warning("CreateThread ERROR: {0}", ex.toString());
 128                 ex.printStackTrace(System.out);


 129                 onError(this, 0, ex.getMessage());
 130                 return;
 131             }
 132 
 133             synchronized (lock) {
 134                 if (cancelled) {
 135                     log.fine("CreateThread: cancelled");
 136                     p.dispose();
 137                     return;
 138                 }
 139                 createThread = null;
 140                 setPlayer(p);
 141             }
 142             log.fine("CreateThread: completed");
 143         }
 144 
 145         private void cancel() {
 146             synchronized (lock) {
 147                 cancelled = true;
 148             }
 149         }
 150     }
 151 
 152 
 153     protected void load(String url, String userAgent) {
 154         synchronized (lock) {
 155             if (createThread != null) {
 156                 createThread.cancel();
 157             }
 158             disposePlayer();
 159             createThread = new CreateThread(url, userAgent);
 160         }
 161         // fx media player does not support loading only metadata,
 162         // so handle PRELOAD_METADATA as PRELOAD_AUTO (start loading)


 319         }
 320     }
 321 
 322     protected void setSize(int w, int h) {
 323         // nothing to do
 324     }
 325 
 326     protected void setPreservesPitch(boolean preserve) {
 327         // nothing to do
 328     }
 329 
 330     protected void renderCurrentFrame(WCGraphicsContext gc, int x, int y, int w, int h) {
 331         // TODO: need a render lock in MediaFrameHandler
 332         synchronized (lock) {
 333             renderImpl(gc, x, y, w, h);
 334         }
 335     }
 336 
 337 
 338     private void renderImpl(WCGraphicsContext gc, int x, int y, int w, int h) {
 339         log.finer(">>(Prism)renderImpl");
 340         Graphics g = (Graphics)gc.getPlatformGraphics();
 341 
 342         Texture texture = null;
 343         VideoDataBuffer currentFrame = frameListener.getLatestFrame();
 344 
 345         if (null != currentFrame) {
 346             if (null != frameHandler) {
 347                 texture = frameHandler.getTexture(g, currentFrame);
 348             }
 349             currentFrame.releaseFrame();
 350         }
 351 
 352         if (texture != null) {
 353             g.drawTexture(texture,
 354                     x, y, x + w, y + h,
 355                     0f, 0f, texture.getContentWidth(), texture.getContentHeight());
 356             texture.unlock();
 357         } else {
 358             log.finest("  (Prism)renderImpl, texture is null, draw black rect");
 359             gc.fillRect(x, y, w, h, 0xFF000000);
 360         }
 361         log.finer("<<(Prism)renderImpl");
 362     }
 363 
 364     // PlayerStateListener
 365     @Override
 366     public void onReady(PlayerStateEvent pse) {
 367         MediaPlayer p = getPlayer();
 368         log.fine("onReady");
 369         Media media = p.getMedia();
 370         boolean hasVideo = false;
 371         boolean hasAudio = false;
 372         if (media != null) {
 373             List<Track> tracks = media.getTracks();
 374             if (tracks != null) {
 375                 log.fine("{0} track(s) detected:", tracks.size());
 376                 for (Track track : tracks) {
 377                     if (track instanceof VideoTrack) {
 378                         hasVideo = true;
 379                     } else if (track instanceof AudioTrack) {
 380                         hasAudio = true;
 381                     }
 382                     log.fine("track: {0}", track);
 383                 }
 384             } else {
 385                 log.warning("onReady, tracks IS NULL");
 386             }
 387         } else {
 388             log.warning("onReady, media IS NULL");




 389         }
 390         log.fine("onReady, hasVideo:{0}, hasAudio: {1}", new Object[]{hasVideo, hasAudio});
 391         notifyReady(hasVideo, hasAudio, (float)p.getDuration());
 392 
 393         // if we have no video, report READY_STATE_HAVE_ENOUGH_DATA right now
 394         if (!hasVideo) {
 395             notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 396         } else {
 397             if (getReadyState() < READY_STATE_HAVE_METADATA) {
 398                 if (gotFirstFrame) {
 399                     notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 400                 } else {
 401                     notifyReadyStateChanged(READY_STATE_HAVE_METADATA);
 402                 }
 403             }
 404         }
 405     }
 406 
 407     @Override
 408     public void onPlaying(PlayerStateEvent pse) {
 409         log.fine("onPlaying");
 410         notifyPaused(false);
 411     }
 412 
 413     @Override
 414     public void onPause(PlayerStateEvent pse) {
 415         log.fine("onPause, time: {0}", pse.getTime());
 416         notifyPaused(true);
 417     }
 418 
 419     @Override
 420     public void onStop(PlayerStateEvent pse) {
 421         log.fine("onStop");
 422         notifyPaused(true);
 423     }
 424 
 425     @Override
 426     public void onStall(PlayerStateEvent pse) {
 427         log.fine("onStall");
 428     }
 429 
 430     @Override
 431     public void onFinish(PlayerStateEvent pse) {
 432         MediaPlayer p = getPlayer();
 433         if (p != null) {
 434             finished = p.getRate() > 0 ? 1 : -1;
 435             log.fine("onFinish, time: {0}", pse.getTime());
 436             notifyFinished();
 437         }
 438     }
 439 
 440     @Override
 441     public void onHalt(PlayerStateEvent pse) {
 442         log.fine("onHalt");
 443     }
 444 
 445     // MediaErrorListener
 446     @Override
 447     public void onError(Object source, int errCode, String message) {
 448         //MediaPlayer p = getPlayer();
 449         log.warning("onError, errCode={0}, msg={1}", new Object[]{errCode, message});



 450         // TODO: parse errCode to detect NETWORK_STATE_FORMAT_ERROR/
 451         // NETWORK_STATE_NETWORK_ERROR/NETWORK_STATE_DECODE_ERROR
 452         notifyNetworkStateChanged(NETWORK_STATE_NETWORK_ERROR);
 453         notifyReadyStateChanged(READY_STATE_HAVE_NOTHING);
 454     }
 455 
 456     //PlayerTimeListener
 457     @Override
 458     public void onDurationChanged(double duration) {
 459         log.fine("onDurationChanged, duration={0}", duration);
 460         notifyDurationChanged((float)duration);
 461     }
 462 
 463     // VideoTrackSizeListener
 464     @Override
 465     public void onSizeChanged(int width, int height) {
 466         //MediaPlayer p = getPlayer();
 467         log.fine("onSizeChanged, new size = {0} x {1}", new Object[]{width, height});



 468         notifySizeChanged(width, height);
 469     }
 470 
 471     private void notifyFrameArrived() {
 472         if (!gotFirstFrame) {
 473             // this is the first frame
 474             // don't set HAVE_ENOUGH_DATA state before onReady
 475             if (getReadyState() >= READY_STATE_HAVE_METADATA) {
 476                 notifyReadyStateChanged(READY_STATE_HAVE_ENOUGH_DATA);
 477             }
 478             gotFirstFrame = true;
 479         }
 480         if (finished != 0) {
 481             log.fine("notifyFrameArrived (after finished) time: {0}", getPlayer().getPresentationTime());
 482         }
 483         notifyNewFrame();
 484     }
 485 
 486     private float bufferedStart = 0f;
 487     private float bufferedEnd   = 0f;
 488     private boolean buffering   = false;
 489 
 490     private void updateBufferingStatus() {
 491         int newNetworkState =
 492                 buffering ? NETWORK_STATE_LOADING
 493                 : bufferedStart > 0 ? NETWORK_STATE_IDLE : NETWORK_STATE_LOADED;
 494         log.fine("updateBufferingStatus, buffered: [{0} - {1}], buffering = {2}",
 495             new Object[]{bufferedStart, bufferedEnd, buffering});


 496         notifyNetworkStateChanged(newNetworkState);
 497     }
 498 
 499     // BufferListener
 500     @Override
 501     public void onBufferProgress(BufferProgressEvent event) {
 502         /* event (in the current API):
 503          * double getDuration(): duration of the movie (seconds);
 504          * long getBufferStart(): start of the buffered data (bytes)
 505          * long getBufferStop(): end of the movie (bytes)
 506          * long getBufferPosition(): end of the buffered data (bytes)
 507          */
 508         // if duration is not yet known, we cannot calculate buffered ranges
 509         if (event.getDuration() < 0) {
 510             return;
 511         }
 512         double bytes2seconds = event.getDuration() / (double)event.getBufferStop();
 513         bufferedStart = (float)(bytes2seconds * event.getBufferStart());
 514         bufferedEnd = (float)(bytes2seconds * event.getBufferPosition());
 515         buffering = event.getBufferPosition() < event.getBufferStop();
 516 
 517         float ranges[] = new float[2];
 518         ranges[0] = bufferedStart;
 519         ranges[1] = bufferedEnd;
 520         int bytesLoaded = (int)(event.getBufferPosition() - event.getBufferStart());
 521         log.finer("onBufferProgress, "
 522                 + "bufferStart={0}, bufferStop={1}, bufferPos={2}, duration={3}; "
 523                 + "notify range [{4},[5]], bytesLoaded: {6}",
 524                 new Object[]{event.getBufferStart(), event.getBufferStop(),
 525                              event.getBufferPosition(), event.getDuration(),
 526                              ranges[0], ranges[1], bytesLoaded});


 527         notifyBufferChanged(ranges, bytesLoaded);
 528         updateBufferingStatus();
 529     }
 530 
 531     /* Inner class that will listen for new frames from the jfxmedia player and
 532      * manage our own texture cache to remove the dependency on
 533      * PrismMediaFrameHandler
 534      */
 535     private final class MediaFrameListener implements VideoRendererListener {
 536         private final Object frameLock = new Object();
 537         private VideoDataBuffer currentFrame;
 538         private VideoDataBuffer nextFrame;
 539 
 540         public void videoFrameUpdated(NewFrameEvent nfe) {
 541             synchronized (frameLock) {
 542                 if (null != nextFrame) {
 543                     nextFrame.releaseFrame();
 544                 }
 545                 nextFrame = nfe.getFrameData();
 546                 if (null != nextFrame) {


< prev index next >