move VideoPlayer functions to Video
							parent
							
								
									845881533b
								
							
						
					
					
						commit
						3966a0c4ea
					
				|  | @ -1,42 +1,66 @@ | ||||||
| /* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/Video.cs */ | /* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */ | ||||||
| using System; | using System; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | using MoonWorks.Graphics; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Video | namespace MoonWorks.Video | ||||||
| { | { | ||||||
| 	public class Video : IDisposable | 	public enum VideoState | ||||||
| 	{ | 	{ | ||||||
| 		public IntPtr Handle => handle; | 		Playing, | ||||||
| 		public int YWidth => yWidth; | 		Paused, | ||||||
| 		public int YHeight => yHeight; | 		Stopped | ||||||
| 		public int UVWidth => uvWidth; | 	} | ||||||
| 		public int UVHeight => uvHeight; |  | ||||||
| 		public double FramesPerSecond => fps; |  | ||||||
| 
 | 
 | ||||||
| 		private IntPtr handle; | 	public unsafe class Video : IDisposable | ||||||
|  | 	{ | ||||||
|  | 		private IntPtr Handle; | ||||||
|  | 
 | ||||||
|  | 		public bool Loop { get; set; } | ||||||
|  | 		public bool Mute { get; set; } | ||||||
|  | 		public float Volume { get; set; } | ||||||
|  | 		public double FramesPerSecond => fps; | ||||||
|  | 		private VideoState State = VideoState.Stopped; | ||||||
|  | 
 | ||||||
|  | 		private double fps; | ||||||
| 		private int yWidth; | 		private int yWidth; | ||||||
| 		private int yHeight; | 		private int yHeight; | ||||||
| 		private int uvWidth; | 		private int uvWidth; | ||||||
| 		private int uvHeight; | 		private int uvHeight; | ||||||
| 		private double fps; | 
 | ||||||
|  | 		private void* yuvData = null; | ||||||
|  | 		private int yuvDataLength; | ||||||
|  | 		private int currentFrame; | ||||||
|  | 
 | ||||||
|  | 		private GraphicsDevice GraphicsDevice; | ||||||
|  | 		private Texture RenderTexture = null; | ||||||
|  | 		private Texture yTexture = null; | ||||||
|  | 		private Texture uTexture = null; | ||||||
|  | 		private Texture vTexture = null; | ||||||
|  | 		private Sampler LinearSampler; | ||||||
|  | 
 | ||||||
|  | 		private Stopwatch timer; | ||||||
| 
 | 
 | ||||||
| 		private bool disposed; | 		private bool disposed; | ||||||
| 
 | 
 | ||||||
| 		public Video(string filename) | 		public Video(GraphicsDevice graphicsDevice, string filename) | ||||||
| 		{ | 		{ | ||||||
| 			Theorafile.th_pixel_fmt format; | 			GraphicsDevice = graphicsDevice; | ||||||
| 
 | 
 | ||||||
| 			if (!System.IO.File.Exists(filename)) | 			if (!System.IO.File.Exists(filename)) | ||||||
| 			{ | 			{ | ||||||
| 				throw new ArgumentException("Video file not found!"); | 				throw new ArgumentException("Video file not found!"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (Theorafile.tf_fopen(filename, out handle) < 0) | 			if (Theorafile.tf_fopen(filename, out Handle) < 0) | ||||||
| 			{ | 			{ | ||||||
| 				throw new ArgumentException("Invalid video file!"); | 				throw new ArgumentException("Invalid video file!"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			Theorafile.th_pixel_fmt format; | ||||||
| 			Theorafile.tf_videoinfo( | 			Theorafile.tf_videoinfo( | ||||||
| 				handle, | 				Handle, | ||||||
| 				out yWidth, | 				out yWidth, | ||||||
| 				out yHeight, | 				out yHeight, | ||||||
| 				out fps, | 				out fps, | ||||||
|  | @ -62,6 +86,193 @@ namespace MoonWorks.Video | ||||||
| 			{ | 			{ | ||||||
| 				throw new NotSupportedException("Unrecognized YUV format!"); | 				throw new NotSupportedException("Unrecognized YUV format!"); | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			yuvDataLength = ( | ||||||
|  | 				(yWidth * yHeight) + | ||||||
|  | 				(uvWidth * uvHeight * 2) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			yuvData = NativeMemory.Alloc((nuint) yuvDataLength); | ||||||
|  | 
 | ||||||
|  | 			InitializeTheoraStream(); | ||||||
|  | 
 | ||||||
|  | 			if (Theorafile.tf_hasvideo(Handle) == 1) | ||||||
|  | 			{ | ||||||
|  | 				RenderTexture = Texture.CreateTexture2D( | ||||||
|  | 					GraphicsDevice, | ||||||
|  | 					(uint) yWidth, | ||||||
|  | 					(uint) yHeight, | ||||||
|  | 					TextureFormat.R8G8B8A8, | ||||||
|  | 					TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				yTexture = Texture.CreateTexture2D( | ||||||
|  | 					GraphicsDevice, | ||||||
|  | 					(uint) yWidth, | ||||||
|  | 					(uint) yHeight, | ||||||
|  | 					TextureFormat.R8, | ||||||
|  | 					TextureUsageFlags.Sampler | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				uTexture = Texture.CreateTexture2D( | ||||||
|  | 					GraphicsDevice, | ||||||
|  | 					(uint) uvWidth, | ||||||
|  | 					(uint) uvHeight, | ||||||
|  | 					TextureFormat.R8, | ||||||
|  | 					TextureUsageFlags.Sampler | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				vTexture = Texture.CreateTexture2D( | ||||||
|  | 					GraphicsDevice, | ||||||
|  | 					(uint) uvWidth, | ||||||
|  | 					(uint) uvHeight, | ||||||
|  | 					TextureFormat.R8, | ||||||
|  | 					TextureUsageFlags.Sampler | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				LinearSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			timer = new Stopwatch(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		public void Play(bool loop = false) | ||||||
|  | 		{ | ||||||
|  | 			if (State == VideoState.Playing) | ||||||
|  | 			{ | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			Loop = loop; | ||||||
|  | 			timer.Start(); | ||||||
|  | 
 | ||||||
|  | 			State = VideoState.Playing; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		public void Pause() | ||||||
|  | 		{ | ||||||
|  | 			if (State != VideoState.Playing) | ||||||
|  | 			{ | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			timer.Stop(); | ||||||
|  | 
 | ||||||
|  | 			State = VideoState.Paused; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		public void Stop() | ||||||
|  | 		{ | ||||||
|  | 			if (State == VideoState.Stopped) | ||||||
|  | 			{ | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			timer.Stop(); | ||||||
|  | 			timer.Reset(); | ||||||
|  | 
 | ||||||
|  | 			Theorafile.tf_reset(Handle); | ||||||
|  | 
 | ||||||
|  | 			State = VideoState.Stopped; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		public Texture GetTexture() | ||||||
|  | 		{ | ||||||
|  | 			if (RenderTexture == null) | ||||||
|  | 			{ | ||||||
|  | 				throw new InvalidOperationException(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (State == VideoState.Stopped) | ||||||
|  | 			{ | ||||||
|  | 				return RenderTexture; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			int thisFrame = (int) (timer.Elapsed.TotalMilliseconds / (1000.0 / FramesPerSecond)); | ||||||
|  | 			if (thisFrame > currentFrame) | ||||||
|  | 			{ | ||||||
|  | 				if (Theorafile.tf_readvideo( | ||||||
|  | 					Handle, | ||||||
|  | 					(IntPtr) yuvData, | ||||||
|  | 					thisFrame - currentFrame | ||||||
|  | 				) == 1 || currentFrame == -1) { | ||||||
|  | 					UpdateTexture(); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				currentFrame = thisFrame; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			bool ended = Theorafile.tf_eos(Handle) == 1; | ||||||
|  | 			if (ended) | ||||||
|  | 			{ | ||||||
|  | 				timer.Stop(); | ||||||
|  | 				timer.Reset(); | ||||||
|  | 
 | ||||||
|  | 				Theorafile.tf_reset(Handle); | ||||||
|  | 
 | ||||||
|  | 				if (Loop) | ||||||
|  | 				{ | ||||||
|  | 					// Start over! | ||||||
|  | 					InitializeTheoraStream(); | ||||||
|  | 
 | ||||||
|  | 					timer.Start(); | ||||||
|  | 
 | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					State = VideoState.Stopped; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return RenderTexture; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private void UpdateTexture() | ||||||
|  | 		{ | ||||||
|  | 			var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); | ||||||
|  | 
 | ||||||
|  | 			commandBuffer.SetTextureDataYUV( | ||||||
|  | 				yTexture, | ||||||
|  | 				uTexture, | ||||||
|  | 				vTexture, | ||||||
|  | 				(IntPtr) yuvData, | ||||||
|  | 				(uint) yuvDataLength | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			commandBuffer.BeginRenderPass( | ||||||
|  | 				new ColorAttachmentInfo(RenderTexture, Color.Black) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline); | ||||||
|  | 			commandBuffer.BindFragmentSamplers( | ||||||
|  | 				new TextureSamplerBinding(yTexture, LinearSampler), | ||||||
|  | 				new TextureSamplerBinding(uTexture, LinearSampler), | ||||||
|  | 				new TextureSamplerBinding(vTexture, LinearSampler) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			commandBuffer.DrawPrimitives(0, 1, 0, 0); | ||||||
|  | 
 | ||||||
|  | 			commandBuffer.EndRenderPass(); | ||||||
|  | 
 | ||||||
|  | 			GraphicsDevice.Submit(commandBuffer); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private void InitializeTheoraStream() | ||||||
|  | 		{ | ||||||
|  | 			// Grab the first video frame ASAP. | ||||||
|  | 			while (Theorafile.tf_readvideo(Handle, (IntPtr) yuvData, 1) == 0); | ||||||
|  | 
 | ||||||
|  | 			// Grab the first bit of audio. We're trying to start the decoding ASAP. | ||||||
|  | 			if (Theorafile.tf_hasaudio(Handle) == 1) | ||||||
|  | 			{ | ||||||
|  | 				int channels, samplerate; | ||||||
|  | 				Theorafile.tf_audioinfo(Handle, out channels, out samplerate); | ||||||
|  | 
 | ||||||
|  | 				// TODO: audio stream | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			currentFrame = -1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		protected virtual void Dispose(bool disposing) | 		protected virtual void Dispose(bool disposing) | ||||||
|  | @ -70,10 +281,17 @@ namespace MoonWorks.Video | ||||||
| 			{ | 			{ | ||||||
| 				if (disposing) | 				if (disposing) | ||||||
| 				{ | 				{ | ||||||
| 					// TODO: dispose managed state (managed objects) | 					// dispose managed state (managed objects) | ||||||
|  | 					RenderTexture.Dispose(); | ||||||
|  | 					yTexture.Dispose(); | ||||||
|  | 					uTexture.Dispose(); | ||||||
|  | 					vTexture.Dispose(); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				Theorafile.tf_close(ref handle); | 				// free unmanaged resources (unmanaged objects) | ||||||
|  | 				Theorafile.tf_close(ref Handle); | ||||||
|  | 				NativeMemory.Free(yuvData); | ||||||
|  | 
 | ||||||
| 				disposed = true; | 				disposed = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1,285 +0,0 @@ | ||||||
| /* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */ |  | ||||||
| using System; |  | ||||||
| using System.Diagnostics; |  | ||||||
| using System.Runtime.InteropServices; |  | ||||||
| using MoonWorks.Graphics; |  | ||||||
| 
 |  | ||||||
| namespace MoonWorks.Video |  | ||||||
| { |  | ||||||
| 	public enum VideoState |  | ||||||
| 	{ |  | ||||||
| 		Playing, |  | ||||||
| 		Paused, |  | ||||||
| 		Stopped |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public unsafe class VideoPlayer : IDisposable |  | ||||||
| 	{ |  | ||||||
| 		public bool Loop { get; set; } |  | ||||||
| 		public bool Mute { get; set; } |  | ||||||
| 		public float Volume { get; set; } |  | ||||||
| 
 |  | ||||||
| 		private Video Video = null; |  | ||||||
| 		private VideoState State = VideoState.Stopped; |  | ||||||
| 
 |  | ||||||
| 		private void* yuvData = null; |  | ||||||
| 		private int yuvDataLength; |  | ||||||
| 		private int currentFrame; |  | ||||||
| 
 |  | ||||||
| 		private GraphicsDevice GraphicsDevice; |  | ||||||
| 		private Texture RenderTexture = null; |  | ||||||
| 		private Texture[] YUVTextures = new Texture[3]; |  | ||||||
| 		private Sampler LinearSampler; |  | ||||||
| 
 |  | ||||||
| 		private Stopwatch timer; |  | ||||||
| 
 |  | ||||||
| 		private bool disposed; |  | ||||||
| 
 |  | ||||||
| 		public VideoPlayer(GraphicsDevice graphicsDevice) |  | ||||||
| 		{ |  | ||||||
| 			GraphicsDevice = graphicsDevice; |  | ||||||
| 			timer = new Stopwatch(); |  | ||||||
| 
 |  | ||||||
| 			LinearSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Load(Video video) |  | ||||||
| 		{ |  | ||||||
| 			Video = video; |  | ||||||
| 			State = VideoState.Stopped; |  | ||||||
| 
 |  | ||||||
| 			if (yuvData != null) |  | ||||||
| 			{ |  | ||||||
| 				NativeMemory.Free(yuvData); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			yuvDataLength = ( |  | ||||||
| 				(Video.YWidth * Video.YHeight) + |  | ||||||
| 				(Video.UVWidth * video.UVHeight * 2) |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			yuvData = NativeMemory.Alloc((nuint) yuvDataLength); |  | ||||||
| 
 |  | ||||||
| 			InitializeTheoraStream(); |  | ||||||
| 
 |  | ||||||
| 			if (Theorafile.tf_hasvideo(Video.Handle) == 1) |  | ||||||
| 			{ |  | ||||||
| 				if (RenderTexture != null) |  | ||||||
| 				{ |  | ||||||
| 					RenderTexture.Dispose(); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				RenderTexture = Texture.CreateTexture2D( |  | ||||||
| 					GraphicsDevice, |  | ||||||
| 					(uint) Video.YWidth, |  | ||||||
| 					(uint) Video.YHeight, |  | ||||||
| 					TextureFormat.R8G8B8A8, |  | ||||||
| 					TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler |  | ||||||
| 				); |  | ||||||
| 
 |  | ||||||
| 				for (int i = 0; i < 3; i += 1) |  | ||||||
| 				{ |  | ||||||
| 					if (YUVTextures[i] != null) |  | ||||||
| 					{ |  | ||||||
| 						YUVTextures[i].Dispose(); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				YUVTextures[0] = Texture.CreateTexture2D( |  | ||||||
| 					GraphicsDevice, |  | ||||||
| 					(uint) Video.YWidth, |  | ||||||
| 					(uint) Video.YHeight, |  | ||||||
| 					TextureFormat.R8, |  | ||||||
| 					TextureUsageFlags.Sampler |  | ||||||
| 				); |  | ||||||
| 
 |  | ||||||
| 				YUVTextures[1] = Texture.CreateTexture2D( |  | ||||||
| 					GraphicsDevice, |  | ||||||
| 					(uint) Video.UVWidth, |  | ||||||
| 					(uint) Video.UVHeight, |  | ||||||
| 					TextureFormat.R8, |  | ||||||
| 					TextureUsageFlags.Sampler |  | ||||||
| 				); |  | ||||||
| 
 |  | ||||||
| 				YUVTextures[2] = Texture.CreateTexture2D( |  | ||||||
| 					GraphicsDevice, |  | ||||||
| 					(uint) Video.UVWidth, |  | ||||||
| 					(uint) Video.UVHeight, |  | ||||||
| 					TextureFormat.R8, |  | ||||||
| 					TextureUsageFlags.Sampler |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Play(bool loop = false) |  | ||||||
| 		{ |  | ||||||
| 			if (State == VideoState.Playing) |  | ||||||
| 			{ |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Loop = loop; |  | ||||||
| 			timer.Start(); |  | ||||||
| 
 |  | ||||||
| 			State = VideoState.Playing; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Pause() |  | ||||||
| 		{ |  | ||||||
| 			if (State == VideoState.Paused) |  | ||||||
| 			{ |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			timer.Stop(); |  | ||||||
| 
 |  | ||||||
| 			State = VideoState.Paused; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Stop() |  | ||||||
| 		{ |  | ||||||
| 			if (State == VideoState.Stopped) |  | ||||||
| 			{ |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			timer.Stop(); |  | ||||||
| 			timer.Reset(); |  | ||||||
| 
 |  | ||||||
| 			Theorafile.tf_reset(Video.Handle); |  | ||||||
| 
 |  | ||||||
| 			State = VideoState.Stopped; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public Texture GetTexture() |  | ||||||
| 		{ |  | ||||||
| 			if (Video == null) |  | ||||||
| 			{ |  | ||||||
| 				throw new InvalidOperationException(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (State == VideoState.Stopped || Video.Handle == IntPtr.Zero || Theorafile.tf_hasvideo(Video.Handle) == 0) |  | ||||||
| 			{ |  | ||||||
| 				return RenderTexture; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			int thisFrame = (int) (timer.Elapsed.TotalMilliseconds / (1000.0 / Video.FramesPerSecond)); |  | ||||||
| 			if (thisFrame > currentFrame) |  | ||||||
| 			{ |  | ||||||
| 				if (Theorafile.tf_readvideo( |  | ||||||
| 					Video.Handle, |  | ||||||
| 					(IntPtr) yuvData, |  | ||||||
| 					thisFrame - currentFrame |  | ||||||
| 				) == 1 || currentFrame == -1) { |  | ||||||
| 					UpdateTexture(); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				currentFrame = thisFrame; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			bool ended = Theorafile.tf_eos(Video.Handle) == 1; |  | ||||||
| 			if (ended) |  | ||||||
| 			{ |  | ||||||
| 				timer.Stop(); |  | ||||||
| 				timer.Reset(); |  | ||||||
| 
 |  | ||||||
| 				Theorafile.tf_reset(Video.Handle); |  | ||||||
| 
 |  | ||||||
| 				if (Loop) |  | ||||||
| 				{ |  | ||||||
| 					// Start over! |  | ||||||
| 					InitializeTheoraStream(); |  | ||||||
| 
 |  | ||||||
| 					timer.Start(); |  | ||||||
| 
 |  | ||||||
| 				} |  | ||||||
| 				else |  | ||||||
| 				{ |  | ||||||
| 					State = VideoState.Stopped; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			return RenderTexture; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		private void InitializeTheoraStream() |  | ||||||
| 		{ |  | ||||||
| 			// Grab the first video frame ASAP. |  | ||||||
| 			while (Theorafile.tf_readvideo(Video.Handle, (IntPtr) yuvData, 1) == 0); |  | ||||||
| 
 |  | ||||||
| 			// Grab the first bit of audio. We're trying to start the decoding ASAP. |  | ||||||
| 			if (Theorafile.tf_hasaudio(Video.Handle) == 1) |  | ||||||
| 			{ |  | ||||||
| 				int channels, samplerate; |  | ||||||
| 				Theorafile.tf_audioinfo(Video.Handle, out channels, out samplerate); |  | ||||||
| 
 |  | ||||||
| 				// TODO: audio stream |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			currentFrame = -1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		private void UpdateTexture() |  | ||||||
| 		{ |  | ||||||
| 			var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); |  | ||||||
| 
 |  | ||||||
| 			commandBuffer.SetTextureDataYUV( |  | ||||||
| 				YUVTextures[0], |  | ||||||
| 				YUVTextures[1], |  | ||||||
| 				YUVTextures[2], |  | ||||||
| 				(IntPtr) yuvData, |  | ||||||
| 				(uint) yuvDataLength |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			commandBuffer.BeginRenderPass( |  | ||||||
| 				new ColorAttachmentInfo(RenderTexture, Color.Black) |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline); |  | ||||||
| 			commandBuffer.BindFragmentSamplers( |  | ||||||
| 				new TextureSamplerBinding(YUVTextures[0], LinearSampler), |  | ||||||
| 				new TextureSamplerBinding(YUVTextures[1], LinearSampler), |  | ||||||
| 				new TextureSamplerBinding(YUVTextures[2], LinearSampler) |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			commandBuffer.DrawPrimitives(0, 1, 0, 0); |  | ||||||
| 
 |  | ||||||
| 			commandBuffer.EndRenderPass(); |  | ||||||
| 
 |  | ||||||
| 			GraphicsDevice.Submit(commandBuffer); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		protected virtual void Dispose(bool disposing) |  | ||||||
| 		{ |  | ||||||
| 			if (!disposed) |  | ||||||
| 			{ |  | ||||||
| 				if (disposing) |  | ||||||
| 				{ |  | ||||||
| 					// dispose managed state (managed objects) |  | ||||||
| 					RenderTexture.Dispose(); |  | ||||||
| 					YUVTextures[0].Dispose(); |  | ||||||
| 					YUVTextures[1].Dispose(); |  | ||||||
| 					YUVTextures[2].Dispose(); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				// free unmanaged resources (unmanaged objects) and override finalizer |  | ||||||
| 
 |  | ||||||
| 				NativeMemory.Free(yuvData); |  | ||||||
| 				disposed = true; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		~VideoPlayer() |  | ||||||
| 		{ |  | ||||||
| 		    // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 		    Dispose(disposing: false); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Dispose() |  | ||||||
| 		{ |  | ||||||
| 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 			Dispose(disposing: true); |  | ||||||
| 			GC.SuppressFinalize(this); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue