EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1. FFmpeg的安装 FFmpeg是用来记录、转换数字音频、视频的开源软件,它支持文件和网络流操作。它支持以函数库的方式使用,所以有很多软件都依赖它,比如VLC、暴风影音、腾讯会议等。它的命令行程序也非常强大,各种命令行选项学起来虽然困难,但是几乎能够满足日常对音视频的各种处理需求。今天我们就通过飞凌嵌入式OKA40i-C开发板保定飞凌嵌入式技术有限公司来介绍它的命令行工作方式。
: V, y2 ^, v* j1 a ^FFmpeg提供了全部源代码,所以在网上可以找到很多教程是关于交叉编译ARM版本的。我们测试的版本使用的是FFmpeg-release-armel-static.tar.xz。解压缩以后拷贝到飞凌嵌入式OKA40i-C开发板上并设置好权限就可以使用了。
4 L2 ^6 E6 e" ]1 m0 }8 {4 v2. USB摄像头测试 OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用 v4l2-ctl --list-devices+ o, i0 M8 d2 }' c2 d' _7 e
可以看到/dev/video0就是我们的USB摄像头,如下图。 ![]()
使用下面的命令可以看到该摄像头的全部参数:
& k4 N$ R5 n! W" N* T/ ?' x v4l2-ctl -d /dev/video0 --all- & g$ y5 `$ M( \9 b/ M) O0 ]% @; ?
$ E. ^& n6 y- r0 B) H5 E
' m8 V! [5 T% }8 ?5 b% c$ s4 E
3 H0 b4 [+ z/ ^* g" { - % C! q9 b9 k) K) h6 l }% x
8 t5 ~' {* j3 p$ v& z
Driver Info (not using libv4l2):; u+ `3 O1 F! s
/ `: ~0 ? A! _5 P) \ ?
1 N8 K8 P+ b5 ]8 m: @% e+ S% _
Driver name : uvcvideo
$ f/ u' w, d: G7 p
& r9 T$ g- Q+ G' m3 a- " J2 f9 W1 s \8 p0 N
8 |# l* X+ h9 p/ n Card type : USB2.0 PC CAMERA5 Q! E' [) X. I4 n I
6 `5 a$ m# ]; }0 h
- 9 J7 _- [# ]1 Y
|' ], u& U) I1 B- h, n5 K
Bus info : usb-sunxi-ehci-1
3 X: {! u2 {7 M8 f
! ^3 b7 J* s5 v- v5 X: K5 v
$ e6 S& ^ ?& ]2 X G2 v+ b* a0 |0 m) K$ I8 a% t
Driver version : 3.10.65 O# |0 M% D. U( k! f5 `0 _- ~
; E7 E; P4 P' Z# z. h# q
- & d* M" x6 Y2 x1 X' C3 E3 z. h
, u- G) |5 d5 g
Capabilities : 0x04000001
2 R& K. \) {7 m1 a" W2 i! o2 E. s3 ]
$ @# r7 O; _& ^7 ?0 T. w2 \
5 p$ @0 ]' R3 \9 Y& K X# w
/ n- u5 [8 F9 W: d; C3 u Video Capture, j# N, w- ?( q
" C% b. _; a+ i+ D* S6 i- ( A9 @3 R/ L$ l7 x
+ H. x5 I+ U' s6 \% `9 R% Z' Q" j
Streaming
- d m: s* x2 ~/ E3 J
8 [8 J( P! t v3 u4 q/ A
3 b6 _9 n; H- X
* q) B F- o' m8 zVideo input : 0 (Camera 1: ok)
1 }& y* T( N' S* k
. n# o9 C3 Y( r1 N/ Z6 C& U" Z; J
% d: T- G7 q9 w6 s. S$ Q
7 ~! h: P2 n( r8 wFormat Video Capture: 2 l. P" B# T8 d- v2 z( X2 y3 P5 p5 E
. T! M8 L( r+ {/ W8 a6 h# x$ r8 e
3 O* z6 a: l% \4 J" G& f
4 Q4 F" P8 i. d9 P2 R `* H% Z Width/Height : 640/4803 _) e* @$ ]' j3 O# v- s
5 ]8 m+ }3 n' C$ B6 j. Q, s1 u
4 p* C# V7 B- a0 ?5 [8 o3 u( J7 |7 ]+ R2 F) H8 U9 R
Pixel Format : 'YUYV'5 A6 l$ F6 \0 c* R
4 P, M- |9 J6 g2 n- W; M8 w; O- 4 w. w j- T, F& e* B' b" _
9 |7 P q' Y9 T s) J' S0 J9 F
Field : None
) x# O* n x1 l3 N
5 [# T( l \/ u+ h9 l) A$ c' `
* c0 H1 K8 b, `# t
8 e* z/ G$ J# k6 s- }) ]8 z Bytes per Line : 1280, @8 y9 K; s9 k% T2 e) t0 {
3 \' s) H& P0 N, A- 7 o7 H6 F8 g" l& W+ C0 ` y
* F* J4 @: H# o" F' S Size Image : 614400
% ^2 g: i% k1 W& R- s1 {1 y. u% y
4 r* x5 w; P. j) G
2 E% Q2 O4 m4 u2 u# R6 }4 @) `: f3 Y
! u. m: A2 L* b% N3 C% ] Colorspace : Default
' ?1 ~$ m" h" Z, e1 w! y- I
7 a" r& ^5 m7 H# N7 f7 H8 B
! y/ ~" t0 s/ G* Y) ?( h4 n/ u: G! k( c7 z! w9 v' z3 W
Transfer Function : Default
. g4 o- v2 y; h" n0 \. W' Q( v! g* X9 f1 s' C- e8 _ E2 t4 L
7 F a$ r* C; Q5 q l8 |9 O* Y7 V9 ?+ S
YCbCr Encoding : Default
s8 G% x* U+ R, r6 U! \7 m& T
9 G6 h- |3 K7 y9 S$ D- . {9 W6 q2 a$ K1 h
& L9 q* @. }. Z' q1 r& n
Quantization : Default
: f1 X3 i* \- v9 _
% o* J0 I3 }$ i ~
+ [6 T' ~$ Z( C8 j2 f# h1 T' N) q! L! T/ n' P9 K
Crop Capability Video Capture:
+ q7 r+ C i4 \5 d8 |1 J
3 {: j# | M$ s2 p- 8 O1 J4 B3 Y/ F& _0 P0 R
0 K8 U! m& E& w: l3 Q2 E! E4 u Bounds : Left 0, Top 0, Width 640, Height 480
1 `5 u$ o x. `4 |9 I& f: _. v! ^9 z
- 3 ^3 ?$ T* Q; m/ R
- D' k) t3 r/ G+ C Default : Left 0, Top 0, Width 640, Height 480 / q' l& O- j8 s ]. r% I' ~
8 \8 F! C# k( ]6 \/ J3 Z
8 t- ?3 M( n3 Q: C' d" p8 x2 B
4 B A+ W1 l0 E4 d. B. F! V6 m; I Pixel Aspect: 1/18 s' r8 N b' f% o
! g) U4 _& X5 l$ P& y. F
9 l; s7 D& G6 T! ]& ^
% q2 \3 w( ^8 F/ c8 }" DStreaming Parameters VideoCapture: {8 \" n' e* u$ B& \: e* h
8 q% L7 b$ B" L5 t
! m% m/ ~& N0 x& Y# Q3 ]+ I0 I! `1 ^( B+ |* o4 n [) j4 ~( J/ d" b
Capabilities : timepeRFrame + j' C! j- f% s) G" S3 E$ `& r3 h
- n% e3 Z# c& J/ U* ]1 K8 j
- m O ]) _$ |. p) q
2 ~$ h; t' q4 v+ S+ b3 l+ D# m: p
Frames per second: 30.000 (30/1) ! d. u0 }3 u7 X6 z8 q: m
* }2 h5 d, ]) |, N
! F \' a+ X; U/ I5 r* F
% u2 G: @7 a/ o Read buffers : 0 9 h1 v& l: x% B/ r" K5 _1 ^5 {* u
P6 X& O, {# u
* ^) L/ X5 w" \1 V
+ i0 \2 M# v: R8 k* S8 _ brightness (int) : min=0 max=255 step=1 default=128value=128 8 M# S1 I% n9 V, ~* _7 K# o9 V& c
1 z5 r' M6 A, E/ L
) t6 r# R+ G. `, D' M1 Y
z, v8 Q0 H; N/ ^' Y( x& ` contrast (int) : min=0 max=255 step=1 default=135value=135
* Y: k4 u% c& ~. D5 F, x6 |) `
2 Z& y" [) \$ l
: K6 L9 K6 o5 P, l3 i
+ w1 a: B, }1 B3 W! v saturation (int) : min=0 max=255 step=1 default=75 value=75
; v }- H+ Q4 `2 E f2 F0 h$ j7 [1 d5 E
$ W) t# b: N: i" u. h% a: z% _7 Y' a7 R6 [! N
hue (int) : min=-127 max=127 step=1 default=0 value=0 & C, K. d, l! b0 Q! l% a
: {. {, \! l* g) b% N
' R$ h7 i _# I, ^
( l" a* B+ x2 u- T6 b0 T9 Z gamma (int) : min=1 max=8 step=1 default=4 value=4 7 B5 x, c* M2 a; E
2 }6 m5 G6 q* ~- k( ~
( G" i( k x c' ?5 |( b# t" w( t7 _4 K2 S, C9 B" D5 D2 W/ t& K
power_line_frequency (menu) : min=0 max=2 default=1 value=1 * V3 l; N* z, j
5 ` n5 I$ q+ Z6 r- ! A0 c$ `. ~( D" ?
9 M/ u- U8 F9 psharpness (int) : min=0 max=15 step=1 default=5 value=5
5 n7 X( j( w6 _3 g0 R: |& s& e8 k: Q1 | ~9 U
- ! Y" G( b8 R5 r n& R; v+ H, {4 V% Q
2 `3 R- [* M9 l7 H; Y0 Q3 |1 t
backlight_compensation (int) : min=1 max=5 step=1 default=1 value=1
8 d5 h9 K9 ]( C5 ^0 x- i% F
: g7 t `/ N! q% n$ W; W- w5 K1 Q @
( `+ N3 X/ U1 B! L* v/ ^$ k
我们使用了两种型号的USB摄像头,按照手册说明使用内置的uvccamera程序进行测试,不过都没有成功,得到的错误信息如下图所示。 ![]()
![]()
我们使用FFmpeg可以抓取视频,命令行如下: ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv
/ u5 v8 N3 P& O0 y1 W4 m使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下: ffplay -s 640x480 -pix_fmt yuyv422 out.yuv! Q7 H0 y4 c; i- ~+ L- \! n7 X
上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行: ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 out3.mp4-timestamps bs% k, C+ j, r( G0 x b
其中的-r 25表示每秒采样25帧,这个参数必须有,否则FFmpeg可能会不断地采集并压缩同一视频帧。-r参数超过30没有什么意义,因为USB摄像头的最大能力就是30fps。 . m1 Z3 o R" ?0 w' S/ t
飞凌嵌入式OKA40i-C开发板可以对于1080P的视频压缩达到45fps,所以对USB摄像头的视频压缩应该没有什么压力。
; m) ]& a8 F' O3. FFmpeg性能测试 FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下: ffmpeg-benchmark -i translate.mp4 -f null –) Q8 B4 H8 [" e3 j2 L* Q
得到的测试数据如下:
/ k( k2 Z- i! J" d. \
9 B5 Y- q+ |$ c4 ~video:
: Z1 i C4 {/ V# q8 |3 h8 r k: ?. u$ q9 f% d' g/ w) h
2 @: W+ y$ Q" H, e2 Z
7 U7 {/ q' O' D7 c148kB0 z# ?+ z1 z7 _# p" `" A
. o! N+ L3 G( `- [
E w3 C! V; J9 ], K, C8 \. E) `/ ^
" j) g( k/ g1 ?# ?. D9 K0 kaudio:/ u% ?7 ~6 `! Z$ v
' F4 S, p' K) Z/ m, @0 C' {( a6 u" m- : }" e V5 q: h7 P1 x
+ T3 G3 o) d( o9 |) A9 }% z3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing' f8 o, X3 G1 [
6 `9 U+ t% N. m. J( F) D5 k6 V$ }
- 1 `& X/ V1 ~9 C# w" E/ F
0 i4 G1 N7 O* b m) R/ C: u
overhead:
3 b8 R1 C0 t6 ]9 ^. R
6 }& ]( O4 w5 g- F ?; p
$ o: c& M0 d8 P2 O* X6 L
; g8 r' p2 d7 w$ b# N1 Vunknown3 p* n$ P- n" T- E+ s* i
1 ]5 c5 r5 i; C/ m, B
- _. D2 P6 n- F5 w5 Z. M
, ]7 z, u% y j7 X# {% x7 d' S4 O% Sbench:' ?6 k* S0 ^! n* X X0 C5 g
$ @8 A p$ N! s* X" Q6 }- B- 9 B+ F4 E% j+ M9 r( V
7 z r/ H( G( k k
utime=2.820s stime=0.110s rtime=0.956s6 q) j2 m$ o+ N+ l% y* R2 W
: k1 s( C7 V2 \( w5 f- G - ; e+ n/ ?* {' M4 |% w+ V( R: S" N$ c. h
' J o' C7 F, ]bench:
2 i. O. Y! `* J, G+ p+ O$ V! ^' I& {- @
3 P/ T( Q9 w! O) J
9 v, `# f* x2 @/ o: Z( s. j$ Emaxrss=14208kB
& v- V0 b$ w3 j& v- S& v+ { t. d: a5 |
l+ s* P" z4 v! e. g' e! }$ W0 P
/ W, y0 {3 `& v由于我手上暂时没有其他的开发板可以对比,于是就通过我用了5年的i7-6500笔记本测试了一下,测试结果如下: - 3 [# N* k; x8 L* e7 d" c' h, m: v
% h* q/ C% ?( B0 H" mvideo:
! t3 u k2 \, i) U
+ @( H: F& J7 |9 E0 X* N$ b
, V7 t* c6 \: j! Z+ S4 n1 D, h) d% U$ R1 v
241kB
2 }% I* V' I: H w" I; I2 P7 Y0 u1 p; K8 @( ^
- 8 s. @/ M8 W; j- ^
5 ]" r7 E5 u! D! i
audio:
. _, j/ q& m% g/ [5 ?" S' s( L) U; O+ E" d4 H: w; h( ?! c: q
/ G" w3 j5 X, w* \: N' r
! ]" c, D7 E1 H6 H; x# s3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing
/ _% ^, Z! A3 D, s( x( T; y9 I( j9 p3 ^7 z9 m3 ?2 e+ A( E+ C4 S2 [3 `
; d7 x. i6 q: g" K* y: A* P u6 r* P/ f; `) A( C. O0 e8 ], Y! G4 [
overhead:
4 @7 H7 y* ` A( } \1 {/ f. ?" E; B
- ( a9 J% P7 R6 k2 W
% Q- n t) i3 j V, F9 eunknown
9 @7 ]' J( U6 H. P4 S+ X/ Y
; Y5 Y& _# o" `% l2 R1 p8 t - # \9 O( E1 |' U2 T1 _3 I9 T
' R( R& E/ L8 ~3 A
bench:
9 W; H! ]1 c7 w4 |% N" @; ?- w: d) x. `& a% l" z$ t
- 3 E4 w/ ]! P: w; s
# p- b- V3 W* `8 y
utime=0.391s stime=0.000s rtime=0.228s1 g" T) ?( D H
$ w, b+ V$ @" J5 R+ q e. }
0 z8 S' B# Q$ W, R8 |* @: m; z9 s1 M+ N8 l: B
bench:& H6 ~9 B- e' o
% H& G- `& I0 m7 l7 A" ~9 O- . D ? J0 L% s9 Z0 K& V
" }* ?/ {0 G. t/ k
maxrss=20316kB
, U# ~# V) e- i" C' T
% L2 R @5 Q' L6 g5 M0 u
9 n/ h; [8 {$ {% b, ^$ L4 z- L
8 ~0 l8 j* n! d1 S4. FFmpeg产生实时视频流 FFmpeg可以支持实时视频流的发送和接收,从而可以把OKA40i-C开发板上的视频实时发送到PC上,由PC上的软件实时接收并显示。我们可以使用下面的命令将OKA40i-C开发板上的一个MP4转换为RTP码流发送的PC上: ffmpeg -re -i test.mp4 -an -c copy -f rtp rtp://192.168.0.105:1234
) n- e' i( f4 c" j4 e# O3 G$ u使用Wireshark可以看到在PC机的1234端口收到大量来自OKA40i-C开发板的H.264视频流。 ![]() 0 z- r' `: f) c$ e. s* @7 K: w
; n; x1 ?/ c$ ~; U) B* C
如果想在PC上显示视频流,需要建立一个SDP文件,它描述视频流中的端口和编码信息。
0 e2 ], W0 z. Y4 \2 C3 ~SDP是来自SIP标准中定义,目前VLC、Apple QuickTime和ffplay等很多软件都可以打开SDP文件,并按照SDP中的描述显示视频流。SDP文件并不需要手工编写,在ffmpeg运行时它会显示命令行所对应的SDP定义,如下图所示。 ![]()
也可以用重定向将输出写入一个SDP文件,如: ffmpeg -re -i test.mp4 -an -c copy -f rtp rtp://192.168.0.105:1234 > rtp.sdp
2 u) s' V t$ S Y- A* \, h9 `下面就是使用VLC显示的接收到的视频流。 ![]()
( i# H" Z2 D V( H8 c4 V2 [* b- ]8 M+ {# X+ t- ]
5. FFmpeg转发USB摄像头的视频流 前面演示了将MP4文件转换为视频流,我们也可以将USB摄像头采集的内容实时转发到PC上,使用下面的命令行即可。 ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 -f rtprtp://192.168.0.105:1234 > usb.sdp! S& `" f. S2 i- [" [9 j
|