本帖最后由 shanji 于 2019-4-27 09:03 编辑 # `5 v$ O6 l3 M0 Z
+ F; w- O2 ~1 W Z7 _! ^$ ^https://www.stmcu.org.cn/module/forum/thread-609701-1-1.html
# j" f( ^: [* X( E) D1 j( L3 L, x距上次分享了个网络摄像头的示例也有一段时间了,用的裸TCP协议,这次来玩玩不同的花样,网页摄像头mjpeg-stream传输,用HTTP协议。网上搜了下,清一色的在Linux下实现的,在单片机上实现的还真没找到,为了玩起来,只能琢磨linux下的代码。& U1 n a5 z y1 u, L! ^
一、先把网页做出来# m0 ]+ ~+ y2 E5 J2 h
网页端的实现比较简单,用img标签,例:/ ]7 `! D2 m3 I+ W) k9 l2 G
<html>
' [* v, v! d0 P8 Y5 I+ l <head>% I4 {+ y0 o2 C0 p
</head>
! F. U$ e. v# ]9 Z- ]/ C. t <body>
9 S; j9 v/ V: c) G2 t8 Q' W <img src="http://192.168.1.199:80/?stm32=mjpeg">,此处的ip指的是服务器的ip。
) g5 C& G' T; W# X4 D; A0 Z </body>
! V. K0 N3 E, v& ~- \</html>; y9 p& v& Y! [, e6 P) Z- s8 b4 \
二、 服务端的代码实现! W$ {( c0 \8 r9 m# v% \! G# b
要在网页上看到不断刷新的图片,服务端需要发送如下的相应包
. b* w7 Z: S/ F HTTP/1.1 200 OK\r\n8 y8 o7 z1 v$ q& l+ b- G6 J0 o
# W7 g- C6 \8 w' _6 d+ L/ \8 L
Content-Type: multipart/x-mixed-replace;boundary=xxxxxxxx\r\n\r\n //boundary后面的字段可自行定义 关于multipart/x-mixed-replace和boundary网上有很多专业解释,我就不copy了,知道怎么用它就对了。 要发送图片时的数据包格式是 --xxxxxxxx\r\n Content-Type: img/jpeg\r\n Content-Length: 2048\r\n\r\n //此帧图片的大小 循环发送这样的数据包给网页,网页上就能看到不断刷新的画面了 有了上面的基础,就可以开始码代码。 关键代码: 程序中使用了RT-Therad RTOS,用socket编程。 - **
5 B# x, p, Y) Z% k% g& } - * @brief 开始发送流
3 E& T. P" m- W) U0 s! p- a4 Y - * @param client,count
2 N3 E" J4 u8 L. S/ Q - * @retval None( T) J+ ]2 ~) }4 D, X
- */8 E2 d% V6 s" v, z% W. {* k
- HTTP_STA HTTP_Streamer_Start(int client,u8 count)
' c2 z! Y* q; l& e6 ` - {
* [6 C e7 g. {% Z; @5 \ - int frame_size=0;) V4 E: l% J* o# v" g b! s1 W3 P
- uint16_t haed_len=0;
6 x9 e+ p5 r: m0 i4 v$ g p% W - sprintf(buffer, "HTTP/1.1 200 OK\r\n"\6 F) U Y. x2 J3 f \
- "Connection: Keep-Alive\r\n"\
2 A; L0 d& V$ K: z$ C2 M6 a3 R - "Server: MJPG-Streamer/0.2\r\n"\: }( O, W3 Q6 f% m
- "Cache-Control:no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"\
1 U j9 r% ]3 V# R. q! ` - "Pragma:no-cache\r\n"\
1 I* Y% i) y7 ~4 ?/ u - "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\
, _9 P+ C% e" y - "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\
4 Q3 e, n) `2 N: t% m - "--openmcu\r\n");
5 z2 \' o& H! ~# W! O p9 y) S - ) }& f) P9 T5 o- v3 \9 [+ k
- haed_len=strlen(buffer);9 G+ E9 X1 L# Y7 I
- //printf("\r\n%s\r\n",buffer);
8 S+ O, T4 Q0 A - if(send(client, buffer,haed_len, 0)==-1)! U4 z- X$ N0 ?# X: _
- {+ S- W( ^# J- h4 W" d) Q5 a
- return HTTP_FAIL;2 F# L6 p% s3 G! `
- }; k$ @+ Z+ `' x& l2 t* `, u
- #if USE_CAMERA
; \0 j- h6 ?$ x% |2 T. B. a+ G - frame_size=jpeg_data_len();
# i) h% r: ]! j6 H" L - if(frame_size==0) return HTTP_FAIL;" A: H8 \9 r( j' A( l/ d
- #else5 J5 D7 j' N; b8 Y' t
- if(count==0)
2 D9 h7 c/ D5 T3 F - frame_size=sizeof(cam_data);
0 j4 U$ T" K$ `1 L - else if(count==1)
) [; S7 Z5 h p7 ?; q! ], P- R @ - frame_size=sizeof(cam_data2);
" R8 X$ R. f" `+ T- w- f5 r# c# K3 t - #endif 9 y9 u* F9 K9 j7 c1 n, l) C R
- haed_len=strlen(buffer);$ ]0 w4 h# K; ?" _$ o/ ^3 R
- / Q1 S# s! M' |
- sprintf(buffer, "Content-Type: image/jpeg\r\n"\
: d( ^0 _6 n/ x - "Content-Length: %d\r\n\r\n", frame_size);) o8 | }* s3 V9 ^8 g, l( K
- printf("\r\n%s\r\n",buffer);
( h: U- H, Q4 q4 ]4 f' @' B - haed_len=strlen(buffer);
9 Z" }7 K2 z& E* x1 j/ m - if(send(client, buffer,haed_len, 0)==-1)3 B* T: A. x9 i8 U' X/ A6 b9 W& n
- {
9 Z8 }$ D% f' e t& j - return HTTP_FAIL;
; B4 ~6 o5 r2 ^ - } o5 x# H: [ y
- #if USE_CAMERA% U% V8 t7 m# v+ p# L
- memcpy(&buffer[haed_len],(char*)ptr,frame_size);
& c- a o: a! D. L: t! X - #else
7 L* Y9 y* n9 l - if(count==0)
B+ T( a( n; e5 L0 g- c: _ - memcpy(&buffer[haed_len],(char*)cam_data,frame_size);% w b7 i9 j0 H; F7 q3 S
- else if(count==1)# |6 l& j# l1 I7 b7 z; E- H
- memcpy(&buffer[haed_len],(char*)cam_data2,frame_size);1 l; r; V8 T, ]2 R1 R; ?
- #endif
9 P% ~$ L9 N$ U0 X) n2 T2 l! N - if(send(client, &buffer[haed_len],frame_size, 0)==-1)6 H* {0 ~9 D0 W, t9 Z
- {
, D3 M5 R) l% Q. I9 f/ [ ]% S5 ~ - return HTTP_FAIL;
/ y- H6 D. J9 A' ]) ~. v - }
- K) T2 K( g) |, b6 \; z - #if USE_CAMERA
! H( h; T: k. k2 C; F" \6 } - newframe=0;
5 T0 p. i a& ]' h r2 z - cam_start();
; ]8 @0 C! x$ c0 y3 u0 h: ^& C - #endif( v! j% i4 ]. }9 l, e
- //lwip_close(client); ( {2 ^! e$ i: W0 Q1 Z: z1 F
- return HTTP_OK;
) i: z& C, l" F) t4 j3 m - }
复制代码
' T) I! K' |- l1 r
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。
' t. z. n9 q3 N) j; F# b- i* v测试源码 |
下次可以和楼主的整合一起
将视频实时显示在屏幕上,+ e7 d \& h3 z% ]' [- O2 p
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
感谢支持下2 }9 m M5 x% v. Q* q% ]
关闭连接后发不出去了,需要重新等待客户端的连接。
那为什么send后面要close呢,这样之前的send数据也发不出去啊