C#屏幕流媒体节目

栏目: ASP.NET · 发布时间: 5年前

内容简介:代码日志版权声明:翻译自:http://stackoverflow.com/questions/34421447/c-sharp-screen-streaming-program

最近我一直在做一个简单的屏幕共享程序.

实际上该程序的工作原理是一个TCP协议,并使用桌面复制API – 一个很酷的服务,支持非常快速的屏幕捕获,并且还提供有关MovedRegions的信息(只改变了他们在屏幕上的位置但仍然存在的区域)和更新区域(更改的区域) .

桌面复制有2个改进的属性 – 2个字节的数组,用于先前的像素和NewPixels数组.每4个字节表示RGBA格式的像素,例如,如果我的屏幕为1920 x 1080,则缓冲区大小为1920 x 1080 * 4.

以下是我的策略的重点

>在初始状态(第一次)我发送整个像素缓冲区(在我的情况下是1920 x 1080 * 3) – alpha组件总是255屏幕上:)

>从现在开始,我迭代了UpdatedRegions(它是一个矩形数组),我发送区域边界和Xo’r像素像这样:

writer.Position = 0;
    var n = frame._newPixels;
    var w = 1920 * 4; //frame boundaries.
    var p = frame._previousPixels;
    foreach (var region in frame.UpdatedRegions)
        {
            writer.WriteInt(region.Top);
            writer.WriteInt(region.Height);
            writer.WriteInt(region.Left);
            writer.WriteInt(region.Width);
            for (int y = region.Top, yOffset = y * w; y < region.Bottom; y++, yOffset += w)
            {
                for (int x = region.Left, xOffset = x * 4, i = yOffset + xOffset; x < region.Right; x++, i += 4)
                {
                    writer.WriteByte(n[i] ^ p[i]); //'n' is the newpixels buffer and 'p' is the previous.xoring for differences.
                    writer.WriteByte(n[i+1] ^ p[i+1]);
                    writer.WriteByte(n[i + 2] ^ p[i + 2]);

                }
            }
        }

>我使用c#编写的lz4包装器压缩缓冲区(参见 lz4.NET@github ).然后,我在NetworkStream上写入数据.

>我在接收方合并区域以获取更新的图像 – 今天不是我们的问题:)

‘writer’是我写的“QuickBinaryWriter”类的一个实例(只是重新使用相同的缓冲区).

public class QuickBinaryWriter
{
    private readonly byte[] _buffer;
    private int _position;

    public QuickBinaryWriter(byte[] buffer)
    {
        _buffer = buffer;
    }

    public int Position
    {
        get { return _position; }
        set { _position = value; }
    }

    public void WriteByte(byte value)
    {
        _buffer[_position++] = value;
    }


    public void WriteInt(int value)
    {

        byte[] arr = BitConverter.GetBytes(value);
        for (int i = 0; i < arr.Length; i++)
            WriteByte(arr[i]);
    }

}

从许多措施中,我看到发送的数据真的很大,有时候对于单帧更新,数据可能会达到200kb(压缩后)!

说实话,200kb真的没什么,但如果我想顺利地流式传输屏幕,并能够以高FPS速率观看,我将不得不在这一点上工作 – 以最大限度地减少网络流量和带宽使用.

我正在寻找建议和创意,以提高程序的效率 – 主要是网络部分发送的数据(通过其他方式打包或其他任何想法),我会感谢任何帮助和想法.

对于1920×1080的屏幕,具有4字节的颜色,您正在看每帧大约8 MB.有20 FPS,你有160 MB / s.所以从8 MB到200 KB(4 MB / s @ 20 FPS)是一个很大的进步.

我想提请您注意某些方面,我不确定你是专注于哪些,希望它有帮助.

压缩屏幕图像越多,可能需要的处理越多

>您实际上需要专注于为连续不断变化的图像设计的压缩机制,类似于视频编解码器(无音频).例如:H.264

>记住,您需要使用某种实时协议来传输数据.这样的想法是,如果你的一个框架让它到达目的地机器有一个滞后,你可以放下下几帧来追赶.否则你会处于一个长期的滞后状态,我怀疑用户将会喜欢.

>您可以随时牺牲品质的表现.您在类似技术(如MS远程桌面,VNC等)中看到的最简单的这种机制是发送8位颜色(ARGB每2位),而不是您使用的3字节颜色.

>另一种改善情况的方法是将焦点放在要流式传输的屏幕上的特定矩形上,而不是将整个桌面流式传输.这将减少框架本身的尺寸.

>另一种方法是在传输之前将屏幕图像缩放到较小的图像,然后在显示之前将其缩放至正常.

>发送初始屏幕后,您可以始终在新像素和先前像素之间发送差异.不用说原始屏幕和差分屏幕都将被LZ4压缩/解压缩.如果您使用一些有损耗的算法来压缩差异,那么您应该常常发送完整的数组而不是diff.

>更新区域有重叠区域吗?可以优化为不发送重复的像素信息吗?

上面的想法可以应用于另一个,以获得更好的用户体验.最终,这取决于您的应用程序和最终用户的具体情况.

编辑:

> Color Quantization 可用于减少用于颜色的位数.以下是颜色量化的具体实现的一些链接

> Optimizing Color Quantization for Images

> nQuant library

>通常将量化的颜色存储在 Color Palette and only the index into this palette 中给予解码逻辑

代码日志版权声明:

翻译自:http://stackoverflow.com/questions/34421447/c-sharp-screen-streaming-program


以上所述就是小编给大家介绍的《C#屏幕流媒体节目》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java核心技术及面试指南

Java核心技术及面试指南

金华、胡书敏、周国华、吴倍敏 / 北京大学出版社 / 2018-9-1 / 59.00

本书根据大多数软件公司对高级开发的普遍标准,为在Java 方面零基础和开发经验在3 年以下的初级程序员提供了升级到高级工程师的路径,并以项目开发和面试为导向,精准地讲述升级必备的技能要点。具体来讲,本书围绕项目常用技术点,重新梳理了基本语法点、面向对象思想、集合对象、异常处理、数据库操作、JDBC、IO 操作、反射和多线程等知识点。 此外,本书还提到了对项目开发很有帮助的“设计模式”和“虚拟......一起来看看 《Java核心技术及面试指南》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具