Alby's blog

世上没有巧合,只有巧合的假象。

0%

一、准备工作

1、安装 node

1
brew install node

可以不预先安装 meson(ninjia)flatc, 编译时会自动使用 pip 安装。故需确保安装了 python3

2、获取源码并安装 node 包

1
2
3
4
5
# 当前目录:/Users/alby/Workspace/OpenSource/Multimedia/versatica
git clone https://github.com/versatica/mediasoup
cd mediasoup
# 如果不关心 node 部分,可以不运行下行。
npm i
阅读全文 »

曾好几次尝试在 Hexo 中使用 hexo-mathhexo-renderer-markdown-it-plus 等包以支持 LaTeX 皆不成功,要么不行要么错乱。刚刚了解到如果使用 NexT 主题的话则不需要手工安装任何包。本文是一篇备忘录。

hexo: 7.0.0
hexo-theme-next: 7.8.0

阅读全文 »

一、概述

ASP.NETASP.NET Core 中,如果服务端得到一个 JSON 字符串(比如从 Redis 缓存中获取),我们可以通过 Content 方法或直接创建 ContentResult 对象来作为 Action 的返回值。

1
2
var json = "{\"key\": \"value\"}";
return Content(json, "application/json");
1
2
3
4
5
return new ContentResult
{
Content = json,
ContentType = "application/json"
};

而在 SignalR 中,在 ASP.NET Core 7.0 之前,对于一个 JSON 字符串只能先反序列化,否则 Web 前端得用 JSON.parse() 处理一次。

本文主要记录测试 RawResult 的结果。

阅读全文 »

一、概述

PUTPATCH 方法用于更新现有资源。 它们之间的区别是,PUT 会替换整个资源,而 PATCH 仅指定更改。

在 ASP.NET Core Web API 中,由于 C# 是一种静态语言(dynamic 在此不表),当我们定义了一个类型用于接收 HTTP Patch 请求参数的时候,在 Action 中无法直接从实例中得知客户端提供了哪些参数。

比如定义一个输入模型和数据库实体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PersonInput
{
public string? Name { get; set; }

public int? Age { get; set; }

public string? Gender { get; set; }
}

public class PersonEntity
{
public string Name { get; set; }

public int Age { get; set; }

public string Gender { get; set; }
}

再定义一个以 FromForm 形式接收参数的 Action:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
// 测试代码暂时将 AutoMapper 配置放在方法内。
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<PersonInput, PersonEntity>());
});
var mapper = config.CreateMapper();

// entity 从数据库读取,这里仅演示。
var entity = new PersonEntity
{
Name = "姓名", // 可能会被改变
Age = 18, // 可能会被改变
Gender = "我可能会被改变",
};

// 如果客户端只输入 Name 字段,entity 的 Age 和 Gender 将不能被正确映射或被置为 null。
mapper.Map(input, entity);

return Ok();
}
1
2
curl --location --request PATCH 'http://localhost:5094/test/patch' \
--form 'Name="foo"'

如果客户端只提供了 Name 而没有其他参数,从 HttpContext.Request.Form.Keys 可以得知这一点。如果不使用 AutoMapper,那么就需要使用丑陋的判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
var keys = _httpContextAccessor.HttpContext.Request.Form.Keys.Select(m => m.ToLower());
var entity = new PersonEntity
{
Name = "姓名", // 可能会被改变
Age = 18, // 可能会被改变
Gender = "我可能会被改变",
};

if (keys.Contains("name"))
{
// 更新 Name(这里忽略合法性判断)
entity.Name = input.Name!;
}
if (keys.Contains("age"))
{
// 更新 Age(这里忽略合法性判断)
entity.Age = input.Age!.Value;
}
// ... 其他判断
return Ok();
}

本文提供一种方式来简化这个步骤。

阅读全文 »

一、概述

在有 CPUGPU 参与的一种运算中,比如深度学习推理,CPU 需要预处理数据,然后交给 GPU 处理,最后 CPU 对 GPU 的运算结果进行后处理
在整个过程中都是 FIFO,即数据 ABC 按顺序输入,也需要按 A’B’C’ 顺序输出。
如果采用同步阻塞的方式,在 CPU 预处理时 GPU 处于空闲状态,GPU 运算时 CPU 后处理处于空闲状态并且也不能进行后续数据的预处理。这样影响整体的吞吐。
期望是 GPU 运算时,CPU 可以同时进行数据预处理和后处理。这是典型的单生产者单消费者模式。

在两个线程之间传递数据时,为确保线程安全,可以在一个线程每次 mallocnew 申请内存,在另一个线程 freedelete。为了避免频繁的内存分配和释放,需要使用到内存池。

本文描述采用有界队列实现内存池,适用场景和限制:

  1. 需要把内存使用控制在一定范围内;
  2. 整个过程不允许丢弃数据;
  3. 生产和消费之间线程安全;
  4. 不会(也不允许)同时生产,不会(也不允许)同时消费。如果确实要多线程生产或多线程消费,调用代码自行确保线程安全。
阅读全文 »

一、准备工作

1、安装 node

1
brew install node

可以不预先安装 meson(ninjia), make 时会自动使用 pip 安装。故需确保安装了 python3

2、获取源码并安装 node 包

1
2
3
4
# 当前目录:/Users/alby/Workspace/OpenSource/Multimedia/versatica
git clone https://github.com/versatica/mediasoup
cd mediasoup
npm i
阅读全文 »

一、概述

Mediasoup 主要提供了 3 个库和 1 个 demo。

库名 说明
mediasoup 主要包含三部分。一是 worker 可执行程序,由 C++ 实现,是本系列分析的重点;二是 Node 库,由 TypeScript 实现;三是 Rust 库,和 Node 的主要不同在于它没有以进程方式而是以静态库方式使用 mediasoup-worker。
mediasoup-client Web 客户端库。TypeScript 实现。
libmediasoupclient Native 客户端库。C++ 实现。
mediasoup-demo 官方 Demo。
Examples 各种示例。

网络上对 mediasoup 的 Node.js 层——准确说是对官方的 mediasoup-demo 的源码分析比较多,对于 mediasoup-clientmediasoup-worker (之后简 worker) 等的源码详细分析相对较少。本人之前有将 GB28281 集成进 mediasoup 的想法并验证了可行性,以及使用 .Net 重新实现过 Node.js 层(含 mediasoup-client 和 mediasoup-demo),对 worker 的源码进行过比较粗略地浏览。最近基于想要弥补一些比较模糊的认知,并且 mediaoup 本身也在进化,故就再做了一次源码的梳理。

至于 mediasoup 是什么、能做什么、与其他 SFU 相较而言的优缺点、Demo 如何运行、为什么不用单一语言来实现等等讨论不是本系列关注的重点。

阅读全文 »