123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- using Accord.Video.FFMPEG;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace ScreenBroadcast
- {
- internal class Program
- {
- //[DllImport("user32.dll", SetLastError = true)]
- //static extern bool GetWindowRect(int hWnd, out RECT lpRect);
- // For Windows Mobile, replace user32.dll with coredll.dll
- [DllImport("user32.dll", SetLastError = true)]
- private static extern int FindWindow(string lpClassName, string lpWindowName);
- [DllImport("user32.dll", SetLastError = true)]
- private static extern bool GetClientRect(int hWnd, out Rect lpRect);
- [DllImport("user32.dll")]
- private static extern bool ClientToScreen(int hWnd, ref Point lpPoint);
- [StructLayout(LayoutKind.Sequential)]
- public struct Rect
- {
- public int Left;
- public int Top;
- public int Right;
- public int Bottom;
- public int Height => Bottom - Top;
- public int Width => Right - Left;
- public Size Size => new Size(Width, Height);
- public Point Location => new Point(Left, Top);
- }
- private static void Main()
- {
- //comfig var
- string wndCls = "ConsoleWindowClass";
- string wndName = "管理员: 命令提示符";
- int port = 2333;
- var frameRate = 25;
- var broadcastQuality = 20L;
- //runtime var
- var runing = true;
- int clientNum = 0;
- byte[] buf = null;
- var waits = new List<AutoResetEvent>();
- var taskSource = Task.Factory.StartNew(() =>
- {
- //image encoding params
- var format = ImageFormat.Jpeg;
- var codec = ImageCodecInfo.GetImageDecoders().First(p => p.FormatID == format.Guid);
- var codecParam = new EncoderParameters(1);
- //buffer vars
- Bitmap imgBuf = null;
- var vdoWriter = new VideoFileWriter();
- var ms = new MemoryStream();
- var hWnd = 0;
- try
- {
- while (runing)
- {
- if (hWnd == 0) hWnd = FindWindow(wndCls, wndName);
- Rect rectWndCa;
- var ptWndLoc = Point.Empty;
- if (GetClientRect(hWnd, out rectWndCa) && ClientToScreen(hWnd, ref ptWndLoc))
- {
- Func<int, int> ensureBy2 = v => v % 2 != 0 ? v + 1 : v;
- Func<int, int> ensureBy4 = v => v % 4 != 0 ? v + (4 - v % 4) : v;
- Func<int, int, int> ensureBy = (b, v) => v % b != 0 ? v + (b - v % b) : v;
- var rect = new Rectangle(ptWndLoc, new Size(ensureBy(2, rectWndCa.Size.Width), ensureBy(2, rectWndCa.Height)));
- if (imgBuf == null || imgBuf.Size != rect.Size)
- {
- imgBuf = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb);
- if (vdoWriter.IsOpen)
- vdoWriter.Close();
- var recordPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "record");
- Directory.CreateDirectory(recordPath);
- var filename = $"record_{DateTime.Now:yyyyMMdd_HHmmss_fffff}-{rect.Width:0000}-{rect.Height:0000}.avi";
- vdoWriter.Open(Path.Combine(recordPath, filename), rect.Width, rect.Height, frameRate, VideoCodec.MPEG4, 8000000);
- }
- Graphics srcGraphics = Graphics.FromImage(imgBuf);
- srcGraphics.CopyFromScreen(rect.Location, Point.Empty, rect.Size);
- codecParam.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, broadcastQuality);
- ms.SetLength(0);
- imgBuf.Save(ms, codec, codecParam);
- //imgBuf.Save(ms, format);
- buf = ms.ToArray();
- foreach (var item in waits)
- {
- item.Set();
- }
- vdoWriter.WriteVideoFrame(imgBuf);
- }
- else
- {
- hWnd = 0; //re find win
- Console.WriteLine("waiting window found...");
- }
- Thread.Sleep(1000 / frameRate);
- }
- vdoWriter.Close();
- }
- catch (Exception ex)
- {
- throw;
- }
- });
- Task.Factory.StartNew(() =>
- {
- Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- Server.Bind(new IPEndPoint(IPAddress.Any, port));
- Server.Listen(10);
- Console.WriteLine("Listening...");
- while (runing)
- {
- int num;
- var client = Server.Accept();
- Console.WriteLine("Acceped socket #{0} from {1} onlines {2}", num = ++clientNum, client.RemoteEndPoint, waits.Count);
- Task.Factory.StartNew(() =>
- {
- var wait = new AutoResetEvent(false);
- waits.Add(wait);
- try
- {
- var stream = new NetworkStream(client, true);
- var writer = new BinaryWriter(stream);
- writer.Write(Encoding.ASCII.GetBytes("HTTP / 1.1 200 OK\r\n"));
- writer.Write(Encoding.ASCII.GetBytes("Content-Type: multipart/x-mixed-replace; boundary=frame\r\n"));
- while (runing)
- {
- wait.WaitOne();
- var rbuf = buf;
- if (rbuf != null)
- {
- writer.Write(Encoding.ASCII.GetBytes("\r\n"));
- writer.Write(Encoding.ASCII.GetBytes("--frame\r\n"));
- writer.Write(Encoding.ASCII.GetBytes("Content-Type: image/png\r\n"));
- writer.Write(Encoding.ASCII.GetBytes("Content-Length: " + rbuf.Length + "\r\n"));
- writer.Write(Encoding.ASCII.GetBytes("\r\n"));
- writer.Write(rbuf);
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine("Lost socket #{1} from {0} onlines {2} by {3}", client.RemoteEndPoint, num, waits.Count, ex.Message);
- }
- waits.Remove(wait);
- });
- }
- });
- ConsoleKeyInfo k;
- while (char.ToLower((k = Console.ReadKey(true)).KeyChar) != 'q')
- {
- if (k.Key == ConsoleKey.UpArrow)
- {
- if (broadcastQuality + 1 == 0)
- broadcastQuality += 2;
- else
- broadcastQuality += 1;
- Console.WriteLine("Quality: {0}", broadcastQuality);
- }
- else if (k.Key == ConsoleKey.DownArrow)
- {
- if (broadcastQuality - 1 == 0)
- broadcastQuality -= 2;
- else
- broadcastQuality -= 1;
- Console.WriteLine("Quality: {0}", broadcastQuality);
- }
- else
- {
- Console.WriteLine("Press Q to exit. up-arrow to inc quality, down-arrow to dec");
- }
- }
- runing = false;
- taskSource.Wait();
- }
- }
- }
|