本帖最后由 shanji 于 2019-4-27 09:03 编辑
' ?, [' {2 f6 v2 b+ C: t) j8 |* J- g9 r1 o, n( Z
https://www.stmcu.org.cn/module/forum/thread-609701-1-1.html
3 ^8 t4 W" O9 I1 Q距上次分享了个网络摄像头的示例也有一段时间了,用的裸TCP协议,这次来玩玩不同的花样,网页摄像头mjpeg-stream传输,用HTTP协议。网上搜了下,清一色的在Linux下实现的,在单片机上实现的还真没找到,为了玩起来,只能琢磨linux下的代码。
7 |1 t4 d3 A/ _ 一、先把网页做出来
; B9 K" G7 Q6 ]. x6 z# E7 p* u 网页端的实现比较简单,用img标签,例:+ }+ V2 J5 \, E
<html>
/ Z4 w6 {, g* N! O1 n: { <head>
: k7 D7 ^, ^1 c& P2 S </head>
1 w2 f4 |! u9 D! \3 k) f <body>1 g0 P& u( d% I- ]* Z$ l
<img src="http://192.168.1.199:80/?stm32=mjpeg">,此处的ip指的是服务器的ip。
" D- {) k6 i" q1 T6 {6 t! \; T </body>* t7 r& \/ T" i+ J; F9 t
</html>. r8 R5 ?/ R* V N0 b' g) b& y8 b
二、 服务端的代码实现
+ ~+ x3 l# Y7 _& w 要在网页上看到不断刷新的图片,服务端需要发送如下的相应包
9 `( G2 E/ b' u0 z2 c5 t h, J7 Z# a! I HTTP/1.1 200 OK\r\n
* x1 C; D6 a- _/ Y1 X7 n( K2 D# N* I0 j, m# f9 z$ C8 [. O
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编程。 - **
, B6 j6 {1 Y0 x" t6 X& F! ?& P1 M - * @brief 开始发送流' V# i3 u0 I( c
- * @param client,count/ {- i9 w0 S- a" h _" Q- t
- * @retval None
8 P) t U$ d4 q u M, Y& C$ |+ F/ U - */
1 _" W! d+ z9 N - HTTP_STA HTTP_Streamer_Start(int client,u8 count)
$ f& X. j7 T6 G+ Z* j6 T - {
) r- o h2 I6 j. t - int frame_size=0;
: d, H/ A' h1 ~1 k! m# A - uint16_t haed_len=0;6 \/ s6 b9 Y$ ?3 a9 b1 D
- sprintf(buffer, "HTTP/1.1 200 OK\r\n"\
% h- p; Y0 F: t! g - "Connection: Keep-Alive\r\n"\
6 |. h* r& l& R/ r - "Server: MJPG-Streamer/0.2\r\n"\; G. r5 Z6 u- }- B
- "Cache-Control:no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"\
7 X/ }. q% k+ |* ]$ ~' g9 i0 t - "Pragma:no-cache\r\n"\+ }* a) P$ K- {2 L9 o. Z: `
- "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\/ }% q. y; ^$ a) A$ L3 c: E! [- m) `
- "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\
, R8 M( \- I4 n - "--openmcu\r\n");
1 o7 s5 P2 j8 j* a+ V2 A - - e5 x6 F- W8 V: ~: g
- haed_len=strlen(buffer);" [$ V( }0 r, E- Q
- //printf("\r\n%s\r\n",buffer);
" e* b( P* F j Y# G. P - if(send(client, buffer,haed_len, 0)==-1) R' S J! U4 _
- {
1 }/ f) c1 b0 j! C - return HTTP_FAIL;5 }! ], \. }- w. G
- }& c& g1 g& W- L. f9 i
- #if USE_CAMERA9 w- @( _2 g0 R! M
- frame_size=jpeg_data_len();
7 g$ \% I& [3 O7 t5 x: k- }( c - if(frame_size==0) return HTTP_FAIL;0 A3 p/ v, C' t$ l( S/ T
- #else
- G; P' r5 ~7 }7 N( D8 m; t - if(count==0), {! q. L e" v
- frame_size=sizeof(cam_data);
* H O9 l( F- ?8 M ~ - else if(count==1)
; @3 t& ?1 Y1 x - frame_size=sizeof(cam_data2);
% r* }* X% ^, n - #endif 6 \2 a& c0 `) e7 Q" ]* d0 l1 B
- haed_len=strlen(buffer);6 |4 S% `9 K% f* T0 t6 }' |
- , F4 W8 W; Q% h+ Y) @- j
- sprintf(buffer, "Content-Type: image/jpeg\r\n"\5 z' U% j" M0 W5 q0 B# ^
- "Content-Length: %d\r\n\r\n", frame_size);
/ w% s( E. F; k4 O) E) W+ Z - printf("\r\n%s\r\n",buffer);
. X8 V3 f8 ^5 ? - haed_len=strlen(buffer);
# F: a2 V5 `) ?0 o o - if(send(client, buffer,haed_len, 0)==-1)4 m) ^1 T n( K$ d) j* n2 v5 b
- {$ E A: G/ [" M
- return HTTP_FAIL;* ?- V3 x. L, U- a% r( O
- }
# }; @% _) `$ `/ R* A - #if USE_CAMERA9 l4 f0 G! I: q0 v0 Y; y4 b0 }8 d$ }
- memcpy(&buffer[haed_len],(char*)ptr,frame_size);
5 X7 F- t' k5 A$ n4 T - #else- e" W5 w+ Z+ f [5 t' ]6 g
- if(count==0)$ d4 Z! @0 x1 C, n, R/ w) L
- memcpy(&buffer[haed_len],(char*)cam_data,frame_size);
9 o# I0 o r- P' N5 U - else if(count==1)
- a3 z! T, g9 p m - memcpy(&buffer[haed_len],(char*)cam_data2,frame_size);
' f" n' e* Q5 ~ \ - #endif ( A6 y8 z! n: Q( |
- if(send(client, &buffer[haed_len],frame_size, 0)==-1)
8 W3 S/ S# x" v* O8 T9 _' U - {* C( z, s0 b2 y3 G
- return HTTP_FAIL;2 A8 D4 z9 j# t
- }1 }: m' `4 j5 M$ n
- #if USE_CAMERA
% ?6 N0 O7 `* o - newframe=0;
# s _( A/ P2 v' } - cam_start();
1 N" l F+ _1 a% F - #endif+ G/ U9 [$ O8 t
- //lwip_close(client);
8 k' W5 `7 H' h" N- a - return HTTP_OK;
/ w M: b! q# D - }
复制代码: G# Q% c# U- y- }3 y/ @
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。
5 d8 y8 a0 `& {6 p测试源码 |
下次可以和楼主的整合一起
将视频实时显示在屏幕上,- W6 A) @+ h( v
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
: g% M. b2 s/ p/ H5 }! d
感谢支持下! P; k$ u2 E+ u- B. |- Q4 d
关闭连接后发不出去了,需要重新等待客户端的连接。
那为什么send后面要close呢,这样之前的send数据也发不出去啊