本帖最后由 shanji 于 2019-4-27 09:03 编辑 , K8 S. Z j& Q$ Y+ _4 i# C
# _% A2 H9 a( b+ Uhttps://www.stmcu.org.cn/module/forum/thread-609701-1-1.html
5 ?* K, L. ^: t! f距上次分享了个网络摄像头的示例也有一段时间了,用的裸TCP协议,这次来玩玩不同的花样,网页摄像头mjpeg-stream传输,用HTTP协议。网上搜了下,清一色的在Linux下实现的,在单片机上实现的还真没找到,为了玩起来,只能琢磨linux下的代码。
# g5 O5 b* e0 S 一、先把网页做出来! g# z& \5 Y% s2 k
网页端的实现比较简单,用img标签,例:1 a0 |; h2 C: r- ]1 B, J% O
<html>7 J' Z ?# E: v) I
<head>1 T1 i) x" c: `# a+ n! `# f$ r
</head>
0 A! C3 ` Y" U3 }, i/ U, N8 [ <body>/ e5 |6 Q$ c5 N1 r/ ~
<img src="http://192.168.1.199:80/?stm32=mjpeg">,此处的ip指的是服务器的ip。: N" a, q% w4 F" j* s8 a
</body>, X5 E+ {" p; V$ ]0 P
</html>; C C% W; p U7 g& g) R
二、 服务端的代码实现
$ ?9 k# f" X) w" r& b% V 要在网页上看到不断刷新的图片,服务端需要发送如下的相应包
+ D! Q5 N# Z5 ~* E2 ^6 T HTTP/1.1 200 OK\r\n
3 H$ t7 I8 J$ D/ l2 L5 K3 A8 I/ b: @! ^& i }' C2 @# ~( v; G- Q
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编程。 - **
+ m% e& d! _6 \' u( Y) s8 j - * @brief 开始发送流
. M' G) _3 C( L* J - * @param client,count, w9 H8 s) ^1 p
- * @retval None
! |# O$ ]/ @+ T6 D/ q) P$ m- E5 y - */0 L2 ^6 x8 q# d
- HTTP_STA HTTP_Streamer_Start(int client,u8 count)
) k; U/ z; s6 q1 K/ S - { 3 T+ g- T8 R3 `. s, M) {2 C
- int frame_size=0;, L1 N% g8 B) v& o: h
- uint16_t haed_len=0;
$ ^$ g( ?; O2 Q ^6 k0 P' y - sprintf(buffer, "HTTP/1.1 200 OK\r\n"\
1 @' {5 K7 U& I" }: ^5 H U - "Connection: Keep-Alive\r\n"\
% H! D- }) m1 l2 E9 C% U* ? - "Server: MJPG-Streamer/0.2\r\n"\
! X1 L* S1 M2 s" J5 W; z - "Cache-Control:no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"\
* X" C1 P7 @* L1 @- Q - "Pragma:no-cache\r\n"\% j% o M( L# M2 x. C. ?2 C
- "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\
+ e$ i2 L k+ j9 N# c5 ~- }% H - "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\# Q8 X; S8 Q+ I' U7 t, T& ~; ?" {
- "--openmcu\r\n");
9 i: h* k% D1 C5 F& u& r& J -
% \9 a: m0 z4 y( A0 ? - haed_len=strlen(buffer);, @( s. R; _3 S/ }* Y" c7 @/ ^5 O# X
- //printf("\r\n%s\r\n",buffer);) {( A) o" P m t+ b; v3 q+ f" O) P
- if(send(client, buffer,haed_len, 0)==-1)6 r4 B1 i4 ~, Y" c
- {7 y* a' F; w# R+ o! Z+ [, ~
- return HTTP_FAIL;3 R i$ t' h% r* ^3 \
- }' w: ^/ e+ y4 D- X
- #if USE_CAMERA
6 D3 K; a3 [# w8 Z - frame_size=jpeg_data_len();
6 _+ g$ i0 m: K7 L+ i$ [/ C - if(frame_size==0) return HTTP_FAIL;6 y: s; L# [5 m+ D) e1 n
- #else
6 f) z) w( {' V" q4 b3 n# d - if(count==0)4 ?) Q0 r7 U M+ d7 R2 p
- frame_size=sizeof(cam_data);* J; ^6 T: J/ N: d W/ o
- else if(count==1)
* d: R8 _- @" _1 s9 i - frame_size=sizeof(cam_data2);
- }3 v2 l) G3 D" v E8 \3 d' T - #endif
# a6 d( s3 B+ Y) \ R6 E0 d - haed_len=strlen(buffer);$ {" j, m( a! q- c9 E/ K
5 R' b# T0 j7 j7 `5 S! c$ w- sprintf(buffer, "Content-Type: image/jpeg\r\n"\
# ^) c( e& K( ]4 w- L4 H, R - "Content-Length: %d\r\n\r\n", frame_size);
: T1 U2 N- D0 W# i) n2 k1 k - printf("\r\n%s\r\n",buffer);
5 u0 @: j5 [1 D3 D - haed_len=strlen(buffer);. j3 a1 a" K1 R1 v4 ^; h/ h
- if(send(client, buffer,haed_len, 0)==-1)0 }& p$ ~* x/ i
- {
7 i# m. ]- L# _ - return HTTP_FAIL;
7 p; b! u3 R- [ - }
& _* D+ e4 N* {6 X1 D& k$ j$ H - #if USE_CAMERA
0 G' y6 w( ~) O. Y& L9 t1 Q - memcpy(&buffer[haed_len],(char*)ptr,frame_size);
6 I: f! w; [& |/ X7 a - #else3 r& G+ L5 [" i4 \6 @* C
- if(count==0)
, V' _# d6 y+ H% A( x - memcpy(&buffer[haed_len],(char*)cam_data,frame_size);! l1 d- p7 T# [) e2 L7 C N) L9 F. t
- else if(count==1)
' g# _+ E1 P4 n- ]+ L - memcpy(&buffer[haed_len],(char*)cam_data2,frame_size);
. ~, a# |/ C! n4 f D - #endif + g6 K! T, E5 K* ?4 s1 c6 }
- if(send(client, &buffer[haed_len],frame_size, 0)==-1)
* ^8 t2 u5 U& q- p c/ v' ^ - {
* E- ]/ o" I, H4 h8 E$ a, G6 i - return HTTP_FAIL;
/ g v% o3 W9 q! q7 I# L - }1 |9 _: W% y2 {7 U. o R
- #if USE_CAMERA
( q, t( B! e* n6 Q - newframe=0;
: n+ v( o1 X% y. V1 Q - cam_start();
3 e; b3 }$ p1 m( T7 o+ A9 ~* K q+ K - #endif
6 n1 ?' P" u2 O - //lwip_close(client); ) X- p' U: \. @5 I0 `
- return HTTP_OK;
" w3 q! h( r' \) E/ K: h8 @ - }
复制代码/ z# x$ U/ \4 P7 t
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。 , Y `' E8 K2 a2 }
测试源码 |
下次可以和楼主的整合一起1 {9 s3 y: Q0 C- _1 l; a1 W
将视频实时显示在屏幕上,# }, _, g7 K! ^/ U
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
* n! b+ L& U! F: W$ Y
感谢支持下
关闭连接后发不出去了,需要重新等待客户端的连接。
那为什么send后面要close呢,这样之前的send数据也发不出去啊