EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1. FFmpeg的安装 FFmpeg是用来记录、转换数字音频、视频的开源软件,它支持文件和网络流操作。它支持以函数库的方式使用,所以有很多软件都依赖它,比如VLC、暴风影音、腾讯会议等。它的命令行程序也非常强大,各种命令行选项学起来虽然困难,但是几乎能够满足日常对音视频的各种处理需求。今天我们就通过飞凌嵌入式OKA40i-C开发板保定飞凌嵌入式技术有限公司来介绍它的命令行工作方式。 0 w9 g7 j, x! a5 ]
FFmpeg提供了全部源代码,所以在网上可以找到很多教程是关于交叉编译ARM版本的。我们测试的版本使用的是FFmpeg-release-armel-static.tar.xz。解压缩以后拷贝到飞凌嵌入式OKA40i-C开发板上并设置好权限就可以使用了。
7 R$ K3 Y4 L" Y" L+ y. g2. USB摄像头测试 OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用 v4l2-ctl --list-devices
; G7 _1 S3 o$ z0 W可以看到/dev/video0就是我们的USB摄像头,如下图。 ![]()
使用下面的命令可以看到该摄像头的全部参数: v4l2-ctl -d /dev/video0 --all- 4 \ ~1 q! d" ]
7 ?( y% d/ ^- K) v
8 v' G) J% @: j, a2 w' |
5 ]3 E$ L ^ S/ S; h - 7 }; ?% B7 n; v$ ]
7 N/ X; I4 o# S! d9 G" r
Driver Info (not using libv4l2):# S7 n* g" h5 q2 M; |
: ]8 @, o( a' q5 T7 X, B( ]2 y/ ]
9 W. M) ~! Q( E# E$ Q
+ v; c* A; |: R, @/ T3 ]; A Driver name : uvcvideo
# O: ~9 ~& y8 d8 y. h- n: j( v7 ], z" q
- ) c% E% m; U+ k$ h
+ {) C( w+ i& S
Card type : USB2.0 PC CAMERA
0 n0 W( B3 @: Z9 r' \; |' U" N7 m5 q
+ s1 z% a7 g7 n9 X9 o - . {- j4 m- [' x# s
5 j* O8 f7 Q( q9 z! L2 H h, \ Bus info : usb-sunxi-ehci-13 O, {2 f1 `( C
; a" a, m( C2 Z0 w& G
' H) h; P7 x' M9 q3 M# n# a$ _9 \/ J8 A. d; v( ?
Driver version : 3.10.65
# d" b! r- f0 [) U, z! j0 f; w2 U& a' T, s1 \
- 7 i. ?. Q, {5 d0 v: G7 o+ ?* L( {
" y2 R& W3 x2 S2 j
Capabilities : 0x04000001
% O" S) [% {6 Q6 p" n: f, D. f. A9 `
- , G. j+ u, L& @: B& _
! M( h& [6 O6 ^ Video Capture
5 i8 i8 u( O. ?4 S; A4 I4 O2 M9 n, f* d: h( Z$ M# Y7 o
H7 w2 c f) g2 C# T6 C* ^$ y2 y0 s0 `/ U: _2 H" ^+ ~! s
Streaming; K: {! K, g/ |) O9 a$ w. H+ r
$ g# e! P+ D$ L5 F# D- 8 v7 a- r; _! n) {2 }: q2 m/ w
# D4 _5 Y1 C' s0 u8 \0 H
Video input : 0 (Camera 1: ok)
$ `8 E6 x! \. q- [& Z) G! Q6 S8 F+ y# ~4 t+ x/ m6 I
4 x+ x/ o% F/ C
. w$ j; o% `) M# v- T+ uFormat Video Capture:
- r! U% q/ u- Y0 K S" M$ C$ [+ M f# L4 G" M5 U
! `* _/ H" q% ?8 s2 c
. n. j7 _& [, w Width/Height : 640/480
% Y7 r9 m- g! D$ ~7 u
4 E, Q; h; ^/ Y7 e4 u
. @$ K8 S9 C& b/ H, r2 h* h' U ~5 G9 |$ X- t6 l& |: O& P
Pixel Format : 'YUYV'. g# k0 C! m; R2 s+ r$ O7 x
7 }7 `8 Y/ X, n+ t/ n O( Y/ W& Q4 J
9 L( b7 k% p$ c/ g5 @
, W) x( ?( }, J* y% `. F Field : None
8 K( b3 {% w, t
/ w% Q2 ?" J6 s0 |$ K
8 E9 o6 x" a) H( X0 v1 e `4 {, l! O
& N; Z0 K# Q2 V- K4 h8 H% J Bytes per Line : 1280
( n$ I( r9 S k( e6 w/ q: d+ U* |0 J
- @( d2 x# r! q# w5 o% q' a
" R# [0 o0 n/ G7 r& Y. Z
J8 r. k; X/ P Size Image : 6144004 \- Q; D7 g |# W/ Z O6 Q1 i) F) o8 W
& d# b% ~6 ~9 V+ I: l' D& J, L' }' ^- 1 L4 o* T( c7 Z2 m1 v1 M5 ~& }
; ^4 Q: M1 m& \2 V8 d& S* a0 _8 G Colorspace : Default) S9 o7 B& r9 u
8 K J: f: W" ]$ O6 \
$ P7 B' u5 ?( g0 J5 T3 z* Q0 }
3 r3 U! `6 ]" ?6 P: o/ J9 h+ F Transfer Function : Default
6 N' k5 w8 s5 E, g2 j( P2 p# y
5 Q2 ~3 k/ l, }3 c- + d0 w5 J4 t; e5 B! d7 C
2 U1 W8 w; p& {+ F
YCbCr Encoding : Default+ @/ v) v A5 Z* b) H- _( @) k
. l7 d6 w* J2 n4 m5 C& T
- ; g& D6 J4 s% r$ `1 i- Z) |% Z
" U8 l0 R& {1 w+ U
Quantization : Default. q8 u8 G: O4 P3 u7 ]
2 g8 I ]6 ?- f! u, R. i; C q* [ - 2 u3 i3 f/ e0 ?2 o( R7 V
0 ?2 j; s4 X0 f! gCrop Capability Video Capture:' Y% z$ I4 w' w6 h# K* d) Z
" v& U# s: J' Y, Z, e - ( H! P' y9 s) C( u' H0 L( _7 B4 ^
3 u' }9 v- N7 r/ e P1 K; Y/ s
Bounds : Left 0, Top 0, Width 640, Height 480
: K9 [8 `0 N- [* _& ] v: G8 z) N, q6 }& d6 \+ Y8 C
, C& j. Z' }0 o6 h6 N$ q: u- W! y5 m) R% A. j( h
Default : Left 0, Top 0, Width 640, Height 480
3 z- y2 _. B" K+ j8 B
8 I# ]9 Q& r- d$ ]4 v5 c3 h: x! W
0 w+ ?4 y0 Q6 Y) B9 o6 n- }2 f& n+ v0 ~( `' J4 a9 P$ m, t
Pixel Aspect: 1/1! ?5 q- Q# W% @! T: H: }! i
% C- E8 ^) W. \$ P* m/ i. P
- , a; c% Y+ }! e# m& M9 V
$ i8 `, x1 W2 T/ _/ L6 SStreaming Parameters VideoCapture:1 R; x" D6 g7 n% v' Z
5 q3 n9 y( Y8 v) u" E
5 y" J& r9 H, O- E5 o' n& _5 `/ N' W" q) g
Capabilities : timepeRFrame ) T# y# q- a+ n( h
7 E' y l* s; w* U. P6 G
k1 ]8 M9 h2 @8 P% W- P( d3 q- y3 t7 b, Y9 h% [1 D
Frames per second: 30.000 (30/1) : y" U* i9 {; A( A. R8 s
& e8 G; D% J# S, \
& i: E( V1 o4 Q7 E9 N3 c" a0 ^1 u* ?" A$ q, `: _
Read buffers : 0 ' s# y; z5 d- r c( m
) R% t, T f- x
! D* [9 `" W2 ?& F$ A6 t1 \, U: C, o) y2 O0 \
brightness (int) : min=0 max=255 step=1 default=128value=128
" y( H1 E% ~# r7 s, o5 X. s& {. M9 _) w
- ; L! S( f6 w3 a& b' ]
- N+ J: j2 c, Y1 b/ {9 ?$ `) m) q
contrast (int) : min=0 max=255 step=1 default=135value=135 " I% W1 |7 U5 k
9 f/ ]% r% | F: i, O2 a5 P
- 6 v4 }6 |% r9 `. t
5 x& K5 |) a* X' ~# {+ u( K
saturation (int) : min=0 max=255 step=1 default=75 value=75
8 |/ m* ]. F! \& {: @7 h2 a# C: p& j3 V/ a' L+ v
- ; g0 I6 A" \. C- v) {" f* A l2 C
+ p: e: Q, t7 z; h: L- L. f- y hue (int) : min=-127 max=127 step=1 default=0 value=0
. U$ t( w# q3 x& y4 v' W5 N- b- }5 `$ R ?/ L& O
" ~# `) Y0 J& J' X
' G/ t& N: Q/ f1 E$ w. p gamma (int) : min=1 max=8 step=1 default=4 value=4
0 c3 q3 O5 f1 n, x5 V S
# X0 l" _ _7 W& U7 r3 a0 k' T. {
/ }( C( ^ l3 r$ c& M
) \. L f0 y* i! I- m$ Tpower_line_frequency (menu) : min=0 max=2 default=1 value=1 + r! o3 |+ A4 R# {! Q
7 G9 v1 ~# D# A, L C1 r) ~3 S- : t5 S, e# f( I% n4 q. z
6 i3 W! {+ b6 H5 J$ _4 q( _% W
sharpness (int) : min=0 max=15 step=1 default=5 value=5$ c+ {4 \' C# n; Z' g, e
' @" [7 K( d" t& r - / R7 N$ e* z3 v- w* s4 b6 K
. @# E- c4 d+ Pbacklight_compensation (int) : min=1 max=5 step=1 default=1 value=1
5 a n4 ~. U o6 A
- [ B3 I! m* M! @6 d1 \! ]+ K
8 M \. \0 E) I- `* l0 |9 ?
9 v, V' F2 w! `( O9 ^
我们使用了两种型号的USB摄像头,按照手册说明使用内置的uvccamera程序进行测试,不过都没有成功,得到的错误信息如下图所示。 ![]()
![]()
我们使用FFmpeg可以抓取视频,命令行如下: ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv& K. ]. Z0 g( _* B6 s; m
使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下: ffplay -s 640x480 -pix_fmt yuyv422 out.yuv
9 `) @9 X; a9 ?- F# b9 M9 U* I上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行: ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 out3.mp4-timestamps bs9 L" `. \) R. z$ _& w4 E0 Q; g$ @
其中的-r 25表示每秒采样25帧,这个参数必须有,否则FFmpeg可能会不断地采集并压缩同一视频帧。-r参数超过30没有什么意义,因为USB摄像头的最大能力就是30fps。
. F" S) s% c F2 K1 N- R飞凌嵌入式OKA40i-C开发板可以对于1080P的视频压缩达到45fps,所以对USB摄像头的视频压缩应该没有什么压力。 - d+ h r3 g \0 J# ?
3. FFmpeg性能测试 FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下: ffmpeg-benchmark -i translate.mp4 -f null –
2 e0 O8 b# `$ u6 Z得到的测试数据如下: - 5 w2 R; [$ B+ e# B6 v2 S3 y! d6 E
! @+ ]( y8 y% G/ C( T
video:6 d5 A4 l$ a; c, \; P3 `3 N6 q, }6 X
( H2 l3 F I M5 Z% S; @
- ) ^) L4 x& x) C# |2 ?! i; E. ~/ u( ]
* J" d( f# h6 d' |! }
148kB
) v/ h4 S! t* x& a$ \. L% f! \2 W$ c0 F* V7 i2 Y- z$ D
3 ?1 U6 b* C$ n3 S9 [' l* y; F: i# P% ^$ g1 x: \! W0 q7 h
audio:
D2 R; K. ^( B' K0 Q$ ]) G, W3 F3 B8 n) U8 K! f
- 4 g9 q# c3 Z. L6 j
2 O+ ~' s% c- m* M8 I
3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing
7 g/ r: z& O! b0 e! M& R' i9 @( E" `7 d" P9 |; P& C4 p( b
' S$ h2 ~1 H4 {' c5 M8 J& J8 N: V4 p: q2 d# A0 T
overhead:
/ ~0 f6 D. r; J L, [" f2 F$ f [& b( f- O6 n2 X
: ^# C( i o3 A# P' \% c ]# W4 q7 k. R) x+ j- Z+ n# t6 {
unknown: M2 @* p8 i+ n* [6 G1 o% B
+ [& V9 Q; ]) U X0 v+ ^# {
- & [2 T6 Q/ G& c/ R) f
+ I `7 r. [3 e3 H. Hbench:
2 V- A; f4 Q7 C! I" m3 E/ b0 o& z4 r+ Z/ C4 d+ n6 }
" f H$ p- i: A5 \
, t/ Z$ ]: \% Xutime=2.820s stime=0.110s rtime=0.956s, L9 U8 w+ G8 b
, F- ~: [* ^6 H; w4 g
8 F# R1 M& ^. E( l2 @5 x- N& _ l& L% [; N7 p
bench:2 X3 m0 H4 b' u" N, V. x
9 l# ]: ?, M7 X& u/ N" N" \
- d/ a+ `" `6 o$ r* S- s; G A) c7 G3 P# \
maxrss=14208kB0 d( w/ b' R+ k
* O9 f8 p- `0 |
( P$ {- Q1 r! ?( O2 Q& @ # O2 x, j: V9 Z" S# f
由于我手上暂时没有其他的开发板可以对比,于是就通过我用了5年的i7-6500笔记本测试了一下,测试结果如下:
0 r1 a% F% d, E$ _$ @, {* p, v) I6 J7 e- R: v! U9 t
video:% a6 ~. \! `3 \+ t T
/ ~# x! D' n/ q) v, l2 ^
- 8 Z6 k4 X9 f9 U' x2 z
& N- ~6 s* ^0 h6 U. a$ k1 E
241kB
$ r4 f: I. U; `4 |# F# F! r' ?( N
4 h' q2 H* i" w8 _8 K1 |) M7 f - % {) A- q4 q+ X+ }9 i4 b; m
7 ~+ h; j, R- b/ R! |( xaudio:! s6 L }" }$ v3 u$ t
( M' E. w: Q5 N( y! @& P7 @0 Q5 W
- $ b. h s8 a* D# y0 e* w
; N' N: P! K/ e5 b
3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing) Y |' `! o! {, y5 r" [+ `
8 ?3 B) Y7 M( h/ x+ A* ]
% Y5 I1 _! c1 f
% E$ h' r9 J# C8 G6 j6 B6 h# F loverhead:
4 j8 ^2 \- W+ z% O8 L4 D
6 K2 o0 N5 [8 U% r2 z- . v6 f U2 C. S4 c
7 o) Y' }! @' N# z5 A
unknown C& g: d) V& V0 b2 N
* q: Z0 o/ T2 x - " `8 a* N/ F# L2 g* n
! g: Q* a' U, o7 m0 ~# f
bench:
0 w0 _: P: X# X
?) e2 x% c7 U% M - 6 S, _: O. o; {- r& I
2 `4 J; M1 C( _& h; }utime=0.391s stime=0.000s rtime=0.228s
0 }# `1 ^% y8 a4 f( A7 Z, r+ _. V. O, U7 y/ e% B
0 z) B3 l3 d& I: ]/ k
" B+ R% h7 l+ f; f- `+ xbench:. @% a! E3 Y5 Q( N
8 L% z7 h6 b! Z9 x: S. i
0 o) ]4 S7 b: ?- `3 x/ S
* |: Q' `0 K O' Imaxrss=20316kB
! H9 g9 H2 s- x2 r4 L! S" l& p! R
6 D7 b' K% R7 K7 p6 ?# Y/ z4 s" |6 }) L* g( _! o
H4 W( \2 n/ n) w- a4. 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
3 Z4 I) l: r @2 g2 C/ v使用Wireshark可以看到在PC机的1234端口收到大量来自OKA40i-C开发板的H.264视频流。 ![]()
# f: y& @8 c0 h1 s( I9 l- \$ E+ R7 y' r$ i. ^
如果想在PC上显示视频流,需要建立一个SDP文件,它描述视频流中的端口和编码信息。 0 N9 v, D5 |$ q$ d1 a. A2 M! H
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
; K0 U5 n5 D$ }; T& m% [+ `7 s下面就是使用VLC显示的接收到的视频流。 ![]() - Y9 N: h5 y D5 A/ M3 T
* m2 e! Y5 E- D$ B- u# H8 c+ H
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- X m# Y+ {( k9 g! t; Z9 O
|