-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rust14.html
521 lines (335 loc) · 158 KB
/
Rust14.html
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- iOS Safari -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Chrome, Firefox OS and Opera Status Bar Color -->
<meta name="theme-color" content="#FFFFFF">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css">
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.19.0/themes/prism.min.css">
<link rel="stylesheet" type="text/css" href="css/SourceSansPro.css">
<link rel="stylesheet" type="text/css" href="css/theme.css">
<link rel="stylesheet" type="text/css" href="css/notablog.css">
<link rel="stylesheet" type="text/css" href="css/CustomSetting.css">
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥥</text></svg>">
<style>
:root {
font-size: 20px;
}
</style>
<title>Rust 驱动 Camera - 采集和播放 | 413’s Website</title>
<meta property="og:type" content="blog">
<meta property="og:title" content="Rust 驱动 Camera - 采集和播放">
<meta name="description" content="流媒体 控制协议 视频捕获">
<meta property="og:description" content="流媒体 控制协议 视频捕获">
<meta property="og:image" content="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🦀</text></svg>">
<style>
.DateTagBar {
margin-top: 1.0rem;
}
</style>
</head>
<body>
<nav class="Navbar">
<a href="index.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥥</text></svg>"></span>
<span>Home</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="blog-collection.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🥅</text></svg>"></span>
<span>blog mark</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="Note.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🎶</text></svg>"></span>
<span>Note</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="reference.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>😷</text></svg>"></span>
<span>杂项</span>
</div>
</a>
<span class="Navbar__Delim">·</span>
<a href="About.html">
<div class="Navbar__Btn">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>😀</text></svg>"></span>
<span>About</span>
</div>
</a>
</nav>
<header class="Header">
<div class="Header__Spacer Header__Spacer--NoCover">
</div>
<div class="Header__Icon">
<span><img class="inline-img-icon" src="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text text-anchor=%22middle%22 dominant-baseline=%22middle%22 x=%2250%22 y=%2255%22 font-size=%2280%22>🦀</text></svg>"></span>
</div>
<h1 class="Header__Title">Rust 驱动 Camera - 采集和播放</h1>
<div class="DateTagBar">
<span class="DateTagBar__Item DateTagBar__Date">Posted on Mon, Sep 2, 2024</span>
<span class="DateTagBar__Item DateTagBar__Tag DateTagBar__Tag--purple">
<a href="tag/Rust.html">Rust</a>
</span>
<span class="DateTagBar__Item DateTagBar__Tag DateTagBar__Tag--red">
<a href="tag/单片机.html">单片机</a>
</span>
</div>
</header>
<div id="content-html"></div>
<article id="https://www.notion.so/6568392ccfa648ca8b07a44b23478384" class="PageRoot"><div id="https://www.notion.so/e3b3e0a52b6440ecbd5f629adfacda47" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">esp32-camera 和 ov3660: </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://shop.m5stack.com/products/esp32-psram-timer-camera-ov3660"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://shop.m5stack.com/products/esp32-psram-timer-camera-ov3660</mark></a></span></span></p></div><div id="https://www.notion.so/0a8e9398c8d84d39835c05a37e227c37" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">OV3660(</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://datasheetspdf.com/pdf-file/1513095/Ommivision/OV3660/1"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">pdf datasheet</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">) 是 3MP 像素的 CMOS 图像传感器,最高 30FPS 720P(2048*1536)的照片(OV2660 可以提供 2MP 像素)。</mark></span></span></p></div><div id="https://www.notion.so/b9a096f5ceb940cf94f87550c3a8155a" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Camera 一般使用 RGB DVP 接口, 部分 LCD 也使用该 RGB 接口类型.</mark></span></span></p></div><div id="https://www.notion.so/e0b4513b53254f9ea8b814e2bd168523" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">OV3660 引脚说明:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/e2fd0d292b7340198a792b4de7c84709" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">VDDA, VDDD, VDDIO</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 电源引脚,分别为模拟电源、数字电源和I/O电源。</mark></span></span></li><li id="https://www.notion.so/8a4e88c4ab914be39834fbdde877f43f" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">GND</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 地(Ground),电源的负极。</mark></span></span></li><li id="https://www.notion.so/bfb62707b8bd485f89aafccc21d68b3b" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">SCL, SDA</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 用于I2C通信的串行时钟线(SCL)和串行数据线(SDA),用于传感器配置。</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/38e2551e8dac45d5afed1b8aa7bc5fb4" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">SIOC # SCCB input clock</mark></span></span></li><li id="https://www.notion.so/344047299e0546789ee078f483d037bd" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">SIOD # SCCB data</mark></span></span></li></ul></li><li id="https://www.notion.so/d1ab551bc4ed4d1d911b5f6fb2944974" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">VS, HS, PCLK</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 视频同步信号(VS,垂直同步),水平同步信号(HS),像素时钟(PCLK)。</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/8e59abe0e3304b5bb8a638befc707c74" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">VS: video output vertical sync signal</mark></span></span></li><li id="https://www.notion.so/6608b5f8a51c4078b7bb59bca90a91b2" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">HS: video output horizontal sync signal</mark></span></span></li><li id="https://www.notion.so/1fdc9467e9bf468bbed29982fcc85a5c" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">PCLK: image output clock</mark></span></span></li></ul></li><li id="https://www.notion.so/1cacbcf6147d439589d751f7438b5cf9" class="NumberedList" value="5"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">D0-D9</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 数字图像数据输出引脚,用于传输图像数据,具体位数根据传感器配置和模式可能有所不同。</mark></span></span></li><li id="https://www.notion.so/e2bebd2670fc4e29a612fc2d4f031fdf" class="NumberedList" value="6"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">RESET_BAR</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 复位引脚,通常用于硬件复位传感器。</mark></span></span></li><li id="https://www.notion.so/faadf9bf56ad41769a44ccf3850df91e" class="NumberedList" value="7"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">PWDN</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 电源关闭(Power Down)控制,用于控制传感器的电源模式。</mark></span></span></li><li id="https://www.notion.so/dad8ffd31f4c4639abd807660d6a5f48" class="NumberedList" value="8"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><strong class="SemanticString__Fragment SemanticString__Fragment--Bold">XCLK</strong></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> - 外部时钟输入,提供给传感器的工作时钟,system input clock/scan clock input。对于 ESP32 是 10 MHz。</mark></span></span></li></ol><div id="https://www.notion.so/b54351bec579465c941034ac73638397" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">通过 I2C 等通信接口(也称为 SCCB,serial camera control bus),外部控制器可以读写 OV3660 的内部寄存器,以配置其工作模式、分辨率、曝光参数、增益等。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/fa97d857ebc340e09da68eb0b41597ba" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">automatic exposure control (AEC)</mark></span></span></li><li id="https://www.notion.so/1d608166a61f4ac5ab5fd7cdbf53205d" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">automatic white balance (AWB)</mark></span></span></li><li id="https://www.notion.so/05dfb91f193840539f38c09c2ee71ed1" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">automatic flicker detection</mark></span></span></li><li id="https://www.notion.so/00ad847104cc4293965a6eb924ccffaf" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">automatic black level calibration (ABLC)</mark></span></span></li><li id="https://www.notion.so/d5f3a11d7141492f9b16d3bc39ea50a6" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">图像质量,如 JPEG 质量;</mark></span></span></li><li id="https://www.notion.so/6b29705f513b4e9fb5a6e0724c135978" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">可编程 frame rate;</mark></span></span></li><li id="https://www.notion.so/bd5329a3ebd44d00b5b9d40e5ad02ebc" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">支持的输出格式: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">raw RGB data, RGB565/555/444, CCIR656, YCbCr422,and JPEG compression</code></mark></span></span></li></ul><div id="https://www.notion.so/04f420b6cce24927926a152dae177444" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ATTR_HTML: :width 400 :align center</mark></span></span></p></div><div id="https://www.notion.so/7f6dfcddc53643f9ba23e29bf4c60fa0" class="Image Image--PageWidth"><figure><a href="#?width=665"><img src="#?width=665" style="width:100%"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/452ebc26a3c44639aa1b6f90ad9072db" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">驱动程序通过发送 VSYNC 信号来从 OV3660 获取恒定的 frame rate 输出。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/abc303ac60ea4b728fb45d984a51f785" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">驱动发起 VSYNC 采集,OV3660 在 VSYNC 采集结束后,发送 VSYNC ISR 中断请求,驱动使用 DMA 来获取 OV3660 输出的一个 frame 数据;</mark></span></span></li></ul><div id="https://www.notion.so/dbf753efaa05454c86d18bc681daf1ab" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">最大图片传输速率:maximum image transfer rate:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/aad959cbbd3a4b5393f065e24a0145c0" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">2048x1536: 15 fps (3MP 像素)</mark></span></span></li><li id="https://www.notion.so/120290e028bc421b8ff08fbd4f738038" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">1080p: 20 fps</mark></span></span></li><li id="https://www.notion.so/96866de8408945ef858313a7a3bebbce" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">720p: 45 fps</mark></span></span></li><li id="https://www.notion.so/bc6f188b5ecd434697056621d688302d" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">XGA (1024x768): 45 fps</mark></span></span></li><li id="https://www.notion.so/eb95b7e1663b47729405b68e16789509" class="NumberedList" value="5"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">VGA (640x480): 60 fps</mark></span></span></li><li id="https://www.notion.so/bd2448aaab214a3a8df6a3470f32d65a" class="NumberedList" value="6"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">QVGA (320x240): 120 fps</mark></span></span></li></ol><h2 id="https://www.notion.so/e5da397605e14c9a83eb389b90437831" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/e5da397605e14c9a83eb389b90437831"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">1 esp32-camera </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-camera-streaming/#esp32-camera"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/f170b3da6f9d4c5694d1a79048667380" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">esp32-camera 项目是 ESP32 官方维护的摄像头驱动和 APIs 库:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/espressif/esp32-camera"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/espressif/esp32-camera</mark></a></span></span></p></div><div id="https://www.notion.so/835345adaa464759983896c58219ebbc" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">主要原理:将摄像头像素输出设置为 JEPG 格式,一个 frame 为一个 JPEG 格式数据的 frame buffer,然后通过读取 frame buffer 来获得单张照片。通过 loop 获取 frame buffer 的数据来形成 video stream。</mark></span></span></p></div><div id="https://www.notion.so/4cd51a67ef234412993f7d672d6ec163" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">esp32-camera 摄像头驱动的配置参数:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/0265b8069e3549c4abdd6b1cfb4d1544" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 LEDC timer 来产生 XCLK 所需的频率信号;</mark></span></span></li><li id="https://www.notion.so/a41e400a97e44283a45ba67ccc11b2a1" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">像素格式,也即摄像头输出的像素数据格式: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG</code></mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/d5d3d4300f1c4c4ba4c513b3197cd1d8" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">YUV 也称为 YCbCr:Y 亮度,U/Cb:蓝色浓度,V/Cr:红色浓度,它也是一种压缩格式。</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/fff2e582979247a99001385179a11a3f" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">为了节省带宽 YUV frame 一般使用采样,如 YUV422 表示 2:1的水平取样,垂直完全采样;</mark></span></span></li><li id="https://www.notion.so/3c24667fdcd841d393bc1c1c804b493a" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">每个像素只需要 2Bytes,这样 3MP 大概是 6MB 存储需求,8 PSRAM 还有 2MB 可用。</mark></span></span></li></ul></li><li id="https://www.notion.so/d3c817b8511041faa95a2da4d14ff051" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RGB 输出格式:</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/6b856945ff0e4203b02a63f91f426c4f" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RGB888,也称 24-bit RGB,各使用 8bit 来表示 red/green/blue,在 3MP 2048x1536 分辨率的情况下,需要 9437184 bytes 存储空间来保存一个 frame,超过了 8 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">PSRAM</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 的容量。所以一般使用 RGB565/YUV/JPEG 等压缩格式</mark></span></span></li><li id="https://www.notion.so/8a6cae5711264cff9c196538c4c76915" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RGB565,也称 16-bit RGB,5 bits for the red channel, 6 bits for the green channel, and 5 bits for the blue channel. 相比 RGB888,更节省资源;</mark></span></span></li><li id="https://www.notion.so/d512b144d6f8449ab77402d18247b399" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RGB 和 YUV 之间可以相互转换;</mark></span></span></li></ul></li><li id="https://www.notion.so/faf67cfac0a54f638be16418fddac4e9" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">JPEG 输出格式:为了节省空间, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">建议使用</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> JPEG 压缩格式,一个 frame 照片的大小大概是原始 raw 的 1/5 空间需求;</mark></span></span></li></ul></li><li id="https://www.notion.so/70ca33eabe504b1d92ceb332e4525946" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">帧大小,也即一幅照片的分辨率:FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA</mark></span></span></li><li id="https://www.notion.so/150726cdcfcd4199bab6273304459f42" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">保存照片数据的 frame buffer 位置:PSRAM 或 DRAM;</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/76825e8f949d4a21818eb1b8e85ace29" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ESP32 需要有至少 8MB 的 PSRAM 来作为 framebuffer 保存照片,同时需要启用 JPEG 压缩格式,OV3660 支持 on-chip 的 JPEG video stream 输出。</mark></span></span></li><li id="https://www.notion.so/1013d59dd4b046d6b8ce4d1402ecc5c3" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">PSRAM 也称为 SPI RAM;</mark></span></span></li><li id="https://www.notion.so/9871163d95fa40dda0f7f38f22793946" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">启用 PSRAM: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">echo 'CONFIG_ESP32_SPIRAM_SUPPORT=y' >> sdkconfig.defaults</code></mark></span></span></li></ul></li></ul><div id="https://www.notion.so/848ea292d5c445c48953820b26a3e1dc" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Copy</mark></span></span></p></div><pre id="https://www.notion.so/da9dd3f15ef74c0193c2fe094d389d31" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment">// https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h#L115</span>
<span class="token comment">/**
* @brief Configuration structure for camera initialization
*/</span>
<span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> pin_pwdn<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera power down line */</span>
<span class="token keyword">int</span> pin_reset<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera reset line */</span>
<span class="token keyword">int</span> pin_xclk<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera XCLK line */</span>
<span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> pin_sccb_sda<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera SDA line */</span>
<span class="token keyword">int</span> pin_sscb_sda <span class="token function">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token function">deprecated</span><span class="token punctuation">(</span><span class="token string">"please use pin_sccb_sda instead"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera SDA line (legacy name) */</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> pin_sccb_scl<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera SCL line */</span>
<span class="token keyword">int</span> pin_sscb_scl <span class="token function">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token function">deprecated</span><span class="token punctuation">(</span><span class="token string">"please use pin_sccb_scl instead"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera SCL line (legacy name) */</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> pin_d7<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D7 line */</span>
<span class="token keyword">int</span> pin_d6<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D6 line */</span>
<span class="token keyword">int</span> pin_d5<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D5 line */</span>
<span class="token keyword">int</span> pin_d4<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D4 line */</span>
<span class="token keyword">int</span> pin_d3<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D3 line */</span>
<span class="token keyword">int</span> pin_d2<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D2 line */</span>
<span class="token keyword">int</span> pin_d1<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D1 line */</span>
<span class="token keyword">int</span> pin_d0<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera D0 line */</span>
<span class="token keyword">int</span> pin_vsync<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera VSYNC line */</span>
<span class="token keyword">int</span> pin_href<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera HREF line */</span>
<span class="token keyword">int</span> pin_pclk<span class="token punctuation">;</span> <span class="token comment">/*!< GPIO pin for camera PCLK line */</span>
<span class="token keyword">int</span> xclk_freq_hz<span class="token punctuation">;</span> <span class="token comment">/*!< Frequency of XCLK signal, in Hz. EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode */</span>
ledc_timer_t ledc_timer<span class="token punctuation">;</span> <span class="token comment">/*!< LEDC timer to be used for generating XCLK */</span>
ledc_channel_t ledc_channel<span class="token punctuation">;</span> <span class="token comment">/*!< LEDC channel to be used for generating XCLK */</span>
pixformat_t pixel_format<span class="token punctuation">;</span> <span class="token comment">/*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */</span>
framesize_t frame_size<span class="token punctuation">;</span> <span class="token comment">/*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */</span>
<span class="token keyword">int</span> jpeg_quality<span class="token punctuation">;</span> <span class="token comment">/*!< Quality of JPEG output. 0-63 lower means higher quality */</span>
size_t fb_count<span class="token punctuation">;</span> <span class="token comment">/*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */</span>
camera_fb_location_t fb_location<span class="token punctuation">;</span> <span class="token comment">/*!< The location where the frame buffer will be allocated */</span>
camera_grab_mode_t grab_mode<span class="token punctuation">;</span> <span class="token comment">/*!< When buffers should be filled */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression">CONFIG_CAMERA_CONVERTER_ENABLED</span></span>
camera_conv_mode_t conv_mode<span class="token punctuation">;</span> <span class="token comment">/*!< RGB<->YUV Conversion mode */</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token keyword">int</span> sccb_i2c_port<span class="token punctuation">;</span> <span class="token comment">/*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */</span>
<span class="token punctuation">}</span> camera_config_t<span class="token punctuation">;</span>
<span class="token comment">/**
* @brief Camera frame buffer location
*/</span>
<span class="token keyword">typedef</span> <span class="token keyword">enum</span> <span class="token punctuation">{</span>
CAMERA_FB_IN_PSRAM<span class="token punctuation">,</span> <span class="token comment">/*!< Frame buffer is placed in external PSRAM */</span>
CAMERA_FB_IN_DRAM <span class="token comment">/*!< Frame buffer is placed in internal DRAM */</span>
<span class="token punctuation">}</span> camera_fb_location_t<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression">CONFIG_CAMERA_CONVERTER_ENABLED</span></span>
<span class="token comment">/**
* @brief Camera RGB\YUV conversion mode
*/</span>
<span class="token keyword">typedef</span> <span class="token keyword">enum</span> <span class="token punctuation">{</span>
CONV_DISABLE<span class="token punctuation">,</span>
RGB565_TO_YUV422<span class="token punctuation">,</span>
YUV422_TO_RGB565<span class="token punctuation">,</span>
YUV422_TO_YUV420
<span class="token punctuation">}</span> camera_conv_mode_t<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span></span></span></span></code></pre><div id="https://www.notion.so/6f6ef41da37e47caabf8fc8f9bda9c7c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">对于 RAW RGB 和 YUV 像素,一般使用 8-10 位并行数字接口(DVP)输出, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">该接口和 RGB LCD 接口类型一致</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,所以 LCD 和 Camera 在 esp-hal 仓库中属于同一个 module:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/lcd_cam/cam.rs"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">lcd_camera</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">;</mark></span></span></p></div><div id="https://www.notion.so/ca674f36974c4cfd86f0a4bb728747d0" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">LCD 显示器一般使用 RGB 像素格式,而且是比较节省空间的 16-bit 的 RGB565 像素格式:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/5abb7b2e449a4ca6a79a5041d6408772" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">camera 可以直接产生 RGB565 数据,故可以直接在 LCD 显示;</mark></span></span></li><li id="https://www.notion.so/f6e2b5a8814a497a97e807f2bccbf5cd" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">bmp/png/jpeg 等图片格式,需要将像素转换为 RGB565 后才能供 LCD 显示;</mark></span></span></li></ul><div id="https://www.notion.so/c041c08416ac466cbd875b2738590968" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/lcd_cam/cam.rs"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/lcd_cam/cam.rs</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> LCD_CAM peripheral driver 支持 8/16 bit DVP 信号的 master 或 slave mode。在 master mode 时 LCD_CAM peripheral driver 为 camera 提供 master clock,反之在 slave mode 时,不提供。这可以通过 driver 的with_master_clock() 方法来设置。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/83cd340187db44a7b9c1023a60b3b492" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">为了提高数据传输效率,这个 driver 使用了 DMA 机制。</mark></span></span></li><li id="https://www.notion.so/b5d422ff0e17423c95282a369f0bb0a8" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">DMA 传输结束的通知方式:ByteLen 或 Signal。</mark></span></span></li></ul><div id="https://www.notion.so/c6dcdf6624074965b6ddebfa6c41e775" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Copy</mark></span></span></p></div><pre id="https://www.notion.so/838d5ac802b64b7daaff38ffb300c164" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span>// https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/lcd_cam/cam.rs
//! ## Examples
//!/Following code shows how to receive some bytes from an 8 bit DVP stream in
//! master mode.
//!
//! ```no_run
//! let mclk_pin = io.pins.gpio15;
//! let vsync_pin = io.pins.gpio6;
//! let href_pin = io.pins.gpio7;
//! let pclk_pin = io.pins.gpio13;
//! let data_pins = RxEightBits::new(
//! io.pins.gpio11,
//! io.pins.gpio9,
//! io.pins.gpio8,
//! io.pins.gpio10,
//! io.pins.gpio12,
//! io.pins.gpio18,
//! io.pins.gpio17,
//! io.pins.gpio16,
//! );
//!
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
//! let mut camera = Camera::new(lcd_cam.cam, channel.rx, data_pins, 20u32.MHz(), &clocks)
//! .with_master_clock(mclk_pin) // Remove this for slave mode.
//! .with_ctrl_pins(vsync_pin, href_pin, pclk_pin);
//! ```
/// Generation of GDMA SUC EOF
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum EofMode {
/// Generate GDMA SUC EOF by data byte length
ByteLen,
/// Generate GDMA SUC EOF by the external enable signal
EnableSignal,
}
/// Perform a DMA read.
///
/// This will return a [RxDmaTransfer]
///
/// The maximum amount of data is 32736 bytes when using [EofMode::ByteLen].
///
/// It's only limited by the size of the DMA buffer when using
/// [EofMode::EnableSignal].</span></span></span></code></pre><div id="https://www.notion.so/3a09b178a80245179a394f0f1c753c3d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">通过将 ESP32 设置为 camera 的 master 模式,可以由 esp32 发送 VSYNC 信号给摄像头来作为采集 frame buffer 开始的控制信号,当 VSYNC 采集结束时,通过中断的方式得到通知;</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/679e1c5dc864482d99a629aadf29eedd" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">如果只有 1 个 frame buffer,则 drvier 需要等待当前 frame finish(VSYNC) 然后启动 I2S DMA,然后app 才能获得 frame buffer 数据。这种单 frame buffer 的方式,会给应用造成等待延迟。</mark></span></span></li><li id="https://www.notion.so/f1147607a64a42d3be0b9f392b089535" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">所以,建议使用 2 个或更多 fram buffer, 这时 I2S 工作在 continuous mode,自动将各 frame push 到 app 可以方位的 queue,这样会给 CPU/Memory 造成压力,但是可以 double frame rate,建议和 JPEG 一起使用。</mark></span></span></li></ul><div id="https://www.notion.so/5e9620fed26045a893aaec717a51b1de" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/1f9ef9974c6341bc8891ee05913f671f" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span>esp_err_t camera_capture(){
//acquire a frame
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
ESP_LOGE(TAG, "Camera Capture Failed");
return ESP_FAIL;
}
//replace this with your own function
process_image(fb->width, fb->height, fb->format, fb->buf, fb->len);
//return the frame buffer back to the driver for reuse
esp_camera_fb_return(fb);
return ESP_OK;
}</span></span></span></code></pre><div id="https://www.notion.so/01255edc06774485830f1c051cb02bb6" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">提供的 API 支持:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/6366e7987e1e4268ba35a6d7c40d9b2a" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">摄像头硬件设置(I2C 接口);</mark></span></span></li><li id="https://www.notion.so/0eb6d69e33514f21b30602601cd96b90" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">JPEG HTTP Capture:提供一个 http handler,请求时获从 fb 获取一张 JPEG 图片并返回;</mark></span></span></li><li id="https://www.notion.so/7580a56a9ecb403f8e6dfd448eb65e8e" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">JPEG HTTP Stream:提供一个 http handler,在 while true 循环中不断获取 fb 中 JPEG 图片,通过 multipart/x-mixed-replace 编码的方式返回给客户端。</mark></span></span><ul class="BulletedListWrapper"><li id="https://www.notion.so/1fc90e4378814436a9c79b145b00ae5a" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">也称为 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Motion JPEG</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> , </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">主流浏览器,QuickTime,VLC 都支持 HTTP Stream</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 播放。</mark></span></span></li></ul></li><li id="https://www.notion.so/11143fd975644c47bcfee18e9c3e85ef" class="NumberedList" value="4"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">BMP HTTP Capture:将捕获的 JPEG 转码为 BMP,再返回;</mark></span></span></li></ol><div id="https://www.notion.so/a6b2b75c91ad4e068be51c5e26760b88" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">开发调试:My initial idea for this (which is the example I have in my project) was to </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">dump the JPEG from the camera as HEX onto the console</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> and use </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">xxd -r -p uart.txt image.jpg</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> to convert it to JPEG file. Somewhat tedious but it works haha.</mark></span></span></p></div><div id="https://www.notion.so/b08ae5f2b7544bb68ad61f7bbf1a4e6d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">将 esp-camera 驱动的摄像头进行 RTSP+RTP(Over UDP) 进行流式输出的例子:</mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/esp-cpp/camera-streamer"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">camera-streamer</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">:Example for ESP32 TimerCam rebuilt using ESPP to stream video over the network. It uses </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTSP + RTP (over UDP)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> to perform real-time streaming of the camera data over the network to multiple clients.</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/85144c3569424ba8afd321f73401a6c7" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 RTSP+REP 将 OV2660 capture 的 JPEG 图片转换成流式输出;</mark></span></span></li><li id="https://www.notion.so/d607c3dbcd27487b9a792c76e9914824" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">初始化摄像头配置:</mark></span></span></li><li id="https://www.notion.so/7cddd273b87644c195736dc2f8bca8aa" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">控制和 data 引脚;</mark></span></span></li><li id="https://www.notion.so/05b4c10df6274ec5b256c5b0e549506c" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">像素输出格式</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> :pixel_format = PIXFORMAT_JPEG, // YUV422,GRAYSCALE,RGB565,JPEG</mark></span></span></li><li id="https://www.notion.so/5238f83a10e640f7af33900cb832afd5" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">分辨率(frame size)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> :frame_size = FRAMESIZE_QVGA</mark></span></span></li><li id="https://www.notion.so/7bf516a9e36743208dc86ac4d96aa107" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">JPEG 质量:越小质量越高;</mark></span></span></li><li id="https://www.notion.so/0b5619da0a094d369aca050ef12ccb67" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">fb_count:frame buffer 数量;</mark></span></span></li></ul><div id="https://www.notion.so/a823fc5e015348d18afd7b07be31d03c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Copy</mark></span></span></p></div><pre id="https://www.notion.so/f38fb86e309747008cc0fae51fc528e4" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment">// https://github.com/esp-cpp/camera-streamer/blob/main/main/main.cpp</span>
<span class="token comment">// initialize camera</span>
<span class="token comment">/**
* @note display sizes supported:
* * QVGA: 320x240
* * WQVGA: 400x240
* * HVGA: 480x320
* * VGA: 640x480
* * WVGA: 768x480
* * FWVGA: 854x480
* * SVGA: 800x600
* * DVGA: 960x640
* * WSVGA: 1024x600
* * XGA: 1024x768
* * WXGA: 1280x800
* * WSXGA: 1440x900
* * SXGA: 1280x1024
* * UXGA: 1600x1200
*/</span>
<span class="token keyword">static</span> camera_config_t camera_config <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span>pin_pwdn <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_reset <span class="token operator">=</span> <span class="token number">15</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_xclk <span class="token operator">=</span> <span class="token number">27</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_sccb_sda <span class="token operator">=</span> <span class="token number">25</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_sccb_scl <span class="token operator">=</span> <span class="token number">23</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d7 <span class="token operator">=</span> <span class="token number">19</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d6 <span class="token operator">=</span> <span class="token number">36</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d5 <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d4 <span class="token operator">=</span> <span class="token number">39</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d3 <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d2 <span class="token operator">=</span> <span class="token number">34</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d1 <span class="token operator">=</span> <span class="token number">35</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_d0 <span class="token operator">=</span> <span class="token number">32</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_vsync <span class="token operator">=</span> <span class="token number">22</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_href <span class="token operator">=</span> <span class="token number">26</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>pin_pclk <span class="token operator">=</span> <span class="token number">21</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>xclk_freq_hz <span class="token operator">=</span> <span class="token number">10000000</span><span class="token punctuation">,</span> <span class="token comment">// EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode</span>
<span class="token punctuation">.</span>ledc_timer <span class="token operator">=</span> LEDC_TIMER_0<span class="token punctuation">,</span>
<span class="token punctuation">.</span>ledc_channel <span class="token operator">=</span> LEDC_CHANNEL_0<span class="token punctuation">,</span>
<span class="token punctuation">.</span>pixel_format <span class="token operator">=</span> PIXFORMAT_JPEG<span class="token punctuation">,</span> <span class="token comment">// YUV422,GRAYSCALE,RGB565,JPEG</span>
<span class="token punctuation">.</span>frame_size <span class="token operator">=</span> FRAMESIZE_QVGA<span class="token punctuation">,</span> <span class="token comment">// QVGA-UXGA, For ESP32, do not use sizes above QVGA when not</span>
<span class="token comment">// JPEG. The performance of the ESP32-S series has improved a</span>
<span class="token comment">// lot, but JPEG mode always gives better frame rates.</span>
<span class="token punctuation">.</span>jpeg_quality <span class="token operator">=</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token comment">// 0-63, for OV series camera sensors, lower number means higher quality</span>
<span class="token punctuation">.</span>fb_count <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token comment">// When jpeg mode is used, if fb_count more than one, the driver will work in</span>
<span class="token comment">// continuous mode.</span>
<span class="token punctuation">.</span>grab_mode <span class="token operator">=</span>
CAMERA_GRAB_LATEST <span class="token comment">// CAMERA_GRAB_WHEN_EMPTY // . Sets when buffers should be filled</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// create the camera and rtsp server, and the cv/m they'll use to communicate</span>
<span class="token keyword">int</span> server_port <span class="token operator">=</span> CONFIG_RTSP_SERVER_PORT<span class="token punctuation">;</span>
logger<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Creating RTSP server at {}:{}"</span><span class="token punctuation">,</span> server_address<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">;</span>
espp<span class="token double-colon punctuation">::</span>RtspServer <span class="token function">rtsp_server</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">.</span>server_address <span class="token operator">=</span> server_address<span class="token punctuation">,</span>
<span class="token punctuation">.</span>port <span class="token operator">=</span> server_port<span class="token punctuation">,</span>
<span class="token punctuation">.</span>path <span class="token operator">=</span> <span class="token string">"mjpeg/1"</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span>log_level <span class="token operator">=</span> espp<span class="token double-colon punctuation">::</span>Logger<span class="token double-colon punctuation">::</span>Verbosity<span class="token double-colon punctuation">::</span>WARN<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
rtsp_server<span class="token punctuation">.</span><span class="token function">set_session_log_level</span><span class="token punctuation">(</span>espp<span class="token double-colon punctuation">::</span>Logger<span class="token double-colon punctuation">::</span>Verbosity<span class="token double-colon punctuation">::</span>WARN<span class="token punctuation">)</span><span class="token punctuation">;</span>
rtsp_server<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// initialize the camera</span>
logger<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"Creating camera task"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> camera_task_fn <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">&</span>rtsp_server<span class="token punctuation">,</span> <span class="token operator">&</span>logger<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token operator">&</span>m<span class="token punctuation">,</span> <span class="token keyword">auto</span> <span class="token operator">&</span>cv<span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
<span class="token comment">// take image</span>
<span class="token keyword">static</span> camera_fb_t <span class="token operator">*</span>fb <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token keyword">static</span> size_t _jpg_buf_len<span class="token punctuation">;</span>
<span class="token keyword">static</span> <span class="token keyword">uint8_t</span> <span class="token operator">*</span>_jpg_buf<span class="token punctuation">;</span>
fb <span class="token operator">=</span> <span class="token function">esp_camera_fb_get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 调用 esp camera 库的 esp_camera_fb_get() 来获得 JPEG 图片</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fb<span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"Camera capture failed"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
_jpg_buf_len <span class="token operator">=</span> fb<span class="token operator">-></span>len<span class="token punctuation">;</span>
_jpg_buf <span class="token operator">=</span> fb<span class="token operator">-></span>buf<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span>_jpg_buf<span class="token punctuation">[</span>_jpg_buf_len <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">!=</span> <span class="token number">0xd9</span> <span class="token operator">||</span> _jpg_buf<span class="token punctuation">[</span>_jpg_buf_len <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">!=</span> <span class="token number">0xd9</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">esp_camera_fb_return</span><span class="token punctuation">(</span>fb<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
espp<span class="token double-colon punctuation">::</span>JpegFrame <span class="token function">image</span><span class="token punctuation">(</span><span class="token generic-function"><span class="token function">reinterpret_cast</span><span class="token generic class-name"><span class="token operator"><</span><span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>_jpg_buf<span class="token punctuation">)</span><span class="token punctuation">,</span> _jpg_buf_len<span class="token punctuation">)</span><span class="token punctuation">;</span>
rtsp_server<span class="token punctuation">.</span><span class="token function">send_frame</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 将 JPEG 图片发送给 rtsp_server 进行流式输出</span>
<span class="token function">esp_camera_fb_return</span><span class="token punctuation">(</span>fb<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> camera_task <span class="token operator">=</span> espp<span class="token double-colon punctuation">::</span><span class="token class-name">Task</span><span class="token double-colon punctuation">::</span><span class="token function">make_unique</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"Camera Task"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>callback <span class="token operator">=</span> camera_task_fn<span class="token punctuation">,</span> <span class="token punctuation">.</span>priority <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
camera_task<span class="token operator">-></span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 启动 camera task</span></span></span></span></code></pre><div id="https://www.notion.so/a53f6987cdad42ea9e60f919694f4471" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">另一个支持 RTSP + HTTP JPEG Streamer + image Capture 的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">强大的库</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> : </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/rzeldent/esp32cam-rtsp/tree/main"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/rzeldent/esp32cam-rtsp/tree/main</mark></a></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/bf68e9a3c9474b25bb1030483b3f142d" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">相当于在官方 esp32-camera 的基础上,加了 RTSP 的功能</mark></span></span></li><li id="https://www.notion.so/0c0415566a6944adaff962184de65306" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Flashing this software on a ESP32CAM module will make it </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">a RTSP streaming camera server</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, a HTTP Motion JPEG streamer and a HTTP image server.</mark></span></span></li><li id="https://www.notion.so/d585fa3b56554d778a2061508729c52e" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP The RTSP protocol is an industry standard and allows many CCTV systems and applications (like for example VLC) to connect directly to the ESP32CAM camera stream. It is also possible to stream directly to a server using ffmpeg. This makes the module a camera server allowing recording and the stream can be stored on a disk and replayed later. The URL is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">rtsp://<ip address>:554/mjpeg/1</code></mark></span></span></li><li id="https://www.notion.so/23d6b4b924184653a5e16e2ae8524f54" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">HTTP Motion JPEG The HTTP JPEG streamer makes it possible to watch the camera stream directly in your browser. The URL is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">http://<ip address>/stream</code></mark></span></span></li><li id="https://www.notion.so/d8e9d48d77204033955c66ebe01b3d91" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">HTTP image The HTTP Image returns an HTTP JPEG image of the camera. The URL is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">http://<ip address>/snapshot</code></mark></span></span></li><li id="https://www.notion.so/ef2a8390dd9f44ebaca04c7988fc68c6" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">同时提供了 web 界面来设置 camera 参数,截图功能。</mark></span></span></li></ul><div id="https://www.notion.so/6107d76e3f4b42a8a8893180a74cf0e0" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">可以使用 opencv 来显示 RTSP 内容:</mark></span></span></p></div><div id="https://www.notion.so/c698fe5287744b27882306c0d2ad1240" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Copy</mark></span></span></p></div><pre id="https://www.notion.so/abcb1cf545c545de951128d60159e3d3" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment"># https://github.com/esp-cpp/camera-streamer/blob/main/opencv_rtsp_client.py</span>
<span class="token keyword">import</span> sys
<span class="token keyword">import</span> cv2
<span class="token keyword">def</span> <span class="token function">stream</span><span class="token punctuation">(</span>addr<span class="token punctuation">,</span> port<span class="token punctuation">)</span><span class="token punctuation">:</span>
vcap <span class="token operator">=</span> cv2<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"rtsp://</span><span class="token interpolation"><span class="token punctuation">{</span>addr<span class="token punctuation">}</span></span><span class="token string">:</span><span class="token interpolation"><span class="token punctuation">{</span>port<span class="token punctuation">}</span></span><span class="token string">/mjpeg/1"</span></span><span class="token punctuation">)</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> vcap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
cv2<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">'VIDEO'</span><span class="token punctuation">,</span> frame<span class="token punctuation">)</span>
cv2<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span>
<span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>sys<span class="token punctuation">.</span>argv<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">3</span><span class="token punctuation">:</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Usage: python ./opencv_rtsp_client <address> <rtsp_port>"</span><span class="token punctuation">)</span>
sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
stream<span class="token punctuation">(</span>sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span></span></span></code></pre><div id="https://www.notion.so/5de2f78c1f8a4e4f96bc8a49f65207b0" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/esp-cpp/camera-display/tree/main?tab=readme-ov-file"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">camera-display</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 项目来从 RTSP+RTP 拉流显示 JPEG 图片:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/760bdc9f8056407faf38c2936f12b445" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTSP client</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> that receives mjpeg frames split into </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTP packets</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, turns them back into </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">JPEG images</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, and pushes them into a queue.</mark></span></span></li><li id="https://www.notion.so/e2896d6b0dab44bd8ebd96a58203a447" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Display task, which pulls image data from the queue, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">decodes the jpeg</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, and displays it on the screen.</mark></span></span></li></ol><div id="https://www.notion.so/92ddd499975f40c5aff0b8a3ffb02d57" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">其他 Streaming JPEG 或任何文件的方式:</mark></span></span></p></div><div id="https://www.notion.so/ecde002c50e143d993ef720c8ebd52f3" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><pre id="https://www.notion.so/416d71bbbb6a4645a317fcaea04641dd" class="Code Code--NoWrap"><code><span class="SemanticStringArray"><span class="SemanticString"><span><span class="token comment"># 使用 Gstreamer 将 webcam 发送的串行 JPEG image 捕获为 mp4 视频输出:</span>
$ gst-launch-1.0 v4l2src <span class="token operator">!</span> jpegdec <span class="token operator">!</span> xvimagesink
<span class="token comment"># Capture a single image and save it in JPEG format.</span>
$ gst-launch v4l2src num-buffers<span class="token operator">=</span><span class="token number">1</span> <span class="token operator">!</span> jpegenc <span class="token operator">!</span> filesink <span class="token assign-left variable">location</span><span class="token operator">=</span>/tmp/test.jpg
<span class="token comment"># Stream video from a webcam.</span>
$ gst-launch v4l2src <span class="token operator">!</span> xvimagesink
<span class="token comment"># if camera supports MJPG</span>
$ gst-launch-1.0 v4l2src num-buffers<span class="token operator">=</span><span class="token number">1</span> <span class="token operator">!</span> image/jpeg,framerate<span class="token operator">=</span><span class="token number">5</span>/1,width<span class="token operator">=</span><span class="token number">1280</span>,height<span class="token operator">=</span><span class="token number">960</span> <span class="token operator">!</span> jpegparse
<span class="token operator">!</span> filesink <span class="token assign-left variable">location</span><span class="token operator">=</span>/tmp/test2.jpg
<span class="token comment"># raw image</span>
$ gst-launch-1.0 v4l2src num-buffers<span class="token operator">=</span><span class="token number">1</span> <span class="token operator">!</span> videoconvert <span class="token operator">!</span> <span class="token string">'video/x-raw,width=1280,height=960,format=RGBx'</span> <span class="token operator">!</span> filesink <span class="token assign-left variable">location</span><span class="token operator">=</span>image.raw</span></span></span></code></pre><div id="https://www.notion.so/d386e5c1338049d48b1c63b4138ab841" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">关于 Streaming 的解释: </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Playing media straight from the Internet without storing it locally</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> is known as </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Streaming</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. We have been doing it throughout the tutorials whenever we used a URI starting with </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="chrome-extension://ldmmifpegigmeammaeckplhnjbbpccmm/popup/index.html"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">http://</mark></a></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. This tutorial shows a couple of additional points to keep in mind when streaming. In particular:</mark></span></span></p></div><div id="https://www.notion.so/80e8aec806894cfaa9b1ac9432dda6a5" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">information Embedding multiple streams inside a single file is called “multiplexing” or “muxing”, and such file is then known as a </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">“container”</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. Common container formats are Matroska (.mkv), Quicktime (.qt, .mov, .mp4), Ogg (.ogg) or Webm (.webm).</mark></span></span></p></div><div id="https://www.notion.so/838c21196e81444182158c25799d8460" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Retrieving the individual streams from within the container is called “demultiplexing” or “demuxing”.</mark></span></span></p></div><h2 id="https://www.notion.so/532987b631584ad1ad0523e0ef1e7caa" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/532987b631584ad1ad0523e0ef1e7caa"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">2 像素格式:YUV 和 RGB </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-camera-streaming/#%E5%83%8F%E7%B4%A0%E6%A0%BC%E5%BC%8F-yuv-%E5%92%8C-rgb"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/3a3878862ff0472c80452ae023f1c9c6" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">YUV 是一种颜色编码方法</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 。常使用在各个影像处理组件中。 YUV 在对照片或影片编码时,考虑到人类的感知能力,允许降低色度的带宽。</mark></span></span></p></div><div id="https://www.notion.so/6c603143275e4eba925f52d05e6fbd78" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">YUV是编译true-color颜色空间(color space)的种类, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Y'UV, YUV, YCbCr,YPbPr等专有名词都可以称为YUV</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,彼此有重叠。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/a0c631676ef8412ca284c96cb600c396" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">“Y”表示明亮度(Luminance、Luma)</mark></span></span></li><li id="https://www.notion.so/3ec4e08e113d48fc958c010b7448b2c5" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">“U”和“V”则是色度、浓度(Chrominance、Chroma),</mark></span></span></li></ul><div id="https://www.notion.so/2a008f6100254a1e9aec56f9b6e2a9a8" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Y′UV, YUV, YCbCr, YPbPr所指涉的范围,常有混淆或重叠的情况。从历史的演变来说,其中:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/7bf4308ba518461eae6c344f5c5f3fa9" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">YUV和Y'UV通常用来编码电视的模拟信号</code></mark></span></span></li><li id="https://www.notion.so/731683bdfd5144ffb0f36cf48a62ace1" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">YCbCr 则是用来描述数字的影像信号</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ,适合影片与图片压缩以及传输,例如 MPEG、JPEG。</mark></span></span></li></ul><div id="https://www.notion.so/c9bdde82a08c48ccadf024bea332f367" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">彩色图像记录的格式,常见的有 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RGB、YUV、CMYK</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 等。彩色电视最早的构想是使用 RGB 三原色来同时传输。这种设计方式是原来黑白带宽的3倍,在当时并不是很好的设计。</mark></span></span></p></div><div id="https://www.notion.so/21eb08da759648c1a89d0cbac448d022" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RGB诉求于人眼对色彩的感应,YUV则着重于视觉对于亮度的敏感程度,Y代表的是亮度,UV代表的是彩度(因此黑白电影可省略UV,相近于RGB),分别用Cr和Cb来表示,因此YUV的记录通常以Y:UV的格式呈现。</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/a84a09cd8ae64b759692043728653e77" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Y:表示亮度,也称流明;</mark></span></span></li><li id="https://www.notion.so/55048fafc32b4812bfc40417c41c7105" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Cb:蓝色浓度偏移量;</mark></span></span></li><li id="https://www.notion.so/a958e781d00e4bc0870a67bae86c19fa" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Cr:红色浓度偏移量;</mark></span></span></li></ul><div id="https://www.notion.so/ad60768f73a84a078d6d4d3b0eae8b47" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">为节省带宽起见,大多数YUV格式平均使用的每像素位数都少于24位。主要的抽样(subsample)格式有 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和YCbCr 4:4:4</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 。YUV的表示法称为A:B:C表示法:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/fe4eba89214c4d07bc5a56ee934caa72" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4:4:4表示完全取样。</mark></span></span></li><li id="https://www.notion.so/16e918d8cd00432997775fd5845b37dc" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4:2:2表示2:1的水平取样,垂直完全采样。</mark></span></span></li><li id="https://www.notion.so/9d29023053784441b8e6f1819699c8f9" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4:2:0表示2:1的水平取样,垂直2:1采样。</mark></span></span></li><li id="https://www.notion.so/ed88d077f18741728087c007537982eb" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4:1:1表示4:1的水平取样,垂直完全采样。</mark></span></span></li></ul><div id="https://www.notion.so/d86eab92865049b2a4541f33331a9d48" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">最常用Y:UV记录的比重通常1:1或2:1,DVD-Video是以YUV 4:2:0的方式记录,也就是我们俗称的 </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">I420,YUV4:2:0</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> 并不是说只有U(即Cb), V(即Cr)一定为0,而是指U:V互相援引,时见时隐,也就是说对于每一个行,只有U或者V分量,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0…以此类推。至于其他常见的YUV格式有 YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等。</mark></span></span></p></div><div id="https://www.notion.so/ad5982aa19ae43e7a4cb6259e45d6842" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Y’代表明亮度(luma; brightness)而U与V存储色度(色讯; chrominance; color)部分; 亮度(luminance)记作Y,而 Y’的prime符号记作伽玛校正。</mark></span></span></p></div><div id="https://www.notion.so/8cb3528e4c2a4db6bca6b8bfcb50283b" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">YUV Formats分成两个格式:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/12925b184f1849b990f2593cf1b9cc28" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">紧缩格式(packed formats):将Y、U、V值存储成Macro Pixels数组,和RGB的存放方式类似。</mark></span></span></li><li id="https://www.notion.so/5e6c154d08a848bca0187777a6abe0e0" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">平面格式(planar formats):将Y、U、V的三个分量分别存放在不同的矩阵中。</mark></span></span></li></ol><div id="https://www.notion.so/71e92cf4cd9041d6b99659ecd8a6aa55" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">紧缩格式(packed format)中的YUV是混合在一起的,对于YUV4:2:2格式而言,用紧缩格式很合适的,因此就有了 UYVY、YUYV等。平面格式(planar formats)是指每Y分量,U分量和V分量都是以独立的平面组织的,也就是说所有的U分量必须在Y分量后面,而V分量在所有的U分量后面,此一格式适用于采样(subsample)。平面格式(planar format)有I420(4:2:0)、YV12、IYUV等。</mark></span></span></p></div><h2 id="https://www.notion.so/642bdf3c18a341ecb4c5ab3696c9a3ed" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/642bdf3c18a341ecb4c5ab3696c9a3ed"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">3 RTSP 协议:Real-Time Streaming Protocol </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-camera-streaming/#rtsp-%E5%8D%8F%E8%AE%AE-real-time-streaming-protocol"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/299999211b4e4ae893d74e01cfed0fee" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://antmedia.io/rtsp-explained-what-is-rtsp-how-it-works/"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://antmedia.io/rtsp-explained-what-is-rtsp-how-it-works/</mark></a></span></span></p></div><div id="https://www.notion.so/ef1e03361d3c4945a70ce0d6eecbbae2" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The Real-Time Streaming Protocol (RTSP) is an application-level network protocol designed for multiplexing and packetizing multimedia transport streams (such as interactive media, video and audio) over a suitable transport protocol. RTSP is used in entertainment and communications systems to </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">control streaming media servers</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. The protocol is used for establishing and controlling media sessions between endpoints. Clients of media servers </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">issue commands such as play, record and pause, to facilitate real-time control of the media streaming from the server to a client</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> (video on demand) or from a client to the server (voice recording).</mark></span></span></p></div><div id="https://www.notion.so/d0664275fbe543eebb008b087f7696ba" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Like HTTP, RTSP uses TCP to maintain an end-to-end connection and, while most RTSP control messages are sent by the client to the server, some commands travel in the other direction (i.e. from server to client).</mark></span></span></p></div><div id="https://www.notion.so/2fcebba0579545b9ae99fb51ad56c6d8" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">PLAY:</mark></span></span></p></div><div id="https://www.notion.so/de7ebb73376d468897d9a6eae7e4edee" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">C->S: PLAY rtsp://example.com/media.mp4 RTSP/1.0 CSeq: 4 Range: npt=5-20 Session: 12345678</mark></span></span></p></div><div id="https://www.notion.so/e610941a148e485cb90a05368e989449" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">S->C: RTSP/1.0 200 OK CSeq: 4 Session: 12345678 RTP-Info: url=rtsp://example.com/media.mp4/streamid=0;seq=9810092;rtptime=3450012</mark></span></span></p></div><div id="https://www.notion.so/ead4d077b394425f8e8597f350d894fe" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">PAUSE:</mark></span></span></p></div><div id="https://www.notion.so/afb6f4c59a024644825115eb3c6cdbec" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">C->S: PAUSE rtsp://example.com/media.mp4 RTSP/1.0 CSeq: 5 Session: 12345678</mark></span></span></p></div><div id="https://www.notion.so/42132dad5a084b108a60501672069647" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">S->C: RTSP/1.0 200 OK CSeq: 5 Session: 12345678</mark></span></span></p></div><div id="https://www.notion.so/5f897bfefca94b3089616b95e8f794f9" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTP:</mark></span></span></p></div><div id="https://www.notion.so/09962230c77749dc9b04e1b0546b5b68" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The transmission of streaming data itself is not a task of RTSP. Most </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTSP servers use the Real-time Transport Protocol (RTP)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> in conjunction with Real-time Control Protocol (RTCP) for media stream delivery . However, some vendors implement proprietary transport protocols. The RTSP server software from RealNetworks, for example, also used RealNetworks’ proprietary Real Data Transport (RDT).</mark></span></span></p></div><div id="https://www.notion.so/11bb921348f34c6caf664309844bdd68" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTP VS RTSP</mark></span></span></p></div><div id="https://www.notion.so/788525817b424510b7e2cd896d4b4b0b" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP is a realtime streaming protocol. Meaning, you can </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">stream whatever you want in real time</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. So you can use it to stream LIVE content (no matter what it is, video, audio, text, presentation…). </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTP is a transport protocol</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> which is used to transport media data which is negotiated over RTSP.</mark></span></span></p></div><div id="https://www.notion.so/e4cd4867555f4e998d39f686618b0522" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">You </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">use RTSP to control media transmission over RTP</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. You use it to setup, play, pause, teardown the stream…</mark></span></span></p></div><div id="https://www.notion.so/30586a84bdad4008a6066514a6ee39bb" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">So, if you want your server to just start streaming when the URL is requested, you can implement some sort of </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTP-only server</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. But if you want </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">more control</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> and if you are streaming live video, you </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">must use RTSP</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, because it transmits SDP and other important decoding data.</mark></span></span></p></div><div id="https://www.notion.so/a914185a67da4a45ade41ac590a7836b" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">总结:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/c8437aa3c75241cfb8a6fcb57b01b40c" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP 提供了丰富的流媒体控制能力;</mark></span></span></li><li id="https://www.notion.so/97145d8f06774b53a4cdc45046083ab5" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">如果不需要控制,只是 stream,可以只实现 RTP server;</mark></span></span></li></ol><div id="https://www.notion.so/77b5602cfacd4710a0dd860a9afe1cd3" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP is widely used in </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">IP camera</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, running as </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">RTSP server in camera</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, so that user could </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">play(pull)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> the RTSP stream from camera. It is a low cost solution, because we don’t need a central media server (think about thousands of camera streams). The arch is bellow:</mark></span></span></p></div><div id="https://www.notion.so/a836c577b8034c45a6de781fe9021ed4" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">IP Camera —-RTSP(pull)—> Player (RTSP server) (User Agent)</mark></span></span></p></div><div id="https://www.notion.so/bbacb5dc6bfa41b49b6f0abd1662da49" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">The RTSP protocol actually contains: A signaling over TCP, at port 554, used to exchange the SDP (also used in WebRTC), about media capabilities. UDP/TCP streams over serval ports, generally two ports, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">one for RTCP and one for RTP (also used in WebRTC)</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">.</mark></span></span></p></div><div id="https://www.notion.so/95f70365b7674a74963b156eae391831" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Comparing to WebRTC, which is now available in H5:</mark></span></span></p></div><div id="https://www.notion.so/0616a8386c1c42be95b812932ed64355" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">A signaling over HTTP/WebSocket or exchange by any other protocols, used to exchange the SDP. UDP streams(RTP/RTCP) over one or many ports, generally bind to one port, to make cloud services load balancer happy.</mark></span></span></p></div><div id="https://www.notion.so/f8aee6063f104d2484cf52ebb827fe18" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">In protocol view, RTSP and WebRTC are similar, but the use scenario is very different, because it’s off the topic, let’s grossly simplified, WebRTC is design for web conference, while RTSP is used for IP camera systems.</mark></span></span></p></div><div id="https://www.notion.so/41e1f2d1a1ad459e9f6d60ee1d83283c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">So it’s clear both RTSP and WebRTC are solution and protocol, used in different scenario. While RTP is transport protocol, also it can be used in live streaming by WebRTC.</mark></span></span></p></div><div id="https://www.notion.so/ec578f93c7724234b391a548c566b3b2" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">服务端:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/935f0807cb444d9ba4ecf0fe2b92a570" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Darwin Streaming Server</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">: Open-sourced version of QuickTime Streaming Server maintained by Apple.</mark></span></span></li><li id="https://www.notion.so/98a9327eb3a44960af2d980713182e17" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">GStreamer</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> based RTSP Server and client.</mark></span></span></li><li id="https://www.notion.so/a91c23baa6344f15a87b361aec07bb0f" class="NumberedList" value="3"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Many CCTV / Security cameras, often called </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">IP cameras</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, support RTSP streaming too, especially those with ONVIF (the Open Network Video Interface Forum) profiles G, S, T.</mark></span></span></li></ol><div id="https://www.notion.so/3ae8432f28da471599d1bef893d4bcdb" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 GStreamer 的 gst-launch-1.0 来做 RTP streaming (audio+video):</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/2857a769f0144879a4d063ada0f0a7be" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">发送端:gst-launch-1.0 -v uridecodebin name=uridec uri=</C:\video.mp4> ! videoconvert ! x264enc noise-reduction=10000 tune=zerolatency byte-stream=true threads=4 key-int-max=15 intra-refresh=true ! mpegtsmux alignment=7 name=mux ! rtpmp2tpay ! queue ! udpsink host=127.0.0.1 port=5000 sync=true uridec. ! audioconvert ! voaacenc ! audio/mpeg ! queue ! mux.</mark></span></span></li><li id="https://www.notion.so/d6161432e6bc450bbdb0c01f09715d66" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">接收端:</mark></span></span><ol class="NumberedListWrapper"><li id="https://www.notion.so/14a5f902d02f4df795168bf231b3ca30" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">gst-launch-1.0 -v playbin uri=udp://127.0.0.1:5000</mark></span></span></li><li id="https://www.notion.so/74efc996793c443caf221d8c2e3eecc0" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">VLC:vlc rtp://@:5000, Open Network Stream (CTRL+N)</mark></span></span></li></ol></li></ol><div id="https://www.notion.so/25f0f5b2ee5b46ebad9a5b6e32e8a85d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">使用 GStraemer 的 gst-launch-1.0 将本地 jpg 图片转换为 RTP 流:</mark></span></span></p></div><ol class="NumberedListWrapper"><li id="https://www.notion.so/6043be317d974fa9a072586886e7e0ef" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">gst-launch-1.0 multifilesrc location=“C:\\Pictures\\Photo.jpg” loop=true start-index=0 stop-index=0 ! image/jpeg,width=640,height=512,type=video,framerate=30/1 ! identity ! jpegdec ! videoscale !videoconvert ! x264enc ! h264parse ! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000</mark></span></span></li></ol><div id="https://www.notion.so/bd00e2561c874fcb8392bf81db77600c" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP 是可以 streaming 任何数据的交互式控制协议。</mark></span></span></p></div><div id="https://www.notion.so/00cfc07e20124e13861dfc49738c5889" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">关于RTSP_RTP_RTCP协议的深刻初步介绍: </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://zhuanlan.zhihu.com/p/72917813"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://zhuanlan.zhihu.com/p/72917813</mark></a></span></span></p></div><div id="https://www.notion.so/be0be111285442f981a5c9e3ca968342" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">前记</mark></span></span></p></div><div id="https://www.notion.so/3bdd0270f30842bf9aed63c93c90698d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">作为一个软件工程师,特别是偏向安防应用或者互联网对接,都应该听说RTSP,RTP,RTCP等协议的概念。本篇博文详细介绍一下关于RTSP等协议,让读者更加方便的理解透彻。另外后续还会从RTSP的应用方面继续编写。三个协议简单描述</mark></span></span></p></div><div id="https://www.notion.so/a22543d2b2d441129edf0a6bfd8202ed" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">RTSP(Real Time Streaming Protocol),RFC2326,实时流传输协议,是TCP/IP协议体系中的一个应用层协议,由哥伦比亚大学、网景和RealNetworks公司提交的IETF RFC标准。该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或UDP完成数据传输。</mark></span></span></p></div><div id="https://www.notion.so/c97f7cdbbfc344809cbfde3a1aa69017" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Real-time Transport Protocol或简写RTP,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的。RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。它是创建在UDP协议上的。</mark></span></span></p></div><div id="https://www.notion.so/32201a1c68404a6390e7ae6734299cb7" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP)是实时传输协议(RTP)的一个姐妹协议。RTCP由RFC 3550定义(取代作废的RFC 1889)。RTP 使用一个 偶数 UDP port ;而RTCP 则使用 RTP 的下一个 port,也就是一个奇数 port。RTCP与RTP联合工作,RTP实施实际数据的传输,RTCP则负责将控制包送至电话中的每个人。其主要功能是就RTP正在提供的服务质量做出反馈。</mark></span></span></p></div><div id="https://www.notion.so/3714d458553d446bbc51d542c94b8991" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">简单的说,以上三个协议就是负责以下图片内容:</mark></span></span></p></div><div id="https://www.notion.so/638e6c047834462583c0a4b06d5b5920" class="Image Image--PageWidth"><figure><a href="#?width=797"><img src="#?width=797" style="width:100%"/></a><figcaption><span class="SemanticStringArray"></span></figcaption></figure></div><div id="https://www.notion.so/5e187c903649445481d9eab55c6634e3" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">三个协议其实相辅相成,只是读完简单介绍其实并不能深刻理解其协议的深刻内涵或者使用方法以及其架构。下面我们对其协议进行详细拆分深刻挖掘。</mark></span></span></p></div><div id="https://www.notion.so/914866cd838d458cb6d1563f9f9e7a8e" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">参考:</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/0e5d6a86cf8c45d196debe44053a562c" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Micro-RTSP 将 ESP32-CAM boards 的 OV2640 jpeg frame 通过 RTSP Streaming: </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://github.com/enesbcs/ESP32_RTSP_Cam/tree/master/lib"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">https://github.com/enesbcs/ESP32_RTSP_Cam/tree/master/lib</mark></a></span></span></li></ul><h2 id="https://www.notion.so/9e221beb26c44ce5a4afb3c95fc0c5cd" class="ColorfulBlock ColorfulBlock--ColorDefault Heading Heading--2"><a class="Anchor" href="#https://www.notion.so/9e221beb26c44ce5a4afb3c95fc0c5cd"><svg width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4 Motion JPEG/webcam 和 HTTP Video Streaming </mark></span><span class="SemanticString"><a class="SemanticString__Fragment SemanticString__Fragment--Link" href="https://blog.opsnull.com/rust-embedded/rust-esp32-camera-streaming/#motion-jpeg-webcam-%E5%92%8C-http-video-streaming"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></a></span></span></h2><div id="https://www.notion.so/55fb3c5d20a7455a9bb2b2258169d1c9" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Motion JPEG (M-JPEG or MJPEG) is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">a video compression format</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> in which each video frame or interlaced field of a digital video sequence is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">compressed separately as a JPEG image</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">.</mark></span></span></p></div><div id="https://www.notion.so/34e60723b03f49fb94530097a4f719cb" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Originally developed for multimedia PC applications, Motion JPEG enjoys broad client support: most major </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">web browsers and players provide native support</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, and plug-ins are available for the rest. Software and devices using the M-JPEG standard include web browsers, media players, game consoles, digital cameras, IP cameras, webcams, streaming servers, video cameras, and non-linear video editors</mark></span></span></p></div><div id="https://www.notion.so/c081fbb3905f4e3a80943d6ee57fd231" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">M-JPEG is now used by </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">video-capture devices</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> such as digital cameras, IP cameras, and webcams, as well as by non-linear video editing systems. It is </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">natively supported by the QuickTime Player</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, the PlayStation console, and web browsers such as Safari, Google Chrome, Mozilla Firefox and Microsoft Edge.</mark></span></span></p></div><div id="https://www.notion.so/823d04f6356544829a35585ad3e7da21" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Video streaming</mark></span></span></p></div><div id="https://www.notion.so/34c32b715f6c4f8fbb5c410eb8971ec6" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">HTTP streaming </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">separates each image into individual HTTP replies on a specified marker</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. HTTP streaming creates packets of </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">a sequence of JPEG images</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> that can be received by clients such as </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">QuickTime or VLC</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. In response to a GET request for a MJPEG file or stream, </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">the server streams the sequence of JPEG frames over HTTP</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> .</mark></span></span></p></div><div id="https://www.notion.so/f8aa8dd43b47499c8767a6b4e24ab92f" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">A special mime-type content type </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">multipart/x-mixed-replace;boundary=<boundary-name></code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> informs the client to expect several parts (frames) as an answer delimited by </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. This boundary name is expressly disclosed within the MIME-type declaration itself. </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">The TCP connection is not closed</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> as long as the client wants to receive new frames and the server wants to provide new frames.</mark></span></span></p></div><div id="https://www.notion.so/395fb7827b7a4175818d75b380bc0637" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Two basic implementations of a M-JPEG streaming server are </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">cambozola and MJPG-Streamer</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. The more robust </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">ffmpeg-server</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> also provides M-JPEG streaming support.</mark></span></span></p></div><div id="https://www.notion.so/d9c776e84ea4421ca91215f62e14d71d" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Native web browser support</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> includes: Safari, Google Chrome, Microsoft Edge[8] and Firefox.[9] Other browsers, such as Internet Explorer can display M-JPEG streams with the help of external plugins. Cambozola is an applet that can show M-JPEG streams in Java-enabled browsers. M-JPEG is also natively supported by PlayStation and </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">QuickTime</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">. </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">Most commonly, M-JPEG is used in IP based security cameras.[10]</code></mark></span></span></p></div><div id="https://www.notion.so/749b85d3c3fb465aa73ff8acde5f7adc" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Video4Linux: v4l2, v4l</mark></span></span></p></div><ul class="BulletedListWrapper"><li id="https://www.notion.so/b3f0f1bbfb77495aafacb42a63053435" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Linux Kernel 提供的 video capture 的设备驱动和 APIs;</mark></span></span></li><li id="https://www.notion.so/e6acd26f762449b8b48039b0fbac9259" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">ffmpeg 使用 V4L 驱动和 APIs 来捕获视频;</mark></span></span></li><li id="https://www.notion.so/01a4b8839f36403b8c587080eead2142" class="BulletedList"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">gstreamer 的 gst-launch-1.0 工具可以从 v4l 设备 stream 视频:</mark></span></span><ol class="NumberedListWrapper"><li id="https://www.notion.so/3a6d1936ff7343faa2568362b16111bf" class="NumberedList" value="1"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">gst-launch-1.0 v4l2src ! xvimagesink: This pipeline shows the video captured from /dev/video0 tv card and for webcams.</mark></span></span></li><li id="https://www.notion.so/1f992f1c00fd4afe997fec51323c381e" class="NumberedList" value="2"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">gst-launch-1.0 v4l2src ! jpegdec ! xvimagesink :This pipeline shows the video captured from a webcam that delivers jpeg images.</mark></span></span></li></ol></li></ul><div id="https://www.notion.so/39b9fac589dc4118be2c096987c4a171" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Video4Linux (V4L for short) is a collection of </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">device drivers and an API</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> for supporting realtime video capture on Linux systems.[1] It supports many </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">USB webcams</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">, TV tuners, and related devices, standardizing their output, so programmers can easily add video support to their applications.</mark></span></span></p></div><div id="https://www.notion.so/e1ff45db035e40b0b003b85402eecd9b" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Video4Linux is responsible for creating V4L2 device nodes aka a device file (</mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">/dev/videoX, /dev/vbiX and /dev/radioX</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> ) and tracking data from these nodes. The device node creation is handled by </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"><code class="SemanticString__Fragment SemanticString__Fragment--Code">V4L device drivers</code></mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault"> using the video_device struct (v4l2-dev.h) and it can either be allocated dynamically or embedded in another larger struct.</mark></span></span></p></div><div id="https://www.notion.so/9e98b6ceb4a54e9691da280e91e8a846" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">Video4Linux was named after Video for Windows (which is sometimes abbreviated “V4W”), but is not technically related to it.[2][3]</mark></span></span></p></div><div id="https://www.notion.so/2d3468beff6148738a26dfd974a07353" class="ColorfulBlock ColorfulBlock--ColorDefault Text"><p class="Text__Content"><span class="SemanticStringArray"></span></p></div><ul id="https://www.notion.so/675c3da8ca59464686092ef04530a25e" class="ColorfulBlock ColorfulBlock--ColorGray TableOfContents"><li class="TableOfContents__Item"><a href="#https://www.notion.so/e5da397605e14c9a83eb389b90437831"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">1 esp32-camera </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/532987b631584ad1ad0523e0ef1e7caa"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">2 像素格式:YUV 和 RGB </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/642bdf3c18a341ecb4c5ab3696c9a3ed"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">3 RTSP 协议:Real-Time Streaming Protocol </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li><li class="TableOfContents__Item"><a href="#https://www.notion.so/9e221beb26c44ce5a4afb3c95fc0c5cd"><div style="margin-left:0px"><span class="SemanticStringArray"><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">4 Motion JPEG/webcam 和 HTTP Video Streaming </mark></span><span class="SemanticString"><mark class="SemanticString__Fragment SemanticString__Fragment--HighlightedColor SemanticString__Fragment--ColorDefault">#</mark></span></span></div></a></li></ul></article>
<aside class="Aside">
<a href="#content-html"><div id="up">👆</div></a>
<a href="#message-board"><div id="down">👇</div></a>
</aside>
<div id="message-board"></div>
<script src="https://utteranc.es/client.js"
repo="syx-413/syx-413.github.io"
issue-term="pathname"
theme="boxy-light"
crossorigin="anonymous"
async>
</script>
<footer class="Footer">
<div>
© 413’s Website 2020~2024
</div>
<div>
·
</div>
<div>
Powered by
<a href="https://github.com/syx-413" target="_blank" rel="noopener noreferrer"> notablog</a>.
</div>
</footer>
</body>
</html>