本帖最后由 shanji 于 2019-4-27 09:03 编辑
. d7 H# F3 B: ^. i3 e
; C: F! n, u; Zhttps://www.stmcu.org.cn/module/forum/thread-609701-1-1.html6 r4 q: J* m4 F, I% m/ d
距上次分享了个网络摄像头的示例也有一段时间了,用的裸TCP协议,这次来玩玩不同的花样,网页摄像头mjpeg-stream传输,用HTTP协议。网上搜了下,清一色的在Linux下实现的,在单片机上实现的还真没找到,为了玩起来,只能琢磨linux下的代码。8 i5 [* c% K: S" ?( Z2 s7 H
一、先把网页做出来
" r- f8 B/ X8 t! ^ h 网页端的实现比较简单,用img标签,例:$ G6 E/ }" X) F
<html>% M7 [$ h- w- L
<head>7 q9 C! W" r& G- I1 {
</head>
7 n+ Z# ?2 R& H. C' q7 @8 [ }: e! I/ O# O <body>6 X- } u+ ^0 B6 Q2 ?( `2 u
<img src="http://192.168.1.199:80/?stm32=mjpeg">,此处的ip指的是服务器的ip。
8 Z$ ]- X6 e! m/ B </body>
& h+ A, Z, D2 Y</html>6 Y5 T, z% Q2 R% Q7 S( }7 K, _
二、 服务端的代码实现
9 o7 D1 Q Q& k' X: [( j- Q 要在网页上看到不断刷新的图片,服务端需要发送如下的相应包: w4 f1 [. s$ {2 q; e2 ]/ X
HTTP/1.1 200 OK\r\n9 v* Q* _8 F% H9 f* K* v- c4 b7 ^
1 K I7 D! G# \) }+ N+ K
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编程。 - **
% F) n0 e3 o" b& y9 M( P# W - * @brief 开始发送流
% w0 l: T* D$ C( O$ J- a - * @param client,count
4 d2 H! w' x; ?% u8 V, q - * @retval None
* _& C0 L) Y* y& ^! [, o! ] - */5 s# w) e8 \6 }5 K; g, m2 C
- HTTP_STA HTTP_Streamer_Start(int client,u8 count)
f0 ^4 S, v) N - { + x1 N z% |, y$ e
- int frame_size=0; h$ f& ~0 z; m8 E
- uint16_t haed_len=0;, ~0 F6 i( B& C. { e1 x- ?: D
- sprintf(buffer, "HTTP/1.1 200 OK\r\n"\
1 n/ r/ |4 k5 ^8 x1 G% d# v8 |' z - "Connection: Keep-Alive\r\n"\0 }! ^- v1 z6 o3 q+ J2 U4 t) O1 R, i2 O) D( e
- "Server: MJPG-Streamer/0.2\r\n"\& ~% b+ p6 s/ [8 p; B$ `+ o/ o
- "Cache-Control:no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"\) N6 x" o3 ?( K! x0 G9 j' }
- "Pragma:no-cache\r\n"\8 M& g8 p3 S; s8 _9 T$ O4 |
- "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\
! ^/ w! Y X$ ~& w8 A- w - "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\6 k' v3 g; H6 {6 Z- }* u
- "--openmcu\r\n"); 0 a% ~/ ^; ~1 t7 d, X0 o
- " U m: G8 C. D/ y
- haed_len=strlen(buffer);% p+ n+ O" Q+ i7 u! ?2 v4 o
- //printf("\r\n%s\r\n",buffer);
8 |' v9 e$ o$ H( A! r - if(send(client, buffer,haed_len, 0)==-1)' M- p) ?: m3 r# x3 V9 s
- {+ i1 @2 W, ]# V1 j4 V2 C
- return HTTP_FAIL;
- l4 k% u/ S# q$ X* H4 D - }9 n% d/ Q% F; L8 ^1 E
- #if USE_CAMERA+ ?; f$ ]" x: X5 O+ B: e6 O
- frame_size=jpeg_data_len(); + h8 ]2 Y1 \) q* I, {5 Q6 n7 m; V) y
- if(frame_size==0) return HTTP_FAIL;
- b. X- r& L4 r- |- }8 V - #else% p1 ^3 V) e) O- g; T# U
- if(count==0)$ U# j" }- V3 O* j, ^6 C
- frame_size=sizeof(cam_data);
1 Z1 I$ o# [6 m$ {+ |8 Q+ A! ?+ I - else if(count==1). w- o9 Y: X0 Q" i
- frame_size=sizeof(cam_data2);/ O1 o) q6 _/ K8 [8 l3 P, ]) ^7 k
- #endif
3 m1 f2 l8 B& P0 _ - haed_len=strlen(buffer);
; N, b- k7 K: O+ ^5 G' Q2 ~! @ - 5 j% }7 y/ b9 }2 @! r
- sprintf(buffer, "Content-Type: image/jpeg\r\n"\
* H x% {* L! Y+ P( I, t - "Content-Length: %d\r\n\r\n", frame_size);5 u. V9 P7 l' Z) F" M1 z
- printf("\r\n%s\r\n",buffer);" e1 j% e7 n% u8 b7 q% A: ?
- haed_len=strlen(buffer);8 Q6 O8 ^/ b. e/ a2 n( {# z
- if(send(client, buffer,haed_len, 0)==-1)! ~- t- m6 O/ J% V- @
- {4 @+ _ Z" c6 r! O+ L" Z
- return HTTP_FAIL; L) B" M9 d6 v4 {4 H8 D
- }( I( @( T* F; b# Y& ^
- #if USE_CAMERA
) ]* J0 z3 Y7 Y2 v8 \, Y9 k - memcpy(&buffer[haed_len],(char*)ptr,frame_size);
& R1 s( H" _4 B# q - #else! D# i2 h. G; O
- if(count==0)' @$ |. v* j. o1 f" D
- memcpy(&buffer[haed_len],(char*)cam_data,frame_size);5 i2 c6 Q) X8 k) m
- else if(count==1)
( J/ m2 v/ |- }# Z! c+ [+ p! O" ? - memcpy(&buffer[haed_len],(char*)cam_data2,frame_size);: Z \$ O# x# C8 J5 \2 z4 T
- #endif
+ n- e. V% m* E% Y2 }; o# U - if(send(client, &buffer[haed_len],frame_size, 0)==-1)- O. y, i: i( D2 R- v
- {
+ R" `+ ]3 Q, b9 U6 g) ~8 K - return HTTP_FAIL;
6 D, o/ ?0 }7 W! q8 P7 I - }
1 M2 j1 L1 F! P' O3 C4 {& e, u' b - #if USE_CAMERA
; ]* C; }5 w& U/ @( A5 S0 G - newframe=0; 0 p8 u+ E4 p2 |' M
- cam_start();
# L9 l5 Z0 f4 y. w" z - #endif
( k5 d U+ B7 l6 \2 k$ d5 M3 _% S - //lwip_close(client); : A% z3 f) A; f7 M# m
- return HTTP_OK;/ B; |9 h) s2 B8 \( y' m" `# J, t( v
- }
复制代码
. x7 g5 d! h9 F: c7 I; t
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。
. s! N7 I; k/ [9 N9 s, T6 G p1 m测试源码 |
下次可以和楼主的整合一起
将视频实时显示在屏幕上,
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
感谢支持下
关闭连接后发不出去了,需要重新等待客户端的连接。
那为什么send后面要close呢,这样之前的send数据也发不出去啊