EDA365电子论坛网

标题: arm mini2440 基于v4l2 ffmpeg x264的视频远程监控 [打印本页]

作者: ulppknot    时间: 2021-2-1 18:34
标题: arm mini2440 基于v4l2 ffmpeg x264的视频远程监控

& H7 m& e) Q9 ]网络上盛传的基于mini2440的摄像头监控一般是基于 MJPEG-Streamer。9 R! Z4 C  Q  C  V
) a# @" N5 m. G
这种方法利用的是V4L2的底层驱动,然后配合mjpeg这种格式的流传输,然后通过浏览器浏览视频和控制。
2 c7 X9 o5 t' b/ G. r# u  w7 c5 |1 {( A/ C% Q4 p* t
下面用一个更接近真实的IP-camera的方案来实现。3 U- V) V9 y. l( _2 R6 p

. ~2 L8 a6 k" V. W这种方案是用的V4L2的视频驱动,然后配合ffmpeg、x264的软件编解码,通过udp上传至pc显示,视频的编解码真的非常麻烦,幸好有很多开源的编解码库可以使用,几百行的代码就可以实现h.264的流编码与传输。6 j+ Q2 T. Z! n

, ^/ F' F  U; y0 J, B3 s0 {usb摄像头得到的数据格式一般是YUV422,如果用的是cmos 摄像头可能是raw原始数据格式,YUV422,是在raw基础上色彩抽点编码,因为人眼对亮度的敏感大于对色彩的敏感,所以并非对所有的色彩编码,这样的数据量会非常的大,视频编解码格式就不讨论了,很多很复杂,当然,你会了,就不会觉得难。
1 O2 f, W2 ]8 g3 z) L3 d1 X" [3 r$ {+ |" b/ Y% @& H/ W
ffmpeg和x264的作用是将YUV422再编码成H.2641 |& Y/ N! w) z- E8 [- W
5 A1 o, `" A% z" ?; C; E$ s1 V! \

- D) \* M4 [* H  ~4 M( C上图看效果,这是在linux中接的图,窗口中显示的是从2440usb摄像头上传上来的视频5 R5 i/ Z; y* ~) `" \
2 g2 a- @7 _) ~/ O, U; ]6 o$ N

5 c1 `0 J$ m4 K' }  ~0 j- J- X. O$ R  g# P( o) E. n* k
这是实物图,手机拍的
) P! o. q* ]5 b9 F  E1 T2 G5 W7 j6 I% H% O; B
4 d$ `/ M, ^  E( T2 o8 B# q( B$ {  d
+ }! L6 s+ Z( s- s+ h5 R
废话少说,一步一步实现
/ p0 r9 }( b/ H+ B* _; r2 R) H$ R- n8 [, z3 c8 m
1、平台8 S' r. y% W1 ^6 M

( D) W+ \5 u! ]; Y! I2 R硬件:arm mini2440,usb摄像头2 U# ], n  j- ?+ g
+ }  @- I7 v) w8 g
软件:fedora14,arm-linux-gcc v4.4.3
" Z" R/ F3 G5 C+ z7 q3 q0 `
8 f7 b1 \2 h. Q' j0 D# R3 D2、源文件
$ S" }7 F/ w( _# s1 H" i7 e, O- h4 R5 z
ffmpeg-0.10.1.tar.gz. x5 i# M) B4 L* C

# o- M3 U  ]* llast_x264.tar.bz2; h3 k( Y5 @0 v. ]$ R
zlib-1.2.5.tar.gz (mini2440中没有libz.so,但是程序运行时需要这个库支持,所以下载源文件交叉编译)
& s, H; U# o/ a3 _8 K以上文件只要会搜索的人都能找到
. x# V* t+ V6 u  X* O1 q' c* J" E4 ?  i
$ }$ u( b4 Q5 t; l5 K; o* {下面开始交叉编译,编译过程中会遇到几个小问题,一一解决
5 f& P. f" \& N( k5 f% ~' K9 x0 z- C; L5 l
1、编译zlib
# |3 H( _3 n7 B2 n0 Y, V
3 l. J  G- T/ T  G' P5 N3 d解压zlib-1.2.5.tar.gz
/ z$ X. v7 o( y
, ^  k6 [+ F8 P9 R; H#tar -xzvf zlib-1.2.5.tar.gz7 y- J* Z& d5 Q. R- B% F& f. M

/ n: x  o8 Z- `4 z4 R进入源文件目录
# A1 k- q' w& g/ t9 k' {: Y
  j# S, _+ _" q1 m1 m#cd zlib-1.2.5
- ~, V0 P( O4 W: J' O2 s& x
8 i' H. T6 A5 \6 l% t* b6 N8 g5 D运行configure配置makefile
, W; e1 C  y* w7 R, C4 Y1 j6 X4 ]2 S/ e  z6 y& u0 m# I! o% ^
#./configure --prefix=/opt/webcam/ffpeg# h5 s; _$ i& Q# o0 g- [8 E( ^! N

0 U: x8 `6 i* F# G7 p& L) R/ z$ T0 h--prefix=/opt/webcam/ffpeg的意思是最后执行make install时,将文件安装在/opt/webcam/ffmpeg,不然会默认安装在/usr/local/lib中,其实这里不写这个参数,最后一起在makefile中修改也可以的。( E! f+ g) M7 r9 p! ?8 A8 z# ]
+ @4 z* C9 W" e4 H4 y+ `, w& h
配置后会在当前目录下生成Makefile
+ U8 y, k( n8 E9 d
' W5 P# K+ n7 F, ]& A% P, a. @修改Makefile以便能够用arm-linux-gcc编译,其实就是把gcc 改成arm-linux-gcc,ar改成arm-linux-ar等) v% E% o0 b3 ~, [8 T+ m! ?" l* h: |

5 T2 A3 _. D' a下面是改好的makefile部分
% \8 a- N1 R) ^: j6 t; V  X  m" y; ~6 Y, ?6 ]' b& M1 |( _, Y
SFLAGS=-O3 -fPIC -D_LARGEFILE64_SOURCE=13 u% {8 o/ b* ?" ]% b
LDFLAGS= -L. libz.a4 u2 J9 d4 s7 f7 W
TEST_LDFLAGS=-L. libz.a. s6 O6 |# m7 ~
LDSHARED=arm-linux-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
  c9 A" c: k7 d+ aCPP=arm-linux-gcc -E
2 c$ T" O. X, k' g! s+ `$ i8 t
! u1 M4 y! o# B# Y8 oSTATICLIB=libz.a
4 Y( z: C' L( ]+ n" K5 eSHAREDLIB=libz.so
3 h" z6 O- ?7 X8 l: B2 b4 tSHAREDLIBV=libz.so.1.2.5" V0 g, f* ~/ p) O
SHAREDLIBM=libz.so.1
' g  H7 [: Q4 p3 s, n& u% J$ i( OLIBS=$(STATICLIB) $(SHAREDLIBV)
; }+ `1 ?) z: }
/ L! a9 x0 q) Z' PAR=arm-linux-ar rc0 V9 C6 ~* }! P! i0 x3 P
RANLIB=arm-linux-ranlib
4 H: e  @1 v1 |/ W, b# ULDCONFIG=ldconfig
+ D& E+ y" m# RLDSHAREDLIBC=-lc) I% S7 P. a; k: w! y
TAR=tar
+ l, i. i) \5 j  ?  J0 P: oSHELL=/bin/sh6 G& `; k& d3 d, ?" o+ h. k; B( t
EXE=9 `; E( X- \, M  Q; W/ y" v6 I

* N7 d7 B4 R9 V+ z4 I# }prefix =/opt/webcam/ffmpeg
$ N. d4 y( E. ?! ^- Z8 Y7 Y运行configure是的--prefix 就是最后这个参数,这里修改也行的2 `, R$ |5 v/ J: E3 J/ k
然后make,make install/ {) O) h: I" n9 S, P  P& y9 A
$ N$ Z0 J, \& n% X
#make2 k+ O1 Z: S" ^6 `2 I6 p. N7 g; c
' R; h# z. ]( }" F# d
#make install8 _2 K% J) p3 B/ g" h7 |0 e, G2 J
' y/ X& y/ a0 `/ c( U$ f
zlib的编译应该不会出现问题,在/opt/wecam/ffmpeg中是编译好的文件,在子文件夹lib中的.so文件最后要复制到2440里
% x/ O3 q  p$ N" I( P
% l) Q' U  A' C6 g% L0 h; @
! H: H3 a" C& p) X9 J  u2、编译x264
7 R! j7 k# d+ {2 C7 T. d9 C2 P5 `+ K+ y, I; b
应为编译ffmpeg时需要要添加对x264的支持,所以要先编译好x264,一边让编译ffmpeg时能够找到它& u) v. W% _' u7 p* e

+ o% R/ F# m( U6 ?% |解压last_x264.tar.bz2
( v. g3 x% \4 i1 O: _+ H
/ s7 T, c& [5 `8 x#tar -xvzf last_x264.tar.bz28 Q2 H# R4 T. l4 x$ h

7 T7 o  N% y: U% [: \+ J) o#cd x264-snapshot-20120316-2245" ]! [% x$ I' E4 p' R  ?8 y
" i( p; P# {" o" z
# ./configure --host=arm-linux --prefix=/opt/wecam/ffmpeg --enable-shared --disable-asm* ^+ m5 U4 Y$ ^2 A4 X4 x  W& b

7 w4 ?+ [2 m4 x5 s配置选项中已经添加了host的选项,所以makefile就不用再修改了,但是要修改config.mak  p) d: }1 w- \/ `

( B. R: X! x! xSRCPATH=.5 w' c3 r" l; m: w) K3 |, k
prefix=/opt/webcam/ffmpeg
  X# D8 C- z) N! A8 m+ f' Mexec_prefix=${prefix}
5 ^8 l3 R5 }' t  v; M9 s$ [bindir=${exec_prefix}/bin" L) i: Z" y$ k9 I8 j5 ^
libdir=${exec_prefix}/lib$ F4 t( H8 \9 K6 O% e* C
includedir=${prefix}/include1 w' Z& E* O" E/ N, J" l9 X
ARCH=ARM2 T  x* R# Y" n6 u
SYS=LINUX
8 s) U. v5 f/ hCC=arm-linux-gcc
4 |4 W) x  ^. p9 R/ N( x7 m% j& Z( QCFLAGS=-Wshadow -O3 -fno-fast-math  -Wall -I. -I$(SRCPATH) -std=gnu99 -fPIC -fomit-frame-pointer -fno-tree-vectorize1 l* f1 `1 X1 \
DEPMM=-MM -g03 m: |8 H0 v: ~. l
DEPMT=-MT. a! j- e! n. [) D& I. A2 x
LD=arm-linux-gcc -o
; F  ^! }/ p2 M) U+ @- i; ~LDFLAGS= -lm -lpthread& y# ^) R! }% b+ D
LIBX264=libx264.a
  E0 l! t, V: I' z7 MAR=arm-linux-ar rc
5 ~& ^# B" K" J9 PRANLIB=arm-linux-ranlib
+ @5 o3 N) _3 C! ASTRIP=arm-linux-strip6 L4 ?# k2 |8 }+ i! Q3 d
#make) \1 Q) f  m1 a- I) O
) i- L+ Y4 c, g: f
#make install
7 O; ]1 ~7 ]# G8 n9 ^: V( \/ Q% o9 S3 n5 x+ _, F( Z4 I
x264编译也不会出现问题的,如果有,把之前安装的pc端的x264全部删掉' i8 b  o5 P* t7 W8 Z9 [/ A

. a% l' R6 W( l0 R* E+ t% S
/ r1 A2 o) c3 u2 F$ }3、编译ffmpeg
' M9 q  Z. y1 O3 z) w( p6 W
* Z7 m9 d; X% {解压ffmpeg-0.10.1.tar.gz
' O& w, |9 ]# n! O4 _9 D! U% H5 m4 _( Z, D% z3 H
#tar -xzvf ffmpeg-0.10.1.tar.gz
4 X* R5 W+ c* Y! n  \- R  h1 b, ^# @: q' \- J( G7 ]( g3 d
#cd ffmpeg-0.10.1" ~9 _3 x$ `! k8 O9 r9 }
- {; n5 \3 B5 N4 x3 m
#./configure --enable-cross-compile --target-os=linux --cross-prefix=arm-linux- --cc=arm-linux-gcc --enable-shared --arch=armv6 --enable-gpl --enable-libx264 --prefix=/opt/webcam/ffmpeg --extra-cflags=-I/opt/webcam/x264/include --extra-ldflags=-L/opt/webcam/x264/lib/
- q6 j: D* G- n5 W5 U) D7 M; l9 A  W8 v  ]+ `
配置需要注意的是--extra-cflags=-I/opt/webcam/ffmpeg/include --extra-ldflags=-L/opt/webcam/ffmpeg/lib/ 指定x264库的位置
, U# C1 o) z% g+ _0 m" t0 {: |
" a( P" W" g# P#make. ?( n) }" b0 J. k1 u2 R5 q% A

5 u. x' J  U3 N#make install
& ]8 n6 |# [9 L; D+ B4 g1 T% y9 Q  `  Y5 ^  C4 \2 o) o
以上,所有依赖的库就都编译好了,下面编译webcam应用程序: Y6 ]/ ^  |" g, ^- |* t8 ^8 k

! `: n9 i- `4 u( n( j4 a  f6 \. R+ p: j; l  r/ H4 p5 ~
所有的源文件不做除了修改udp上传用的ip地址和makefile文件外,不做任何修改,源码存放位置/opt/webcam
3 ^- Q* w# z4 h$ V2 f+ f/ B; p9 h& Z
5 t5 [6 s7 u, l2 v1 |1、修改server.cpp ip$ @5 S) v# S& D6 v
5 s' v' R& Q2 a, P0 p
将#define TARGET_IP "192.168.1.220" 后面的ip改成你的pc linux的ip,依旧是客户端webcam_shower所在的pc的ip地址3 `/ ~7 B3 f- Y/ N
* q; C) s1 T& d- [9 o: U' Y
2、修改shower.cpp中的
1 X6 O5 z3 _) t9 g# ?
3 P- y! O( M# Xinet_addr("192.168.1.220"); 将ip修改为pc linux的ip,就是自己的ip,socket绑定端口用
" r' q( H3 |% l3 C1 a  b* I% L5 @4 @& l( j% l
3、修改makefile,以便交叉编译webcam_server,注意,之前编译zlib x264 ffmpeg都在放在webcam/ffmpeg中了
3 a7 }" w/ D. X4 o  i+ p( z
; {0 q( ^/ j3 p: h4 _* ]5 |all: webcam_server
" V1 V+ O! P8 y  A8 \#webcam_shower, ^7 `+ ~# j3 T8 `5 Q
CC=arm-linux-g++
& |8 I8 \' J  I9 a4 H# {LD=arm-linux-ld
$ n5 y$ E' K$ ~$ F8 D5 {, |, u/ eCXXFLAGS=        -c -g -O0 -fPIC -I./ffmpeg/include -L./ffmpeg/lib
- V! C7 G8 I4 h" G% W
' B& O, _% H) k% R3 w) vOBJS_SERVER=        capture.o vcompress.o sender.o server.o
& S0 Y! l" \- p; t& [8 C( P) HOBJS_SHOWER=         vshow.o recver.o shower.o
) b( s7 ?, D5 [; A) vLIBS_SERVER=        -lavcodec -lswscale -lavutil -lx264 -lpthread -lz
2 F0 J2 ?& N; MLIBS_SHOWER=    -lavcodec -lswscale -lavutil
& g9 h5 ]: b' x  z6 G2 y4 i) k: u; T9 s: N9 ~. g& V  V/ d/ y6 W
.cpp.o:( A  O; M8 V6 O: G& w: t. |
        $(CC) $(CXXFLAGS) $<
( V7 b1 z, q. J! A5 x* B, [. V! z. H
webcam_server: $(OBJS_SERVER)
9 u  x% {- v. a        $(CC) -o $@ $^ -L./ffmpeg/lib $(LIBS_SERVER) 1 H1 I# v; B& v# F

* @( v0 [2 c/ L/ I& {$ c$ pwebcam_shower: $(OBJS_SHOWER)' h: ^; d8 ^% p, l0 b9 w
        $(CC) -o $@ $^ $(LIBS_SHOWER)
- q: Q8 v& r( O! }& u6 x! f7 F( K7 i
clean:4 s. A" M# t' ^9 A- W: E
        rm -f *.o( F7 J3 ^8 q: o2 Q+ }. S3 Q
        rm -f webcam_server
3 a" Y4 k  s5 k8 \- W, W        rm -f webcam_shower
6 h' o) E' q, j2 l' b6 q7 C
/ z! e0 i! J# u- Q9 d2 |; [8 r#make
! h6 n) q! l, N) G! A, p' B这一步会出错,报c与c++兼容问题,在include/libavutil/common.h中添加如下,即可
6 }: f0 e$ y, F  U
, u' x2 q3 Z! b2 a: V4 z; F! L& |#ifndef   UINT64_C* l3 ^. ~! _7 d5 b$ W' w
#define   UINT64_C(value)__CONCAT(value,ULL)2 O( Y" j9 u. K1 K  S
#endif8 q3 o- W4 f/ J8 b' S9 o

5 Q1 j0 H" T  P+ k1 t8 D; s3 @1 p8 a9 ?: v' g
最后就得到了编译好的web_server了,将web_server复制到mini2440中,并且将之前编译的第三方编解码库/lib下的所有.so文件复制到mini2440的 /usr/lib中
1 q  }; X0 Y4 x8 w6 N
. _8 F. I2 L- h- s. n: @( D( ]插上usb摄像头,webcam_server就可以再mini2440中运行了
6 Q  z" {0 m; R: y
2 h. ^2 F$ |- B+ l( R  Z5 }: @- B+ p+ e% V: ]$ c2 L' j
最后是编译pc端的webcam_shower,这个很简单,按顺序从头编译就好了
作者: regngfpcb    时间: 2021-2-1 19:02
arm mini2440 基于v4l2 ffmpeg x264的视频远程监控




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2