video.adoc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. = Video
  2. :author:
  3. :revnumber:
  4. :revdate: 2016/03/17 20:48
  5. :relfileprefix: ../../
  6. :imagesdir: ../..
  7. ifdef::env-github,env-browser[:outfilesuffix: .adoc]
  8. [WARNING]
  9. ====
  10. This +++<abbr title="Application Programming Interface">API</abbr>+++ is deprecated.
  11. ====
  12. Relevant forum topics:
  13. link:http://hub.jmonkeyengine.org/t/ive-made-a-movieappstate-so-you-dont-have-to/31673[http://hub.jmonkeyengine.org/t/ive-made-a-movieappstate-so-you-dont-have-to/31673]
  14. link:http://hub.jmonkeyengine.org/t/news-about-playing-videos-on-jme/30084/5[http://hub.jmonkeyengine.org/t/news-about-playing-videos-on-jme/30084/5]
  15. link:https://jvm-gaming.org/t/yunpm-a-java-media-player/39517[YUNPM - a Java Media Player] (java-gaming.org)
  16. link:http://www.java-gaming.org/topics/gstlwjgl-yet-another-media-player/27146/view.html[GstLWJGL] (java-gaming.org)
  17. link:http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/util/av/package-summary.html[GL Media Player] (jogamp.org)
  18. link:http://www.xuggle.com/xuggler[Xuggler]
  19. jMonkeyEngine supports Jheora Ogg video (`com.jme3.video`).
  20. You create either a file inputstream to load the video from your hard drive:
  21. [source,java]
  22. ----
  23. FileInputStream fis = new FileInputStream("E:\\my_bunny.ogg");
  24. ----
  25. Or you stream the video live from a web location:
  26. [source,java]
  27. ----
  28. InputStream fis = new URL("http://server/my_video.ogg").openStream();
  29. ----
  30. Setting the queued frames to a value value higher than 5 (`videoQueue = new VQueue(5);`) will make web streamed playback smoother at the cost of memory.
  31. Here is an example of video streaming in context:
  32. [source,java]
  33. ----
  34. private void createVideo(){
  35. try {
  36. InputStream fis = new URL("http://mirrorblender.top-ix.org/peach/"+
  37. "bigbuckbunny_movies/big_buck_bunny_480p_stereo.ogg").openStream();
  38. videoQueue = new VQueue(5); // streaming quality vs memory
  39. decoder = new AVThread(fis, videoQueue);
  40. videoThread = new Thread(decoder, "Jheora Video Decoder");
  41. videoThread.setDaemon(true);
  42. videoThread.start();
  43. masterClock = decoder.getMasterClock();
  44. } catch (IOException ex) {
  45. ex.printStackTrace();
  46. }
  47. }
  48. ----
  49. Use the simpleUpdate() method to play the audio:
  50. [source,java]
  51. ----
  52. @Override
  53. public void simpleUpdate(float tpf){
  54. if (source == null){
  55. if (decoder.getAudioStream() != null){
  56. source = new AudioNode(decoder.getAudioStream(), null);
  57. source.setPositional(false);
  58. source.setReverbEnabled(false);
  59. audioRenderer.playSource(source);
  60. }else{
  61. // uncomment this statement to be able to play videos
  62. // without audio.
  63. return;
  64. }
  65. }
  66. if (waitTime > 0){
  67. waitTime -= tpf;
  68. if (waitTime > 0)
  69. return;
  70. else{
  71. waitTime = 0;
  72. drawFrame(frameToDraw);
  73. frameToDraw = null;
  74. }
  75. }else{
  76. VFrame frame;
  77. try {
  78. frame = videoQueue.take();
  79. } catch (InterruptedException ex){
  80. stop();
  81. return;
  82. }
  83. if (frame.getTime() < lastFrameTime){
  84. videoQueue.returnFrame(frame);
  85. return;
  86. }
  87. if (frame.getTime() == -2){
  88. // end of stream
  89. System.out.println("End of stream");
  90. stop();
  91. return;
  92. }
  93. long AV_SYNC_THRESHOLD = 1 * Clock.MILLIS_TO_NANOS;
  94. long delay = frame.getTime() - lastFrameTime;
  95. long diff = frame.getTime() - masterClock.getTime();
  96. long syncThresh = delay > AV_SYNC_THRESHOLD ? delay : AV_SYNC_THRESHOLD;
  97. // if difference is more than 1 second, synchronize.
  98. if (Math.abs(diff) < Clock.SECONDS_TO_NANOS){
  99. if(diff <= -syncThresh) {
  100. delay = 0;
  101. } else if(diff >= syncThresh) {
  102. delay = 2 * delay;
  103. }
  104. }
  105. System.out.println("M: "+decoder.getSystemClock().getTimeSeconds()+
  106. ", V: "+decoder.getVideoClock().getTimeSeconds()+
  107. ", A: "+decoder.getAudioClock().getTimeSeconds());
  108. if (delay > 0){
  109. waitNanos(delay);
  110. drawFrame(frame);
  111. }else{
  112. videoQueue.returnFrame(frame);
  113. lastFrameTime = frame.getTime();
  114. }
  115. }
  116. }
  117. ----
  118. Helper Methods:
  119. [source,java]
  120. ----
  121. private void drawFrame(VFrame frame){
  122. Image image = frame.getImage();
  123. frame.setImage(image);
  124. picture.setTexture(assetManager, frame, false);
  125. // note: this forces renderer to upload frame immediately,
  126. // since it is going to be returned to the video queue pool
  127. // it could be used again.
  128. renderer.setTexture(0, frame);
  129. videoQueue.returnFrame(frame);
  130. lastFrameTime = frame.getTime();
  131. }
  132. ----
  133. [source,java]
  134. ----
  135. private void waitNanos(long time){
  136. long millis = (long) (time / Clock.MILLIS_TO_NANOS);
  137. int nanos = (int) (time - (millis * Clock.MILLIS_TO_NANOS));
  138. try {
  139. Thread.sleep(millis, nanos);
  140. }catch (InterruptedException ex){
  141. stop();
  142. return;
  143. }
  144. }
  145. ----