EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1. FFmpeg的安装 FFmpeg是用来记录、转换数字音频、视频的开源软件,它支持文件和网络流操作。它支持以函数库的方式使用,所以有很多软件都依赖它,比如VLC、暴风影音、腾讯会议等。它的命令行程序也非常强大,各种命令行选项学起来虽然困难,但是几乎能够满足日常对音视频的各种处理需求。今天我们就通过飞凌嵌入式OKA40i-C开发板保定飞凌嵌入式技术有限公司来介绍它的命令行工作方式。
$ L! j4 p4 Y s( w1 kFFmpeg提供了全部源代码,所以在网上可以找到很多教程是关于交叉编译ARM版本的。我们测试的版本使用的是FFmpeg-release-armel-static.tar.xz。解压缩以后拷贝到飞凌嵌入式OKA40i-C开发板上并设置好权限就可以使用了。
4 f( ]+ u* ]! R% ?2. USB摄像头测试 OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用 v4l2-ctl --list-devices9 ]' A& l3 T# F+ m
可以看到/dev/video0就是我们的USB摄像头,如下图。 ![]()
使用下面的命令可以看到该摄像头的全部参数: v4l2-ctl -d /dev/video0 --all- 6 l! t/ F ]0 j4 R% G" ^* i3 }
- ) L5 C9 p) G* T. m$ x
) l4 o/ [& A/ c* p9 t
$ z2 T7 x$ l4 q( l# x
O) Q$ z: b$ p4 M# c& o
- `, m4 b$ ^2 A, x! l) e+ ~8 y" O! e$ w0 K
Driver Info (not using libv4l2):
# p% Z% \6 T4 L4 n
% K5 `$ e: O! R! D+ D) i- ( q# v T2 s. x; n
7 D* E$ b9 o: Y. C6 N R Driver name : uvcvideo
\( ^" f3 G. A$ H0 Z' e/ a
# H B6 [: E. ?% R, O
+ l$ g S& l0 T, p2 Q8 c& I3 Y8 r3 x0 S8 ~0 ]
Card type : USB2.0 PC CAMERA
) b/ O2 e6 J9 i
- x) q, M3 u& s! @; v' c- 2 ~" o% [, }6 X$ e$ C
; a2 }8 t1 }- u7 I
Bus info : usb-sunxi-ehci-13 h7 {4 g5 W9 d
0 ?0 m/ q" }7 ^5 A2 h7 W
- . {6 z- E2 }4 S# b9 l
( ^& P' t+ k" K
Driver version : 3.10.65
/ g- v' O; O4 E2 V5 r c, Y3 I* ?. W: a: A
' k- r7 \. D( [! U% ~6 R3 d( K0 Z4 g. `
Capabilities : 0x04000001+ B2 `: L# ?! U. f/ g' ^2 T0 p9 `3 t0 {
1 ]! q3 e0 s* N$ |" l- ]! L& X
- - a% [6 T0 W' [
Q/ u! P4 a# p" [: E: W Video Capture7 H2 @( ^+ e& E0 ~1 {9 c# j7 \: X
. X6 `8 m; H" ~% H
4 U( L3 m3 o0 _9 x$ t! |* o( Q" q @# s4 h% A
Streaming
, X+ d: f* I' b4 V4 o* \* _( `( C" y A
- + @4 G$ z3 o @* G8 E3 ?* L
$ r U: r% N$ ]4 @
Video input : 0 (Camera 1: ok)4 f/ _( z8 ^& y4 L; q! H
) c9 K- f" f3 d! S
- ! B: J+ _, {! _* Z7 H& t7 F
* O7 Q4 O9 t0 g4 x/ T1 K- v* G
Format Video Capture:
; Y# y4 M! K v; m8 {2 K' e) Y* g! L* W
- ; [% w) m2 u0 Q4 b3 c: A6 K
" o; b( J: ^" R# b( L$ _* U" }; l Width/Height : 640/480# {6 ]( Q s) Q7 a: T: W
, i7 _; `. d% ?1 l% ]# c
- 1 o' o2 M+ g! E( I( J. G# I4 k
* }! q( H9 h6 M Pixel Format : 'YUYV'( l- P, w6 r2 V/ M0 H3 a! o
, {$ C" I+ e) M' Z1 v) \. I9 `/ X
7 ~' ?( P& K0 x
0 j7 ^5 s u2 r- [/ C Field : None
2 X2 b/ z% _; \2 E
+ s- N& E5 \! Z5 q. q) g+ S) b
2 t8 b8 w+ a% |% m* W! v. J% X* B2 c& _! w- Y5 b
Bytes per Line : 1280
3 e8 ]/ g; e8 g8 |2 w. c0 Q+ ]+ J+ P+ U6 H6 t' M; ]" O* ^
- 2 Q, p% d3 A3 P5 @/ Q$ ^
! p. ]9 }, j* Y. }
Size Image : 614400
, f: H7 u% C8 s
. |( @; U: X) E! g6 ^ C6 k - - k5 j- \6 f7 o/ x# k& I
+ C- L. f9 x$ f; \
Colorspace : Default: X( A& V* d; S* h
* A- R: ^# v5 _* O# C+ D
2 n2 g) n' D) Y4 y- c1 V& N% y4 W, P5 j* q4 o+ x' n
Transfer Function : Default4 S0 u. y) _+ T! `4 h. H+ U
) j, B# Q" k/ U2 M
1 T/ Q) B, b8 l0 g- w- a" |( E# H- W0 z. T6 ?5 C+ V9 B
YCbCr Encoding : Default* }4 {3 m1 B! u# C
1 l+ {! |, V4 t3 X. O8 F
: r" Y6 `8 r. r' M: m' T B
1 b8 T; o5 K1 {: y. S J' m Quantization : Default3 \$ B2 e1 A9 n
# D" }) m* f" x9 c
M! Z. H) z( r6 p4 X/ p- S4 ^# S2 {. C& E8 T l6 O
Crop Capability Video Capture:: r s: Z D1 z3 D9 `6 e5 u( E
- `: R; [8 j) i! \- , {6 W" f% W$ t) p0 m
8 }& H+ o1 x8 }
Bounds : Left 0, Top 0, Width 640, Height 480
# f/ ~4 e- F2 U; _7 v3 o% c* {6 F- g( R8 G) y- i+ ~
- + i4 X' W8 d" f; g5 _7 s
6 C, A: ]$ e9 e( a& Y$ e Default : Left 0, Top 0, Width 640, Height 480
4 p# V w' a) x0 r+ j4 ^# f( Y
4 G4 R+ ^1 ]2 z0 t& v# x' N1 E0 @
2 u, v7 W. ]* }* R. O0 u/ a* o0 U5 X, t |$ S4 I8 {
Pixel Aspect: 1/1) L6 h5 O; {" m, z( b: j
8 U o; B ^- J, x1 G/ |
- * D1 }* p$ l E' N& W( D
, m1 w f5 i( f+ x* Z. C. QStreaming Parameters VideoCapture:+ ?8 K4 i9 w- B& m0 l
0 H) _3 q4 ]& P
& B) p) ?+ _1 p: m# G. k x1 g) ~0 s- h
Capabilities : timepeRFrame
1 O5 R, E; B) K8 t# i$ U; v$ F4 s) M( P) y) w( @0 c7 f
% b* r2 h3 M" j$ L9 T" c4 W4 j3 @
4 L# P7 X: \6 _; ^- e) @4 w8 h Frames per second: 30.000 (30/1) 9 Q/ Z/ ~* h6 Z6 n* u
; [! g8 q' K/ q& T' E6 B$ \
* G+ I1 f* S4 t: J
$ @) i# [6 d# j Read buffers : 0
. Q9 S3 c2 f% x2 ?% w7 J- d. H' w4 ~+ x3 ]: q7 l" Y& k
- + c# C, y9 v# j8 G
% ?: z' e! `: T+ m; X
brightness (int) : min=0 max=255 step=1 default=128value=128
1 @/ r8 P- ~, C# L% u" B! ~4 F+ _) g4 s# h5 v7 g
, S) y/ f, `& D4 y) |3 A9 d7 G6 M% d8 q: ^" g
contrast (int) : min=0 max=255 step=1 default=135value=135 3 t0 z; f$ l! |+ n
; O$ A, X) t& p, y. y2 j$ i
! s7 e1 z- z' q2 o, k g$ E; b1 h' n( ]
saturation (int) : min=0 max=255 step=1 default=75 value=75 2 n9 K3 Z5 }" Y9 m" \0 S
: q+ P/ d: x' D. D! L) z
- 9 M9 Y# _. W6 {2 P& @: n' @
/ p& m* S) T* @, q; f( i
hue (int) : min=-127 max=127 step=1 default=0 value=0
5 D- G" U* t1 t9 s p( M
0 U8 A9 R" K5 ]4 ^5 e5 _0 G5 U - , `/ T& T9 n, G K: ?) D( L( m6 A1 N" ?
) M9 g1 h4 @" U
gamma (int) : min=1 max=8 step=1 default=4 value=4 $ J1 F! Z. ?" B/ L7 f0 O7 p
1 A* L% j) T G ~5 _, e
2 s' ?1 g" A [
9 u! b2 g% M1 S t4 `& L; ppower_line_frequency (menu) : min=0 max=2 default=1 value=1 + {; v1 F$ Y; Y
/ }2 i( q2 t" ^
/ G6 g+ ` W- e+ q4 U) i6 N; _: l7 X
sharpness (int) : min=0 max=15 step=1 default=5 value=57 {2 Z* M$ z% e* M
+ C' j% X% I2 O) Y% c& q) b8 d- 6 v! P8 E' m$ s) |
' Z; H5 U. @$ j- t$ [; ybacklight_compensation (int) : min=1 max=5 step=1 default=1 value=1$ ?" I7 R6 Y, }- u! b8 g, {0 i8 ]4 v
5 z" B3 P6 l1 ~
$ w# w% O# _) L
. @5 k1 o+ ]" }7 u
我们使用了两种型号的USB摄像头,按照手册说明使用内置的uvccamera程序进行测试,不过都没有成功,得到的错误信息如下图所示。 ![]()
![]()
我们使用FFmpeg可以抓取视频,命令行如下: - 5 I8 }. I7 G. D3 m% Z* O G/ K: o0 `6 e
ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv" i2 y( g- F% P. C- A
使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下: ffplay -s 640x480 -pix_fmt yuyv422 out.yuv/ m8 X3 s3 ^3 M$ C5 E8 l7 W0 n
上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行: ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 out3.mp4-timestamps bs/ G4 ^6 |! M0 k+ U! m3 R, X8 S
其中的-r 25表示每秒采样25帧,这个参数必须有,否则FFmpeg可能会不断地采集并压缩同一视频帧。-r参数超过30没有什么意义,因为USB摄像头的最大能力就是30fps。
' l, H6 N/ y$ o7 u飞凌嵌入式OKA40i-C开发板可以对于1080P的视频压缩达到45fps,所以对USB摄像头的视频压缩应该没有什么压力。
; u9 }' c6 p q7 ]/ \ w+ b- r: ~8 |3. FFmpeg性能测试 FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下:
# w1 h( ]5 Z; J- |5 v" G/ I ffmpeg-benchmark -i translate.mp4 -f null –
* N7 z( D+ s6 q! N; Q得到的测试数据如下: - 5 }! Y* S8 |7 }0 e+ R) X
, D& N. B$ j- m" P8 X% pvideo:
) G/ N( [* N) x
& _7 Y+ Q: N' g5 I" P' u* v - : x4 f" r* d" W; m
/ f" ^" s/ z+ _0 v+ Z8 I
148kB+ p7 B8 n2 W: e/ Y; u
# \+ }$ x5 G6 X9 j ^" T+ ? - 9 @4 h2 k# z r$ z
- B( o4 Y+ J* e' _- l- ]audio:0 S5 e, F4 Y/ [% ?
8 K0 Z4 I4 C3 f8 W% ~
, O: T. D& }" r1 w) G7 v
) O, X6 F9 _* N! Y) G3 |! N( C2 ?3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing4 \ P9 H* ?& I
! W4 @( Y* P1 g; [% c) m( _% T
: P' G9 u7 P4 g! g
; n2 l7 m2 U' O' Moverhead:
; g+ q4 m' H2 }( M8 I& w7 ~4 ~. C3 ]( t6 E( d8 U' N
- & K$ n+ t& N! w4 M
7 G6 ~3 d# a4 G' U8 e* B
unknown& u, M0 f; G$ j- d
2 p- ]: ] a( c
$ V( N8 { u" `; X8 b4 e+ p( a
9 d3 T) W9 c. o& A4 {2 `& c u% c5 abench: |; x3 | y4 K! u
Y& u0 d; O/ L9 D
& B' A3 z5 S2 u) v8 r% k" C; L2 h0 R5 R% y+ ]+ P3 D
utime=2.820s stime=0.110s rtime=0.956s. [- |8 x! _6 D5 @
7 D- t3 L9 y* O. ?/ }5 h! C) t
% Y) y8 X" F9 t9 ^( y- _0 N$ U6 i2 j) }. ^% |% {: |
bench:
: D9 }% F$ y& o6 Q, X5 Z9 @+ t" n5 h! ^/ U
% ~* F4 D' a* O) E W$ i. j p+ w: S- o& `$ F9 ?/ O
maxrss=14208kB
1 @1 z0 i9 q" ^. S" C" H7 G( F' I% u% Q9 T! G0 n @
( U' L1 G. o: p
' j4 Q S, G2 u6 r2 ]# n/ o由于我手上暂时没有其他的开发板可以对比,于是就通过我用了5年的i7-6500笔记本测试了一下,测试结果如下: - ; m& O7 d. z4 r8 W7 w
5 S5 n) G( x. q. gvideo:
' Y) ?4 t& o0 g$ |6 E
* `: A( E4 I6 S$ p! K, Q
; O& i1 {# u {& W. K6 x9 U
4 \. j" e0 X$ @. e- N0 W241kB7 x; K: B! ^% {* B+ d2 S7 M
! N1 ]( `# w) Z
7 B. r7 b8 _+ D `/ x6 Y/ ?8 H2 z$ n7 e1 v: g
audio:
2 b( ?' o/ r _& W4 A! V; Q/ Z: s
+ W' l3 M5 q- v, a- % I. Y# g, L4 }: {/ r( E5 L9 d
& L* p" z: J% [3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing
3 s! j& v; f5 l$ d5 ?$ }
8 K2 H4 H2 u1 h
3 y/ W( c7 ]0 Z0 I0 u% N- V5 I( O1 L* `4 Z+ k3 s
overhead:
( G: U7 t6 ?5 |2 Z0 f7 v+ a- Z; F: _4 v: G- D
- ) H* m, ?* B/ h, F& v
% Z7 U" X# w6 N& b: g7 N
unknown
- ?7 D" @# R {' o* d5 }( m3 N( [1 O# [* K1 b; k- h9 R
! P& F7 s1 X0 G8 I4 f9 }
5 z; g$ i+ X! Y6 L6 l5 Sbench:4 j+ |6 Q2 X ~- n
) Y9 p% V7 I( ?
7 Y* U& l' x( j/ w
6 l; o. V3 H% s Rutime=0.391s stime=0.000s rtime=0.228s
7 {% n! J' [9 b# y. O
+ [; J6 g' j' Z1 d {
% Q; ]8 L4 b+ z( S+ i
- N: u* m9 S* \5 nbench:
7 P8 s# O- A6 Z
+ ]9 ^! z6 {" N0 J$ p3 n3 u
" x" d# ?6 u( m; ^1 p7 P7 f* d% K3 z5 X. s/ p
maxrss=20316kB5 M3 | N S% x
" d5 n$ o+ T6 J5 r
6 S2 r; C# c0 U1 U% w+ b, M/ Z. ^
t9 q/ u3 Z2 R( f9 t! d. t9 U1 ]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:1234/ f9 q9 J; C$ {$ q0 q; I1 }' n7 C" |
使用Wireshark可以看到在PC机的1234端口收到大量来自OKA40i-C开发板的H.264视频流。 ![]()
8 M4 V) J3 J% n: H7 @+ q4 t8 X9 q& y
如果想在PC上显示视频流,需要建立一个SDP文件,它描述视频流中的端口和编码信息。
: s$ ?% j- H' B5 l- e% _) ]; MSDP是来自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
% [9 N# |- Y& D下面就是使用VLC显示的接收到的视频流。 ![]()
# G& H9 J' V; d* w% w$ v2 g
. g$ b: h" f0 q9 Q6 j+ P$ a5. 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
4 I' E3 i) w3 A1 ^ |