本帖最后由 shanji 于 2019-4-27 09:03 编辑
5 w- _* C0 Y" n9 A8 X4 w4 L- T8 B m- d f' F+ ]; V8 h6 D4 H
https://www.stmcu.org.cn/module/forum/thread-609701-1-1.html
$ T. g) m+ `& S, C u距上次分享了个网络摄像头的示例也有一段时间了,用的裸TCP协议,这次来玩玩不同的花样,网页摄像头mjpeg-stream传输,用HTTP协议。网上搜了下,清一色的在Linux下实现的,在单片机上实现的还真没找到,为了玩起来,只能琢磨linux下的代码。
. i8 I. M% V# T1 E( _* k- H" f7 r 一、先把网页做出来* i" K- b/ b% x: j6 k
网页端的实现比较简单,用img标签,例:
; V( `) D0 B1 H! c3 N& S+ }+ ?! q* S<html>
( o+ Q) M4 `8 }4 L2 |3 S! l <head>9 A/ G) H0 s6 t/ W* L$ o- Y
</head>
- e$ L* F& Q1 V: m- F& P! p* k <body>1 T$ n( @' @. W' k
<img src="http://192.168.1.199:80/?stm32=mjpeg">,此处的ip指的是服务器的ip。
s/ ^/ m5 Z% e8 x% f </body>
0 H0 ?' ?! ?/ F% n2 E7 R+ w</html>/ z4 g0 i/ e/ S
二、 服务端的代码实现
+ W3 v6 l3 ?- I" A 要在网页上看到不断刷新的图片,服务端需要发送如下的相应包0 @( ~; T- a- u2 T% ^- W
HTTP/1.1 200 OK\r\n9 l0 x1 D. _8 f. D4 N
# I3 ]. Z [3 Y( W% x7 E" U! n 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编程。 - **( I( m: j W, i: {
- * @brief 开始发送流
# q9 b" w C* ?! {" B7 A - * @param client,count
/ s8 v- k# A/ v$ y; d6 i T2 d% \ - * @retval None4 e- }7 H% P7 S* {. d
- */6 |. P4 b& H, e: B
- HTTP_STA HTTP_Streamer_Start(int client,u8 count)# n5 [% N; B5 ?6 a9 s
- {
& c+ \. U a& P0 l - int frame_size=0;& y; ^) @+ ?9 B( b5 f; _5 E% L) m: i
- uint16_t haed_len=0;' `. B8 g( c8 f. k
- sprintf(buffer, "HTTP/1.1 200 OK\r\n"\0 o3 {. ~; W6 x$ r: J- |9 d9 D/ \
- "Connection: Keep-Alive\r\n"\
! F1 [/ t* M$ y - "Server: MJPG-Streamer/0.2\r\n"\$ ^! b! H. o# w) v7 K" g
- "Cache-Control:no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"\
: R0 `2 M* x! m3 Y F; a - "Pragma:no-cache\r\n"\" F* [0 g% [' p/ m5 K! W9 w/ j
- "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\8 ^$ R- ~( B' x* I i3 _( q
- "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\4 I: ^( h2 N% s, C: C) m) Q, G3 _
- "--openmcu\r\n");
% i% Q( g1 B; x. H! @8 Z5 n. d1 j -
- p3 e5 K' L5 P v% [ - haed_len=strlen(buffer);3 @: a. w3 w. x$ k; Z- z. M0 u
- //printf("\r\n%s\r\n",buffer);
' j' _0 n3 c3 p - if(send(client, buffer,haed_len, 0)==-1)+ C$ e$ y9 x2 j# k. v1 G+ T
- {
; |( o3 u4 z/ z, R; | - return HTTP_FAIL;4 p7 |' ?- b4 V* Z$ l& h( \
- }
! {+ S% ~( U1 V4 n - #if USE_CAMERA
! l, |8 D, h* n* L, P8 O& Y - frame_size=jpeg_data_len(); ; x+ {7 ~/ O+ T6 E; m
- if(frame_size==0) return HTTP_FAIL;
0 D8 O# \1 w6 s p - #else* l: G$ D- g+ e- [& s: e5 L ~
- if(count==0)- t7 i1 d0 m5 }5 ~$ c6 S: G4 g! Z7 U
- frame_size=sizeof(cam_data);7 ]3 a" {9 I Q! H3 d' A+ U' X
- else if(count==1); M7 ?3 V9 O1 R- p- ^* d
- frame_size=sizeof(cam_data2);
& P1 v, w/ y& W4 a$ [/ l - #endif
& i+ T+ h& b ^# f4 A - haed_len=strlen(buffer);
9 K y, K& h+ K8 }" ]
$ q! K; Z3 V2 Z- sprintf(buffer, "Content-Type: image/jpeg\r\n"\
' E3 Z, o9 K+ v7 n G* J6 v - "Content-Length: %d\r\n\r\n", frame_size);
* U. m) L( K8 I/ O - printf("\r\n%s\r\n",buffer);3 ?0 d5 Z2 P" U7 r, `
- haed_len=strlen(buffer);
; r2 u7 Y4 i, X' f4 K - if(send(client, buffer,haed_len, 0)==-1)
1 x7 p4 y' I( ?" @3 p6 ^ - {2 d3 D! [! ^6 n
- return HTTP_FAIL;* S, X1 {% x; }7 H
- }
! Y! z2 _- P8 q7 c E4 f K3 o' U Z - #if USE_CAMERA v& o$ m; V/ u; T/ j3 F6 d& Y
- memcpy(&buffer[haed_len],(char*)ptr,frame_size);0 R8 C" R* ]7 t" r
- #else
5 m, j4 \6 m* Q# M6 G$ M( l - if(count==0)& K3 F, r, x' |0 W- c$ C
- memcpy(&buffer[haed_len],(char*)cam_data,frame_size);
; p. r5 L1 D' M: E - else if(count==1)
. ]; \- E2 b9 R4 O - memcpy(&buffer[haed_len],(char*)cam_data2,frame_size); F ~$ k5 _& w6 `
- #endif
; ]) F5 |1 n1 v6 c5 A - if(send(client, &buffer[haed_len],frame_size, 0)==-1)0 C/ q* j5 h) M6 l& E: ^: U4 [
- {+ A/ H5 w; z/ [4 V9 k% f1 l; T9 v
- return HTTP_FAIL;/ [# Y7 G6 N" q$ E s3 n5 F
- }! o& b! C# o8 j% j2 b$ O* \$ g
- #if USE_CAMERA
$ |& G+ P$ W4 x. F4 T$ A! n8 d - newframe=0;
J* \, ?+ Q3 j, l) V) A S) o8 | - cam_start();
) u& W# |. | @ L: O/ M' T# t - #endif
$ f5 ]% H. D8 b% \: f - //lwip_close(client);
8 L0 f9 t. ^* e! Z: E - return HTTP_OK;
( H6 f' ]# p1 x+ s j - }
复制代码! d ~4 g% {: k! n2 \
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。
% ]* I6 \( V% L测试源码 |
下次可以和楼主的整合一起
将视频实时显示在屏幕上,
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
) R$ Z. r! X- l/ i6 y
感谢支持下, C$ M q/ [ g+ _8 w1 y* u
关闭连接后发不出去了,需要重新等待客户端的连接。
那为什么send后面要close呢,这样之前的send数据也发不出去啊