EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1. FFmpeg的安装 FFmpeg是用来记录、转换数字音频、视频的开源软件,它支持文件和网络流操作。它支持以函数库的方式使用,所以有很多软件都依赖它,比如VLC、暴风影音、腾讯会议等。它的命令行程序也非常强大,各种命令行选项学起来虽然困难,但是几乎能够满足日常对音视频的各种处理需求。今天我们就通过飞凌嵌入式OKA40i-C开发板保定飞凌嵌入式技术有限公司来介绍它的命令行工作方式。
8 y/ _# k& D$ t( w8 V9 k9 FFFmpeg提供了全部源代码,所以在网上可以找到很多教程是关于交叉编译ARM版本的。我们测试的版本使用的是FFmpeg-release-armel-static.tar.xz。解压缩以后拷贝到飞凌嵌入式OKA40i-C开发板上并设置好权限就可以使用了。 * } s5 V& w/ Q( ]' H# Y1 e' F
2. USB摄像头测试 OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用 - . b0 d$ A/ r C) p+ l; G& P9 G. g, w
v4l2-ctl --list-devices
, J0 B8 x& J% Q; p7 i可以看到/dev/video0就是我们的USB摄像头,如下图。 ![]()
使用下面的命令可以看到该摄像头的全部参数:
, L/ ~2 f4 `: L: G( D5 X% G' u. y v4l2-ctl -d /dev/video0 --all
+ R0 Z! G& T% [: X
% T& ]+ m8 f' a2 ?9 S. Z3 h. V* J0 {$ l; V# X7 t9 C1 ^( `
* n* J( E- ?, f/ {. c- \- L& q, i+ J* y
1 _/ }0 H& R7 m! V
4 r1 V# Q" `, w" }; oDriver Info (not using libv4l2): M& E) G* q6 x! E! g
) T; G4 o4 E1 o; z) o" i- / i; @6 e4 G* }# I5 }
& a5 h4 |8 a; O9 B" Z7 B1 B/ j
Driver name : uvcvideo
( s. B/ T4 S0 A7 q8 `* V: V# d5 ?5 w/ A. C O" \& v' W3 ?+ f+ V/ y
9 x3 S. \. S/ G# J4 X) @" m% W6 M9 X8 o- l- L( k9 L4 q- G
Card type : USB2.0 PC CAMERA
2 f3 z% E" S8 D' B3 i
/ d/ S$ L3 f) M- 7 ^/ ]+ ]. r& U& i8 a# m3 ^0 x
L. n! T! O4 Y$ c( i
Bus info : usb-sunxi-ehci-1! x! z W1 _2 o( M; O9 j
# Z$ {2 }* \ I
- * w% T3 C% O' |& |+ o4 J2 ^
. |7 w- G2 E M. e" Y( M9 b Driver version : 3.10.654 I, X- x( L F% O0 g& g. @
9 t0 d4 O% G0 f; i3 a! \
- 7 Q k4 |# n. v7 d5 i; H
& m' W$ U# L0 Q7 F9 J! T Capabilities : 0x04000001/ t4 _) l; i+ F
2 h8 s- z! l; s" c# }
- 7 [! U1 v8 {5 N6 @
. @1 m% f7 @, v( ?. X Video Capture
$ ~# w4 X7 k- @
( r q, A/ G( j1 O8 \' ]+ ?
% u# l+ Y9 M2 ^( o+ t H
. A7 N% y& d9 y" o Streaming$ ]' _- J0 G" c+ V, W6 v! m* l
% w Q7 R* @& J' m
# ]! ~9 _+ k0 U9 y+ L& z! O3 R) b8 O+ a6 t# ^
Video input : 0 (Camera 1: ok)1 x1 T; m$ g& Z' s
. M4 D/ g o( b8 s/ _- 8 j7 j: C9 P8 C0 [# Z! r: [
" S' e4 v, Y7 yFormat Video Capture:
) y' U$ R& o& [: x' _2 R0 s; c6 {1 N2 ]( c7 k/ g o. v( E M
- " }' N9 d. a E' a2 I e$ l. v
8 G; i7 Z8 d+ E1 J# Y3 d
Width/Height : 640/480
( D, Q4 B, [2 {2 ~! m
; j* y1 x, {) m9 z6 a
1 H+ J" N+ J" n2 U B7 k0 r, ^$ _) _
Pixel Format : 'YUYV'
& [) f* w- h6 l& r5 b& K# X' B( u1 o7 i4 @& R* R8 |1 Y0 W
- : @. {' U3 a( Y9 I W
o9 \8 J0 r) y- B Field : None- `$ h0 Y) p1 K2 q1 n) X
8 C: q/ U9 e2 {8 q6 E' r - ; G+ U- T% @! I3 ^
1 Q! }) Z' R) G, f, M
Bytes per Line : 1280
1 B0 d D) H9 H
2 m+ f! L* h! Y' N - a& a0 S, d- A1 D7 E
& n) {- E2 N+ A2 ]6 ^6 a8 o Size Image : 614400
- M4 q! ^- J, L$ Q" l0 }
! J0 f3 C1 L; l+ J0 W
: x& v9 W" Y' D7 [- X
% J$ z, c. v, F# m; j% n Colorspace : Default& B2 p; M1 U4 G- ?! K
7 U* D2 i$ j0 j7 r; u, v- # ~! B0 m/ Y: ]' R4 O
% t0 s& I1 H; i: O
Transfer Function : Default* L0 {1 l8 w) a- R
: @ D$ d5 ~! M
- # b6 r. a8 W3 I; h3 U* ~
& y* B, ^6 R2 G) ~; @; r YCbCr Encoding : Default
; F& K% A/ |9 D, `+ q2 a
! r/ J2 Y, ]/ J. \* i
+ H( _2 V5 T% h$ {3 f. w) u
. Q( B) B5 q5 R Quantization : Default6 U% B" {" ?& V) g4 z
4 [3 S* o* M: k& A" z
- / D6 D: p' Z7 A3 }* M3 c' K
; X! Y3 }" r+ ~! ?
Crop Capability Video Capture:2 H; q# x) P6 d' W* L: u2 [
4 d5 O* ?7 {, d4 e) {) }6 X5 O
- 5 ^* ?9 y& v8 w7 Z' O
' ?5 A% A+ K/ F, w4 F) |
Bounds : Left 0, Top 0, Width 640, Height 480% f! K( x. J( P0 Y
# }2 o( e9 u# c2 p
5 e, M& V" z5 F( |
9 i W0 c( p& P) S Default : Left 0, Top 0, Width 640, Height 480 3 O/ ^9 `' r7 s q5 q' f
! Y9 F" _5 g8 M8 s
! y, C' ^5 `! p7 U3 Z' I1 V, k/ ~5 }. L! p
Pixel Aspect: 1/1+ H" k/ l* a- a
) _4 p# z# K1 p, u6 A
x, v; A% @/ E0 K; F" D |! }" f# }& e' T6 q- p. S5 h
Streaming Parameters VideoCapture:" w; d, T4 `1 Z, ]5 l
7 ~/ }5 x- K1 v2 \" u- + V4 H5 k" p/ E3 |
% C6 s) q$ l$ U8 T7 L% z& ^: D Capabilities : timepeRFrame
3 r4 ~4 \ Y& |* P' S
7 v: T" K; H& u$ N: A - " W3 ]! B; b1 x9 d' T! S2 l
. _7 Y5 Y& g* W& W Frames per second: 30.000 (30/1) 9 h9 F' o8 `$ n5 M( F
2 c! n& l! x( Y. Y, ~6 S6 p
' C* j6 w$ {+ B8 @; G6 q- F
7 T( ?5 x- U0 n Read buffers : 0 ! s. ? i3 O' e _) o
# w2 K: r* w& I3 t- N/ S
- : w d% T! ]8 M+ S8 o) n4 K
& @2 f. W% ~7 s E brightness (int) : min=0 max=255 step=1 default=128value=128 ' Y7 b$ U7 @8 O* }) o6 ?- `
. j0 e+ j" F% @# V0 w2 |% u8 h
- C& A" k' I! B: A. @
4 A7 b/ ~/ q5 W- t$ U- ?% |9 D. _+ ] contrast (int) : min=0 max=255 step=1 default=135value=135
; y4 T- D' ]; _/ A V4 N3 T1 z+ y. L
0 ]1 a; Y/ p* N4 |% `$ z- m; ^% I7 [7 h. K$ T. `
saturation (int) : min=0 max=255 step=1 default=75 value=75 + @6 b7 o- ~% u5 _) q/ f+ [
; u3 I# \/ \8 ?7 }/ e
1 L, a3 O0 x- x9 d% }( r0 ]3 i
8 ]) K% |" R9 O0 f* i hue (int) : min=-127 max=127 step=1 default=0 value=0
& s; w) S' O' V6 N0 g* v- K8 @
, O2 F: E4 O' f: b4 P. }" z. \- $ ], B9 R" t* D# [( W3 v* n2 i
; U0 k5 H/ B+ N: _" p) } gamma (int) : min=1 max=8 step=1 default=4 value=4
/ X- z) I% V# u& J+ C d7 b! z1 v/ J/ X
- 0 X1 y0 }% o: e( J, f
+ Z9 A; Z4 m1 j& P
power_line_frequency (menu) : min=0 max=2 default=1 value=1 5 a$ m: u0 d" S# d9 g0 n7 R. o
# R- m0 f2 E5 z
# u9 m$ k% q$ X: l$ u- w, T: X8 A* m6 R7 r) k3 [
sharpness (int) : min=0 max=15 step=1 default=5 value=5
& |0 N7 c* |" a- B( X2 w2 q* l; E" K0 s1 r; t
3 d5 A5 ~6 K& o( v* M7 v7 ^: E& v0 M5 h2 P; R2 u
backlight_compensation (int) : min=1 max=5 step=1 default=1 value=1
& ~+ A) }. l% C1 V# S( X8 W C
1 Y* m4 U, R! E2 P* E& F5 Y$ G# [, S$ H# _
![]()
8 D- c. V0 i% l9 A8 c我们使用了两种型号的USB摄像头,按照手册说明使用内置的uvccamera程序进行测试,不过都没有成功,得到的错误信息如下图所示。 ![]()
![]()
我们使用FFmpeg可以抓取视频,命令行如下: ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv
J. k8 s& }' R" Z使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下: ffplay -s 640x480 -pix_fmt yuyv422 out.yuv3 N/ Z; X. q) K# b* G: ]6 e
上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行: ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 out3.mp4-timestamps bs
; s s" @2 X" c! e1 b6 k其中的-r 25表示每秒采样25帧,这个参数必须有,否则FFmpeg可能会不断地采集并压缩同一视频帧。-r参数超过30没有什么意义,因为USB摄像头的最大能力就是30fps。
0 |. p& \. {1 K( m飞凌嵌入式OKA40i-C开发板可以对于1080P的视频压缩达到45fps,所以对USB摄像头的视频压缩应该没有什么压力。 - v" Q/ e X `+ j2 \
3. FFmpeg性能测试 FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下: ffmpeg-benchmark -i translate.mp4 -f null –4 D+ t* o# y% D9 o
得到的测试数据如下: - ( E4 d: O! I# b9 ^' a, S
4 a* u1 b2 Z- J* L; `video:( ]. }7 n$ k x# `
3 u' T: m' i, V4 b* Z
- + z+ N1 i8 D3 C0 a1 z
! k! z) J3 ~4 L# |148kB1 B3 g7 _! E6 j0 n! [
3 X! V7 T- ^( a9 |4 ^1 d$ \
- 7 e- Z# x1 G/ {' H& \& |
; Q' i& C+ J/ }$ R; ^8 M4 ?
audio:
4 ~$ C. D0 K% Y6 W% W6 Q) O' v; G3 V* V3 s7 [
- % H4 I0 `) `5 y
( b4 H% d7 @6 V7 L/ w" |3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing( w7 K9 I" w0 Z+ K
- d, H( G' ^) u/ l, o, g
- 1 m. q% w: \# l
" d5 K6 F, S! v. i5 a/ o9 voverhead:
3 j* ?+ u! }3 Y/ M+ I, f* F2 k! w8 _; M: O6 A/ w. _1 D
$ [# N7 R/ `+ J
+ Q9 n% c& r' k1 @% cunknown: U4 G; q8 m! B* a5 Q3 a
}- y# G& `* V, r
- & a+ w! x) k$ `4 v0 e, v4 E8 V
5 D7 _) _6 g5 Pbench:
/ _! |( o+ N( V- r- F; [. f4 \
, [5 o0 ?: L* e: c# R# o - 7 ]: X0 x0 J; @! q2 d5 `/ s& D
' O, ]% `+ b0 B# |, t
utime=2.820s stime=0.110s rtime=0.956s
& [$ h; E6 z3 J
6 y- Y; T H: _7 k- J$ q2 ?, _' r
# y( l/ g0 b: s! Q, n$ O1 u2 C7 w1 _% d' j1 n0 w5 z
bench:
4 G) ?( S3 u% ~
+ I* b! U1 v5 L x4 `: G
, S3 [! [2 Q# f+ D. x8 ^% n/ ]+ p
maxrss=14208kB7 N) ]: P; b8 J3 P
+ P: |( y; z6 v: e
) X% K! ~! i/ T1 f
, V* }7 ~* J* l. ~5 X9 \9 m由于我手上暂时没有其他的开发板可以对比,于是就通过我用了5年的i7-6500笔记本测试了一下,测试结果如下: - 4 g& ]" [& w- Q1 I
) q; a* B( K1 N6 e, O1 e+ X
video:
4 e4 _: V# u7 ^9 g/ a+ z& Y' C |
: h7 ^/ }7 A$ D1 ^ - * m2 ?! h, h7 a( e
+ r7 a @! J; A
241kB& j; J$ \2 c1 q" D7 f
2 w) S! W$ f8 a$ {" w' J
- 7 o6 ^) g# I6 t' V' g+ f# \7 W: b
7 ~9 a; s ]+ T& E9 V
audio:
5 m) l/ K) y, r+ C4 Y4 j+ s. _4 }8 G G
& C9 j h6 v: _- G$ k* n# J) a \' h6 n. E# Q6 E" P- i% e2 L. I
3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing8 c; z. n: o# n3 u$ n/ ]3 E
' M& ]* u/ r/ v1 @6 y3 n- 2 U8 h1 m5 y! c# h6 o: K: Y6 y ?
: N( k, {- V# `& @+ V/ e5 X! S
overhead:
1 K) Q K/ X! g
0 W) I# ]. {- @ - % A$ ~( F% U7 k2 o
' B% Q! W) ~% p( i: D) a
unknown; U' k u2 D/ w* j
; N, t$ a# N$ A4 V% }- X
- 9 f* Y' i8 G4 {. P7 w, {
# c+ S, T5 R9 U$ ~4 F' T2 Abench:
5 }/ f4 w' u# d( l& W
; Q5 H; a' V7 V; l& U3 O - + R! P& O( \8 k9 x
: }0 ^. O [# I% C+ o8 _( `utime=0.391s stime=0.000s rtime=0.228s
9 @ [( ]# U4 |" L ^$ F
, |/ b& p. O+ ~# C
$ i6 p; z4 _. o2 X( Q$ @' D9 x& q6 h7 L: i
bench:' h" u9 F: ~1 L! T/ q) Y- v2 e, `
( n7 F1 `) I6 ]
6 b6 v9 X1 K; }% O+ x2 l7 c
/ [$ L" `' L8 Q! ^) F& ^maxrss=20316kB' r1 i! D9 F8 y+ H2 C% o
! }- v9 v& P/ _7 c" ]8 p
7 l) v% k' [! u8 X8 o
0 {4 L& P" y# f5 O, Z. A. L; w; ^
4. 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:12341 K, U, k6 [: h L' P
使用Wireshark可以看到在PC机的1234端口收到大量来自OKA40i-C开发板的H.264视频流。 ![]() 2 P* c" T% I/ ^, y4 M- t
6 j/ U- E2 ?) C; O& v/ o5 L
如果想在PC上显示视频流,需要建立一个SDP文件,它描述视频流中的端口和编码信息。
( @( w, |0 H. I/ m( cSDP是来自SIP标准中定义,目前VLC、Apple QuickTime和ffplay等很多软件都可以打开SDP文件,并按照SDP中的描述显示视频流。SDP文件并不需要手工编写,在ffmpeg运行时它会显示命令行所对应的SDP定义,如下图所示。 ![]()
也可以用重定向将输出写入一个SDP文件,如: - ' ^% i7 J. Z, K( B' {% I1 M
ffmpeg -re -i test.mp4 -an -c copy -f rtp rtp://192.168.0.105:1234 > rtp.sdp7 b; ]5 O. S" _( ^# j4 n" a* E
下面就是使用VLC显示的接收到的视频流。 ![]()
( i$ E+ p' n! g. H' W6 a
: O: g5 j( f. A1 c+ _) [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' X5 E7 a) E, F- {& _
|