Client LuaCsForBarotrauma
Video.cs
1 using System;
2 using Barotrauma.IO;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.Threading;
6 using System.Linq;
7 using System.Runtime.InteropServices;
8 using Microsoft.Xna.Framework;
9 using Microsoft.Xna.Framework.Graphics;
10 using Barotrauma.Sounds;
11 
13 {
14  partial class Video : IDisposable
15  {
16  private static Internal.EventCallback VideoFrameCallback;
17  private static Internal.EventCallback VideoAudioCallback;
18 
19  private static Dictionary<IntPtr, Video> videos;
20 
21  public static void Init()
22  {
23  if (VideoFrameCallback == null)
24  {
25  VideoFrameCallback = VideoFrameUpdate;
26  }
27 
28  if (VideoAudioCallback == null)
29  {
30  VideoAudioCallback = VideoAudioUpdate;
31  }
32 
33  if (videos == null)
34  {
35  videos = new Dictionary<IntPtr, Video>();
36  }
37  }
38 
39  public static void Close()
40  {
41  if (videos != null)
42  {
43  List<Video> vids = videos.Values.ToList();
44  foreach (Video v in vids)
45  {
46  v.Dispose();
47  }
48  }
49  }
50 
51  private IntPtr videoInternal;
52 
53  private Texture2D texture;
54  private bool textureChanged;
55  private Int32[] textureData;
56 
57  private object mutex;
58 
59  private VideoSound sound;
60 
61  public int Width { get; private set; }
62  public int Height { get; private set; }
63 
64  public float AudioGain
65  {
66  get { return sound == null ? 0.0f : sound.BaseGain; }
67  set { if (sound != null) { sound.BaseGain = value; } }
68  }
69 
70  public bool LoadFailed { get; private set; }
71 
72  public static Video Load(GraphicsDevice graphicsDevice, SoundManager soundManager, string filename)
73  {
74  Video video = new Video(graphicsDevice, soundManager, filename);
75  if (video.LoadFailed) { video = null; }
76  return video;
77  }
78 
79  private Video(GraphicsDevice graphicsDevice,SoundManager soundManager,string filename)
80  {
81  Init();
82 
83  videoInternal = Internal.loadVideo(filename);
84 
85  if (videoInternal == IntPtr.Zero) { LoadFailed = true; return; }
86 
87  mutex = new object();
88 
89  Width = Internal.getVideoWidth(videoInternal); Height = Internal.getVideoHeight(videoInternal);
90 
91  texture = new Texture2D(graphicsDevice, (int)Width, (int)Height);
92 
93  textureData = new Int32[Width * Height];
94  for (int i = 0; i < Width * Height; i++)
95  {
96  textureData[i] = unchecked((int)0xff000000);
97  }
98  texture.SetData(textureData);
99 
100  videos.Add(videoInternal, this);
101 
102  IntPtr videoFrameCallbackPtr = Marshal.GetFunctionPointerForDelegate(VideoFrameCallback);
103  Internal.setVideoFrameCallback(videoInternal, videoFrameCallbackPtr);
104  IntPtr videoAudioCallbackPtr = Marshal.GetFunctionPointerForDelegate(VideoAudioCallback);
105  Internal.setVideoAudioCallback(videoInternal, videoAudioCallbackPtr);
106 
107  sound = null;
108  if (Internal.videoHasAudio(videoInternal)==1)
109  {
110  int sampleRate = Internal.getVideoAudioSampleRate(videoInternal);
111  int channelCount = Internal.getVideoAudioChannelCount(videoInternal);
112  sound = new VideoSound(soundManager, filename, sampleRate, channelCount, this);
113  }
114 
115  textureChanged = false;
116 
117  Internal.playVideo(videoInternal);
118  }
119 
120  public void Play()
121  {
122  if (LoadFailed) { return; }
123  Internal.playVideo(videoInternal);
124  }
125 
126  public void Dispose()
127  {
128  if (LoadFailed) { return; }
129 
130  Internal.deleteVideo(videoInternal);
131  videos.Remove(videoInternal);
132 
133  sound?.Dispose();
134 
135  texture.Dispose();
136  }
137 
138  public bool IsPlaying
139  {
140  get
141  {
142  if (LoadFailed) { return false; }
143  return Internal.isVideoPlaying(videoInternal)==1;
144  }
145  }
146 
147  public Texture2D GetTexture()
148  {
149  if (LoadFailed) { return null; }
150  lock (mutex)
151  {
152  if (textureChanged)
153  {
154  texture.SetData(textureData);
155  textureChanged = false;
156  }
157 
158  if (sound!=null && !sound.IsPlaying() && IsPlaying) { sound.Play(); }
159  }
160 
161  return texture;
162  }
163 
164  public void SetFrameData(IntPtr data)
165  {
166  lock (mutex)
167  {
168  Marshal.Copy(data, textureData, 0, (int)(Width * Height));
169  textureChanged = true;
170  }
171  }
172 
173  static void VideoFrameUpdate(IntPtr videoInternal, IntPtr data, Int32 dataElemSize, Int32 dataLen)
174  {
175  Video video = videos[videoInternal];
176 
177  video.SetFrameData(data);
178  }
179 
180  static void VideoAudioUpdate(IntPtr videoInternal, IntPtr data, Int32 dataElemSize, Int32 dataLen)
181  {
182  Video video = videos[videoInternal];
183 
184  if (video.sound != null && dataLen > 0)
185  {
186  //TODO: reduce garbage?
187  short[] newBuf = new short[dataLen];
188  Marshal.Copy(data, newBuf, 0, dataLen);
189  video.sound.Enqueue(newBuf);
190  }
191  }
192  }
193 }
void SetFrameData(IntPtr data)
Definition: Video.cs:164
static Video Load(GraphicsDevice graphicsDevice, SoundManager soundManager, string filename)
Definition: Video.cs:72
static void Close()
Definition: Video.cs:39
Texture2D GetTexture()
Definition: Video.cs:147
static void Init()
Definition: Video.cs:21
override SoundChannel Play(float gain, float range, Vector2 position, bool muffle=false)
Definition: VideoSound.cs:58
void Enqueue(short[] buf)
Definition: VideoSound.cs:50
override bool IsPlaying()
Definition: VideoSound.cs:40