|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
; A0 q; D6 v6 ` l
网络上盛传的基于mini2440的摄像头监控一般是基于 MJPEG-Streamer。
) X( K6 @- }" @0 \% J" ~
; I, I j$ k+ ~ G这种方法利用的是V4L2的底层驱动,然后配合mjpeg这种格式的流传输,然后通过浏览器浏览视频和控制。
& r( y4 I; Y/ s6 I; B k* F7 ^ ?5 d2 r
下面用一个更接近真实的IP-camera的方案来实现。4 e9 p/ {" I0 V
$ `- l6 ^. n( ?$ T2 ?这种方案是用的V4L2的视频驱动,然后配合ffmpeg、x264的软件编解码,通过udp上传至pc显示,视频的编解码真的非常麻烦,幸好有很多开源的编解码库可以使用,几百行的代码就可以实现h.264的流编码与传输。+ Z4 E4 A6 l0 p) x0 h" y
0 ]9 j' S/ [4 B& u; ^2 V1 v" }+ `6 Uusb摄像头得到的数据格式一般是YUV422,如果用的是cmos 摄像头可能是raw原始数据格式,YUV422,是在raw基础上色彩抽点编码,因为人眼对亮度的敏感大于对色彩的敏感,所以并非对所有的色彩编码,这样的数据量会非常的大,视频编解码格式就不讨论了,很多很复杂,当然,你会了,就不会觉得难。
/ Q1 C9 Y2 A! w7 U# }' x7 K U1 s* V7 Y+ V
ffmpeg和x264的作用是将YUV422再编码成H.264
+ I* f! a3 W- p+ `# u* |% \& d& \3 O( D/ y4 b& i
+ ?7 v2 l( z0 u! q e" P
上图看效果,这是在linux中接的图,窗口中显示的是从2440usb摄像头上传上来的视频' R$ n( j" e6 y* s0 k$ J
/ J/ O! Y4 o# {8 p$ }
" P6 Y5 k+ R8 C7 U; `2 W9 A% q; A' w" w; b) y5 \
这是实物图,手机拍的; ~. f. A+ d% P: g& C8 I0 E
7 Q# S/ E2 p7 N! E
( o0 c, n v% H0 J3 {' \1 ]5 }# t v
/ e1 U9 x; Y: N& ?. f
废话少说,一步一步实现3 Y+ y2 T$ S' s8 y5 H5 L% E- _
( B0 e' L; _1 X9 w1、平台
6 O( C& p' M- a+ p% V
. |- S4 J$ r6 Q4 |* b硬件:ARM mini2440,usb摄像头7 S. j3 _2 d7 b( \8 R7 Q4 s* N% W
& ~5 r" E+ R! i0 G5 t软件:fedora14,arm-linux-gcc v4.4.3
! t+ `* I( I4 t( J' U& p
/ k, m. J6 D, ^) |7 E3 `2、源文件1 J9 [% ]; R3 x7 j& ^1 X6 R9 V
0 [" @1 e! o. F) C) I" J/ A R
ffmpeg-0.10.1.tar.gz
$ t `" k9 P% @ d& |/ h8 [
3 Y* f. F6 `6 w! K; n2 \* qlast_x264.tar.bz2* ^0 c( z! r8 u t9 x" c, @: o' A
zlib-1.2.5.tar.gz (mini2440中没有libz.so,但是程序运行时需要这个库支持,所以下载源文件交叉编译)8 |; v1 @' B# f6 y3 \3 e' M
以上文件只要会搜索的人都能找到
) e) i/ h. x' J: T% @$ ^. ], y) Z
下面开始交叉编译,编译过程中会遇到几个小问题,一一解决
* I) y* ?. f2 ~0 V; k
: y/ \5 {+ c7 Y% ]- L5 O) i* L$ d+ k1、编译zlib
8 [0 F6 N( R) ]# g6 i4 v$ d" @
% W+ L c3 v! m! E3 K解压zlib-1.2.5.tar.gz% W; \0 N! Z0 E( R
( y& a2 e7 I/ j1 U2 o#tar -xzvf zlib-1.2.5.tar.gz
5 u5 G6 b5 T- r7 l5 O& X# S/ Y2 C; s7 v% u0 x3 p5 F" {
进入源文件目录. I- ^! i* o5 _- _4 ~% S6 ^9 m1 h! o
* b( \; }/ ?3 S2 {
#cd zlib-1.2.50 c/ X) l3 g2 J6 K4 q
8 H, u w- I7 [7 q( p运行configure配置makefile
( G, F! {/ r- b$ S; G! _# q6 }0 f. h
#./configure --prefix=/opt/webcam/ffpeg- J1 @$ P9 u6 l) o5 [$ q
+ c( z) A2 T) V% a5 p
--prefix=/opt/webcam/ffpeg的意思是最后执行make install时,将文件安装在/opt/webcam/ffmpeg,不然会默认安装在/usr/local/lib中,其实这里不写这个参数,最后一起在makefile中修改也可以的。
/ [3 ]" x( I0 E. s3 N6 l6 |! X, b4 W, G( j8 K8 D
配置后会在当前目录下生成Makefile% q7 Z% {+ x$ X( |4 K: G; t
4 S6 H" }0 y" A8 R5 W
修改Makefile以便能够用arm-linux-gcc编译,其实就是把gcc 改成arm-linux-gcc,ar改成arm-linux-ar等* K8 p* ~( h5 V4 L& Z# q! l1 g5 `
9 O- z% m+ |/ l }( n4 |7 o& N下面是改好的makefile部分9 p0 N4 r) j) ~: j; ], [2 L& M0 z$ h! U' }
. M1 n& O9 r) x2 i9 _+ XSFLAGS=-O3 -fPIC -D_LARGEFILE64_SOURCE=1
2 q1 o6 a! \& jLDFLAGS= -L. libz.a V- V7 h2 `* T2 _
TEST_LDFLAGS=-L. libz.a
' f* C8 J9 k+ Y+ R( k. M) c' n wLDSHARED=arm-linux-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map' y! O- k- M1 {' }; A: x
CPP=arm-linux-gcc -E
0 @9 \7 h% V4 r% P* ^; {6 _* g6 i) p' S3 ?5 T( H6 g& w
STATICLIB=libz.a
0 S: ]' ]3 c: W" rSHAREDLIB=libz.so
. i* ]& R. U4 Z# NSHAREDLIBV=libz.so.1.2.5
% l d, r/ r8 O x, x: tSHAREDLIBM=libz.so.1
5 O. p0 A0 H8 y2 `1 MLIBS=$(STATICLIB) $(SHAREDLIBV)% c, j3 |1 P7 G8 ?! ~
9 _3 @* j0 g+ r `/ `. j p! P
AR=arm-linux-ar rc
3 a; L4 S4 t7 j3 O" L( n/ k( kRANLIB=arm-linux-ranlib, D6 z+ h& ~) p6 [' w. t
LDCONFIG=ldconfig& Q/ a8 N8 _" A3 o" W- \
LDSHAREDLIBC=-lc! P" a2 f# z1 M+ H2 o
TAR=tar9 T( u8 o5 S* c* A2 y& B: b# V+ W
SHELL=/bin/sh
2 c- E! X/ b6 {( gEXE=
2 b- Q9 {% v/ E2 t& C7 k7 {* O1 ?
/ a2 G) m# o; T( H8 a4 c3 Jprefix =/opt/webcam/ffmpeg
4 w/ G F. ?* | H7 M5 k3 I- I运行configure是的--prefix 就是最后这个参数,这里修改也行的
+ C/ U6 ?$ L# O+ i; i1 k( E' G然后make,make install
1 A7 R! M R* g1 u4 J/ x
" {5 A) g8 a' { p! ^#make m) x8 y' c, H- B u t
5 g+ o# p4 e3 I, S2 U; N6 l Y% n
#make install
! a C8 k: \- q+ ?% W
- h3 |# m: z0 Dzlib的编译应该不会出现问题,在/opt/wecam/ffmpeg中是编译好的文件,在子文件夹lib中的.so文件最后要复制到2440里- i, R' i4 y% t) _% {
; N) m7 `8 T* E* G; O
9 k8 c- x/ g8 I* Y# e; b, W/ }2、编译x264
+ O5 K5 ?$ [! r# ]+ P
) F$ A, z/ f9 Z* n: U$ O' `7 P( I应为编译ffmpeg时需要要添加对x264的支持,所以要先编译好x264,一边让编译ffmpeg时能够找到它
5 `2 k) B" q! i( }9 b- ]5 [9 }! h$ c# P& `3 I# M* ~" q
解压last_x264.tar.bz2
6 P, a3 Y/ K2 Y/ R& U3 ?# e: s1 ?) w& `2 W$ E! Z5 C
#tar -xvzf last_x264.tar.bz2
3 c* ~& ~3 Y- Z$ I u4 D; A4 d1 l% E7 N! K$ N" R
#cd x264-snapshot-20120316-22451 b, @$ p3 z$ M# m+ J8 `
4 \& z7 y; k7 P% x# K
# ./configure --host=arm-linux --prefix=/opt/wecam/ffmpeg --enable-shared --disable-asm
( r j1 h2 o+ b4 ]% A6 z1 U. B/ C" T6 W A4 d! n4 \
配置选项中已经添加了host的选项,所以makefile就不用再修改了,但是要修改config.mak6 R4 ?* F* T* _- o( g
: `+ x9 D9 I7 Y% m2 i7 JSRCPATH=.. h; l$ {* U. B1 {9 X6 ^
prefix=/opt/webcam/ffmpeg
% N6 Q1 h+ K/ t L; bexec_prefix=${prefix}
+ s* C/ p9 T' _" ibindir=${exec_prefix}/bin+ p* S3 g7 X% a8 ?
libdir=${exec_prefix}/lib5 v) z; o& U. B" G) o) _& V
includedir=${prefix}/include# r5 e) r4 \4 X8 x
ARCH=ARM
2 F6 g9 \0 Q! R1 E5 ASYS=LINUX! b- f$ O, j6 R1 _ @! d$ b3 d
CC=arm-linux-gcc2 r4 S; V8 ?# _
CFLAGS=-Wshadow -O3 -fno-fast-math -Wall -I. -I$(SRCPATH) -std=gnu99 -fPIC -fomit-frame-pointer -fno-tree-vectorize
% t) C8 S2 g! Z/ e8 E2 D TDEPMM=-MM -g0
- Y# {) o( o! \) {8 A' U wDEPMT=-MT+ F' ^6 N: Z8 ?! J- `
LD=arm-linux-gcc -o
) Y3 W! g! b& _6 _) a; `LDFLAGS= -lm -lpthread4 A& h H( C- q0 y: \
LIBX264=libx264.a
% N* a2 y3 Z4 x- s" VAR=arm-linux-ar rc
N5 S: w0 w6 B" H3 k( Q: I' dRANLIB=arm-linux-ranlib
1 q! x8 a7 T8 {2 n8 u' }STRIP=arm-linux-strip: W) C- t5 T+ o2 X8 C; N
#make) T2 `* b6 m1 g6 }, a$ w
, J. m0 `( c* x( h
#make install0 U {2 F6 F; j, p
6 \- @2 u6 y" V/ ~* j2 tx264编译也不会出现问题的,如果有,把之前安装的pc端的x264全部删掉
$ i' C0 H) s& E. F/ ], D
; }, k$ ^5 Y8 H `5 l4 i1 y. s% M2 Q5 I. W
3、编译ffmpeg# A5 G/ g4 B: _, H# u0 f
/ N# P' a% p8 w8 o- _# V* c
解压ffmpeg-0.10.1.tar.gz, {2 v8 e4 \' N! W" c+ l$ s, W% i! S
6 z9 y/ `# a0 o4 _& D#tar -xzvf ffmpeg-0.10.1.tar.gz
3 m" M$ n+ w; d9 ?1 |* n0 F# ]( \) G* R0 A+ @
#cd ffmpeg-0.10.1
* c. B: ] [ c/ m# ^
& i) m+ W3 m6 A#./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/
, c+ G+ s8 j/ a# s: D8 }% @$ D
8 d: f# D( \5 L+ b( h7 x配置需要注意的是--extra-cflags=-I/opt/webcam/ffmpeg/include --extra-ldflags=-L/opt/webcam/ffmpeg/lib/ 指定x264库的位置5 T) ~( i- t7 u! b8 v
7 q, I3 I) c1 b" [8 E) v. Q0 Y9 i) r
#make
0 Z' ^2 Z% a- D3 L
* u& a! C: w8 D#make install3 Q0 Z, v; A+ e) K
/ O5 x; I t" S, u以上,所有依赖的库就都编译好了,下面编译webcam应用程序
6 M# {9 i. {/ R' g: a
7 b3 b$ g! i9 S. p Y% v6 A' i% K1 M# U' G4 J8 T* Q
所有的源文件不做除了修改udp上传用的ip地址和makefile文件外,不做任何修改,源码存放位置/opt/webcam) h6 P5 Q& B5 ^ j( C1 N
1 u! v1 e* n+ W4 i1、修改server.cpp ip* b+ N: r7 Q1 A7 ~
0 q# _) _' R: M将#define TARGET_IP "192.168.1.220" 后面的ip改成你的pc linux的ip,依旧是客户端webcam_shower所在的pc的ip地址: f& H' x% p7 i2 F" k: y$ R
4 l& O! x! X0 i1 t2、修改shower.cpp中的+ G- V) W! q3 W0 W' n3 A, ~
" v6 A& M" x8 ^ R* J
inet_addr("192.168.1.220"); 将ip修改为pc linux的ip,就是自己的ip,socket绑定端口用
6 W5 Z3 \5 y! n
( }+ Y% q2 }$ R% o, n" v7 x S3、修改makefile,以便交叉编译webcam_server,注意,之前编译zlib x264 ffmpeg都在放在webcam/ffmpeg中了( i( l5 j) \1 L. g; X1 e8 P3 M& X
8 o( V7 @; H* o; Yall: webcam_server* l$ \2 q. x4 i& G0 Z
#webcam_shower
1 W0 e5 n: s9 C) E* _* }! |CC=arm-linux-g++
* F2 u+ f: w1 [4 d! A+ z& o, sLD=arm-linux-ld
5 H* o I) x% vCXXFLAGS= -c -g -O0 -fPIC -I./ffmpeg/include -L./ffmpeg/lib1 T' ^* _4 J8 v% U: n
* `6 A) s9 g# G6 s5 R
OBJS_SERVER= capture.o vcompress.o sender.o server.o# `8 r0 c* A. I# e+ k6 M( l, M; X
OBJS_SHOWER= vshow.o recver.o shower.o3 q- h9 H% Z; S2 }( N. _6 I" M
LIBS_SERVER= -lavcodec -lswscale -lavutil -lx264 -lpthread -lz
0 K# n+ D8 K: V! b$ B3 CLIBS_SHOWER= -lavcodec -lswscale -lavutil
$ _0 |6 _* b0 K6 J: W
: F/ Q8 ~/ u& S.cpp.o:+ W( x7 W+ p* v3 d4 \# u
$(CC) $(CXXFLAGS) $<. l: @$ L' K3 n- z4 h2 h d) }6 K
2 l' A6 y# S1 r2 L( Mwebcam_server: $(OBJS_SERVER)
9 V& x; f4 x0 U2 d3 \ $(CC) -o $@ $^ -L./ffmpeg/lib $(LIBS_SERVER)
7 T# a2 R) O0 ?$ w; T3 A. \$ d9 h; z* T. B0 ^: \3 q- ~
webcam_shower: $(OBJS_SHOWER)) p; M0 r) H& D% W, c2 U
$(CC) -o $@ $^ $(LIBS_SHOWER)
+ H' P. w4 k4 x5 N& [
5 O8 o, M4 |) s4 K/ J# n& o& [clean:; s G* t$ p- @5 O6 z( S
rm -f *.o* O9 j4 j0 q/ n9 D% U w
rm -f webcam_server
* J; Z! [1 K' p rm -f webcam_shower
- o" Y+ m" N9 L+ e r+ Q# [4 e4 b0 T* f0 [( e6 {( s& J+ J3 C0 x$ q
#make
3 X2 R6 ~; r, Z% P) B这一步会出错,报c与c++兼容问题,在include/libavutil/common.h中添加如下,即可 b* {9 @( B1 [0 {5 N0 M( J
$ q- H# x) R" B6 R7 B+ u
#ifndef UINT64_C
$ g; _/ I5 R* C4 |7 L- W6 a$ D& N#define UINT64_C(value)__CONCAT(value,ULL)" z# R0 N6 h4 \; d
#endif1 H; j& B9 y& G8 j8 v
O b) i3 U4 J) A8 z" |! S) T! i
& T1 A$ d5 n `" e6 {1 X最后就得到了编译好的web_server了,将web_server复制到mini2440中,并且将之前编译的第三方编解码库/lib下的所有.so文件复制到mini2440的 /usr/lib中
: |, L' G- {+ F$ H% _+ F& e
* y3 `0 L6 m7 G6 B插上usb摄像头,webcam_server就可以再mini2440中运行了4 p$ c8 A0 y0 n; s) o Y' I
+ [5 l; g9 K6 _6 U w# T
4 C8 ?7 D/ U; K; S' Z$ m2 H; y最后是编译pc端的webcam_shower,这个很简单,按顺序从头编译就好了 |
|