mpeg1.bmx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. ' Copyright (c) 2024 Bruce A Henderson
  2. '
  3. ' Permission is hereby granted, free of charge, to any person obtaining a copy
  4. ' of this software and associated documentation files (the "Software"), to deal
  5. ' in the Software without restriction, including without limitation the rights
  6. ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. ' copies of the Software, and to permit persons to whom the Software is
  8. ' furnished to do so, subject to the following conditions:
  9. '
  10. ' The above copyright notice and this permission notice shall be included in
  11. ' all copies or substantial portions of the Software.
  12. '
  13. ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. ' THE SOFTWARE.
  20. '
  21. SuperStrict
  22. Rem
  23. bbdoc: Video/Mpeg1 playback.
  24. End Rem
  25. Module Video.Mpeg1
  26. ModuleInfo "Version: 1.00"
  27. ModuleInfo "License: MIT"
  28. ModuleInfo "Copyright: pl_mpeg - 2019 Dominic Szablewski"
  29. ModuleInfo "Copyright: Wrapper - 2024 Bruce A Henderson"
  30. ModuleInfo "History: 1.00 Initial Release"
  31. Import "common.bmx"
  32. ' Notes
  33. '
  34. ' Changes made to pl_mpeg.h to support a PLM_BUFFER_MODE_STREAM mode.
  35. '
  36. Rem
  37. bbdoc: An MPEG1 video player.
  38. End Rem
  39. Type TMpeg1
  40. Field mpgPtr:Byte Ptr
  41. Field mpegStream:TMpeg1Stream
  42. Field videoHandler:IVideoHandler
  43. Field pix:TPixmap
  44. Method New(mpegStream:TMpeg1Stream, videoHandler:IVideoHandler)
  45. mpgPtr = bmx_mpeg1_create(Self, mpegStream.buffer, True)
  46. Self.mpegStream = mpegStream
  47. Self.videoHandler = videoHandler
  48. pix = videoHandler.Pixmap(Width(), Height(), PF_RGB888)
  49. End Method
  50. Rem
  51. bbdoc: Loads a video from a file.
  52. End Rem
  53. Function Load:TMpeg1(filename:String, videoHandler:IVideoHandler)
  54. If videoHandler = Null Then
  55. Throw "videoHandler is required"
  56. End If
  57. Local stream:TStream = ReadStream(filename)
  58. If stream Then
  59. Return Load(stream, videoHandler)
  60. End If
  61. End Function
  62. Rem
  63. bbdoc: Loads a video from a stream.
  64. End Rem
  65. Function Load:TMpeg1(stream:TStream, videoHandler:IVideoHandler)
  66. If videoHandler = Null Then
  67. Throw "videoHandler is required"
  68. End If
  69. Local mpegStream:TMpeg1Stream = New TMpeg1Stream(stream)
  70. Local mpg:TMpeg1 = New TMpeg1(mpegStream, videoHandler)
  71. videoHandler.InitAudio(mpg)
  72. Return mpg
  73. End Function
  74. Method Delete()
  75. If mpgPtr Then
  76. bmx_mpeg1_destroy(mpgPtr)
  77. mpgPtr = Null
  78. End If
  79. End Method
  80. Rem
  81. bbdoc: Returns the width of the video, in pixels.
  82. End Rem
  83. Method Width:Int()
  84. Return plm_get_width(mpgPtr)
  85. End Method
  86. Rem
  87. bbdoc: Returns the height of the video, in pixels.
  88. End Rem
  89. Method Height:Int()
  90. Return plm_get_height(mpgPtr)
  91. End Method
  92. Rem
  93. bbdoc: Returns #Tue if video decoding is enabled.
  94. End Rem
  95. Method GetVideoEnabled:Int()
  96. Return plm_get_video_enabled(mpgPtr)
  97. End Method
  98. Rem
  99. bbdoc: Enables or disables video decoding.
  100. about: If video is disabled, the video decode callback will not be called.
  101. End Rem
  102. Method SetVideoEnabled(videoEnabled:Int)
  103. plm_set_video_enabled(mpgPtr, videoEnabled)
  104. End Method
  105. Rem
  106. bbdoc: Returns #True if audio decoding is enabled.
  107. End Rem
  108. Method GetAudioEnabled:Int()
  109. Return plm_get_audio_enabled(mpgPtr)
  110. End Method
  111. Rem
  112. bbdoc: Enables or disables audio decoding.
  113. about: If audio is disabled, the audio decode callback will not be called.
  114. End Rem
  115. Method SetAudioEnabled(audioEnabled:Int)
  116. plm_set_audio_enabled(mpgPtr, audioEnabled)
  117. End Method
  118. Rem
  119. bbdoc: Returns the current internal time of the video, in seconds.
  120. End Rem
  121. Method GetTime:Double()
  122. Return plm_get_time(mpgPtr)
  123. End Method
  124. Rem
  125. bbdoc: Advances the internal timer by @elapsedTime seconds and decode video/audio up to this time.
  126. about: This will call the video decode callback and audio decode callback any number
  127. of times. A frame-skip is not implemented, i.e. everything up to current time will be decoded.
  128. End Rem
  129. Method Decode(elapsedTime:Double)
  130. plm_decode(mpgPtr, elapsedTime)
  131. End Method
  132. Rem
  133. bbdoc: Returns the current framerate of the video.
  134. End Rem
  135. Method Framerate:Double()
  136. Return plm_get_framerate(mpgPtr)
  137. End Method
  138. Rem
  139. bbdoc: Returns the current samplerate of the video.
  140. End Rem
  141. Method Samplerate:Int()
  142. Return plm_get_samplerate(mpgPtr)
  143. End Method
  144. Rem
  145. bbdoc: Returns the duration of the video in seconds.
  146. End Rem
  147. Method Duration:Double()
  148. Return plm_get_duration(mpgPtr)
  149. End Method
  150. Rem
  151. bbdoc: Return #True if the video has ended.
  152. End Rem
  153. Method HasEnded:Int()
  154. Return plm_has_ended(mpgPtr)
  155. End Method
  156. Rem
  157. bbdoc: Sets the the audio lead time in seconds - the time in which audio samples are decoded in advance (or behind) the video decode time.
  158. about: Typically this should be set to the duration of the buffer of the audio API that you use for output.
  159. End Rem
  160. Method SetAudioLeadTime(leadTime:Double)
  161. plm_set_audio_lead_time(mpgPtr, leadTime)
  162. End Method
  163. Rem
  164. bbdoc: Returns whether looping is enabled.
  165. End Rem
  166. Method GetLoop:Int()
  167. Return plm_get_loop(mpgPtr)
  168. End Method
  169. Rem
  170. bbdoc: Sets the looping mode.
  171. about: If loop is set to #True, the video will loop when it reaches the end, otherwise it will stop.
  172. End Rem
  173. Method SetLoop(loop:Int)
  174. plm_set_loop(mpgPtr, loop)
  175. End Method
  176. Function _LoadCallback(stream:TMpeg1Stream, buffer:SMpeg1Buffer Ptr) { nomangle }
  177. stream.Read()
  178. End Function
  179. Function _SeekCallback(stream:TMpeg1Stream, buffer:SMpeg1Buffer Ptr, offset:Size_T) { nomangle }
  180. stream.Seek(offset)
  181. End Function
  182. Function _VideoCallback(mpg:TMpeg1, frame:SMpeg1Frame Ptr) { nomangle }
  183. If mpg.videoHandler Then
  184. If mpg.pix.format = PF_RGB888 Then
  185. plm_frame_to_rgb(frame, mpg.pix.pixels, frame.width * 3)
  186. Else If mpg.pix.format = PF_RGBA8888 Then
  187. bmx_plm_frame_to_rgba(frame, mpg.pix.pixels, frame.width * 4, True, mpg.pix.capacity)
  188. End If
  189. mpg.videoHandler.VideoCallback(mpg.pix)
  190. End If
  191. End Function
  192. Function _AudioCallback(mpg:TMpeg1, frame:SMpeg1Samples Ptr) { nomangle }
  193. If mpg.videoHandler Then
  194. mpg.videoHandler.AudioCallback(frame)
  195. End If
  196. End Function
  197. End Type
  198. Interface IVideoHandler
  199. Method VideoCallback(pix:TPixmap)
  200. Method AudioCallback(frame:SMpeg1Samples Ptr)
  201. Method Pixmap:TPixmap(width:Int, height:Int, format:Int)
  202. Method InitAudio(mpg:TMpeg1)
  203. End Interface
  204. Type TMpeg1Stream
  205. Field buffer:SMpeg1Buffer Ptr
  206. Field stream:TStream
  207. Field buf:Byte[4096]
  208. Method New(stream:TStream)
  209. buffer = bmx_mpeg1_create_buffer(Self, Size_T(stream.Size()))
  210. Self.stream = stream
  211. End Method
  212. Method Read()
  213. If buffer.discardReadBytes Then
  214. plm_buffer_discard_read_bytes(buffer)
  215. End If
  216. Local bytesAvailable:Size_T = buffer.capacity - buffer.length
  217. Local bytesRead:Size_T = stream.Read(buffer.bytes + buffer.length, bytesAvailable)
  218. buffer.length :+ bytesRead
  219. If bytesRead = 0 Then
  220. buffer.hasEnded = True
  221. End If
  222. End Method
  223. Method Seek(offset:Size_T)
  224. stream.Seek(offset)
  225. buffer.bitIndex = 0
  226. buffer.length = 0
  227. End Method
  228. End Type