你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

全网首发,用STM32F429实现的网页摄像头mjpeg-stream  

[复制链接]
shanji 发布时间:2019-4-1 17:58
本帖最后由 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-replaceboundary网上有很多专业解释,我就不copy了,知道怎么用它就对了。
    要发送图片时的数据包格式是
  --xxxxxxxx\r\n
   Content-Type: img/jpeg\r\n
   Content-Length: 2048\r\n\r\n  //此帧图片的大小
   循环发送这样的数据包给网页,网页上就能看到不断刷新的画面了      
   有了上面的基础,就可以开始码代码。
    关键代码:
     程序中使用了RT-Therad RTOS,用socket编程。
  1. **
    % F) n0 e3 o" b& y9 M( P# W
  2.   * @brief 开始发送流
    % w0 l: T* D$ C( O$ J- a
  3.   * @param  client,count
    4 d2 H! w' x; ?% u8 V, q
  4.   * @retval None
    * _& C0 L) Y* y& ^! [, o! ]
  5.   */5 s# w) e8 \6 }5 K; g, m2 C
  6. HTTP_STA HTTP_Streamer_Start(int client,u8 count)
      f0 ^4 S, v) N
  7. {        + x1 N  z% |, y$ e
  8.     int frame_size=0;  h$ f& ~0 z; m8 E
  9.    uint16_t haed_len=0;, ~0 F6 i( B& C. {  e1 x- ?: D
  10.    sprintf(buffer, "HTTP/1.1 200 OK\r\n"\
    1 n/ r/ |4 k5 ^8 x1 G% d# v8 |' z
  11.    "Connection: Keep-Alive\r\n"\0 }! ^- v1 z6 o3 q+ J2 U4 t) O1 R, i2 O) D( e
  12.    "Server: MJPG-Streamer/0.2\r\n"\& ~% b+ p6 s/ [8 p; B$ `+ o/ o
  13.    "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' }
  14.    "Pragma:no-cache\r\n"\8 M& g8 p3 S; s8 _9 T$ O4 |
  15.    "Expires:WED, 23 Jan 2019 01:00:00 GMT\r\n"\
    ! ^/ w! Y  X$ ~& w8 A- w
  16.    "Content-Type: multipart/x-mixed-replace;boundary=openmcu\r\n\r\n"\6 k' v3 g; H6 {6 Z- }* u
  17.    "--openmcu\r\n"); 0 a% ~/ ^; ~1 t7 d, X0 o
  18.                               " U  m: G8 C. D/ y
  19.     haed_len=strlen(buffer);% p+ n+ O" Q+ i7 u! ?2 v4 o
  20.    //printf("\r\n%s\r\n",buffer);
    8 |' v9 e$ o$ H( A! r
  21.    if(send(client, buffer,haed_len, 0)==-1)' M- p) ?: m3 r# x3 V9 s
  22.    {+ i1 @2 W, ]# V1 j4 V2 C
  23.       return HTTP_FAIL;
    - l4 k% u/ S# q$ X* H4 D
  24.    }9 n% d/ Q% F; L8 ^1 E
  25.   #if USE_CAMERA+ ?; f$ ]" x: X5 O+ B: e6 O
  26.   frame_size=jpeg_data_len(); + h8 ]2 Y1 \) q* I, {5 Q6 n7 m; V) y
  27.   if(frame_size==0) return HTTP_FAIL;
    - b. X- r& L4 r- |- }8 V
  28.   #else% p1 ^3 V) e) O- g; T# U
  29.   if(count==0)$ U# j" }- V3 O* j, ^6 C
  30.   frame_size=sizeof(cam_data);
    1 Z1 I$ o# [6 m$ {+ |8 Q+ A! ?+ I
  31.   else if(count==1). w- o9 Y: X0 Q" i
  32.   frame_size=sizeof(cam_data2);/ O1 o) q6 _/ K8 [8 l3 P, ]) ^7 k
  33.   #endif         
    3 m1 f2 l8 B& P0 _
  34.   haed_len=strlen(buffer);
    ; N, b- k7 K: O+ ^5 G' Q2 ~! @
  35. 5 j% }7 y/ b9 }2 @! r
  36.   sprintf(buffer, "Content-Type: image/jpeg\r\n"\
    * H  x% {* L! Y+ P( I, t
  37.   "Content-Length: %d\r\n\r\n", frame_size);5 u. V9 P7 l' Z) F" M1 z
  38.   printf("\r\n%s\r\n",buffer);" e1 j% e7 n% u8 b7 q% A: ?
  39.   haed_len=strlen(buffer);8 Q6 O8 ^/ b. e/ a2 n( {# z
  40.   if(send(client, buffer,haed_len, 0)==-1)! ~- t- m6 O/ J% V- @
  41.   {4 @+ _  Z" c6 r! O+ L" Z
  42.      return HTTP_FAIL;  L) B" M9 d6 v4 {4 H8 D
  43.    }( I( @( T* F; b# Y& ^
  44.   #if USE_CAMERA
    ) ]* J0 z3 Y7 Y2 v8 \, Y9 k
  45.   memcpy(&buffer[haed_len],(char*)ptr,frame_size);
    & R1 s( H" _4 B# q
  46.   #else! D# i2 h. G; O
  47.   if(count==0)' @$ |. v* j. o1 f" D
  48.   memcpy(&buffer[haed_len],(char*)cam_data,frame_size);5 i2 c6 Q) X8 k) m
  49.   else if(count==1)
    ( J/ m2 v/ |- }# Z! c+ [+ p! O" ?
  50.   memcpy(&buffer[haed_len],(char*)cam_data2,frame_size);: Z  \$ O# x# C8 J5 \2 z4 T
  51.   #endif                 
    + n- e. V% m* E% Y2 }; o# U
  52.   if(send(client, &buffer[haed_len],frame_size, 0)==-1)- O. y, i: i( D2 R- v
  53.   {
    + R" `+ ]3 Q, b9 U6 g) ~8 K
  54.      return HTTP_FAIL;
    6 D, o/ ?0 }7 W! q8 P7 I
  55.   }
    1 M2 j1 L1 F! P' O3 C4 {& e, u' b
  56.   #if USE_CAMERA
    ; ]* C; }5 w& U/ @( A5 S0 G
  57.        newframe=0;  0 p8 u+ E4 p2 |' M
  58.        cam_start();         
    # L9 l5 Z0 f4 y. w" z
  59.   #endif
    ( k5 d  U+ B7 l6 \2 k$ d5 M3 _% S
  60.       //lwip_close(client);                : A% z3 f) A; f7 M# m
  61.   return HTTP_OK;/ B; |9 h) s2 B8 \( y' m" `# J, t( v
  62. }
复制代码

. x7 g5 d! h9 F: c7 I; t
发送完第一帧图片后,循环发送前面介绍的图片数据格式,就能看到摄像头的实时画面了。
GIF2.gif

. s! N7 I; k/ [9 N9 s, T6 G  p1 m
测试源码
【】STM32F429_网络摄像头(网页版)V1.1.rar (1.74 MB, 下载次数: 403)

评分

参与人数 2 ST金币 +13 收起 理由
你若安好_清风徐来 + 5 很给力!
g921002 + 8 很给力!

查看全部评分

1 收藏 19 评论202 发布时间:2019-4-1 17:58

举报

202个回答
昱枫 回答时间:2019-12-19 10:06:22
学习了,  M& ?2 D8 b/ k) `7 n
下次可以和楼主的整合一起
9 Y8 V9 @+ N+ z4 ~1 h5 S8 Y将视频实时显示在屏幕上,
4 m" \( P3 |( I9 S6 x3 Q) d# z1 G" vhttps://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=622494&page=1#pid2473242
* J( H- o. J; p3 F' R3 N
, Y0 [0 y  M" |" t! @# q感谢支持下
% G- R5 |+ I* [( ?
shanji 回答时间:2019-4-3 10:34:11
yklstudent-1794 发表于 2019-4-3 10:16$ l, B+ w/ N* y# J6 c9 p( w
楼主请教下,发送数据后就立即关闭连接,之前发送的数据还能发送出去吗? ...

: g* h3 I1 @7 \* V4 S$ Q' ^& X: f关闭连接后发不出去了,需要重新等待客户端的连接。
yklstudent 回答时间:2019-4-3 10:43:01
shanji 发表于 2019-4-3 10:34# g. d% ^. A' y# o4 X
关闭连接后发不出去了,需要重新等待客户端的连接。
# p- N3 _9 f3 M- }. @3 s5 ]
那为什么send后面要close呢,这样之前的send数据也发不出去啊
海迹天涯 回答时间:2019-4-2 09:30:25
厉害了我的哥
3111272 回答时间:2019-4-2 09:31:44
膜拜大佬
Wature 回答时间:2019-4-2 09:58:24
真的是厉害了我的哥
神奇小芭比 回答时间:2019-4-2 09:59:41
厉害了我的歌
Kevin_G 回答时间:2019-4-2 10:11:11
点赞,超级牛
xiaobai.. 回答时间:2019-4-2 10:41:30
不错
网络孤客 回答时间:2019-4-2 10:54:27
厉害,学习学习!
Bowen 回答时间:2019-4-2 10:54:58
厉害了,学习下
STMWoodData 回答时间:2019-4-2 11:29:19
提示: 作者被禁止或删除 内容自动屏蔽
与我非 回答时间:2019-4-2 11:35:29
厉害厉害
yklstudent 回答时间:2019-4-2 12:32:20
MARK,厉害了我的哥
STMCU-管管 回答时间:2019-4-2 13:00:43
支持支持
七哥 回答时间:2019-4-2 13:04:33
膜拜
老牛洋车 回答时间:2019-4-2 13:20:00
佩服!拜楼主为师。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版