EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1. FFmpeg的安装 FFmpeg是用来记录、转换数字音频、视频的开源软件,它支持文件和网络流操作。它支持以函数库的方式使用,所以有很多软件都依赖它,比如VLC、暴风影音、腾讯会议等。它的命令行程序也非常强大,各种命令行选项学起来虽然困难,但是几乎能够满足日常对音视频的各种处理需求。今天我们就通过飞凌嵌入式OKA40i-C开发板保定飞凌嵌入式技术有限公司来介绍它的命令行工作方式。
" V- C/ K" O5 ?FFmpeg提供了全部源代码,所以在网上可以找到很多教程是关于交叉编译ARM版本的。我们测试的版本使用的是FFmpeg-release-armel-static.tar.xz。解压缩以后拷贝到飞凌嵌入式OKA40i-C开发板上并设置好权限就可以使用了。
. Z+ Y4 h* w% O, U. D- L2. USB摄像头测试 OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用 - * w* a: z4 n6 x! F) ~+ ~' y
v4l2-ctl --list-devices+ p: C3 Y( G8 C
可以看到/dev/video0就是我们的USB摄像头,如下图。 ![]()
使用下面的命令可以看到该摄像头的全部参数: v4l2-ctl -d /dev/video0 --all- ' k' \6 T6 }, s
! Z' |7 m' t7 k+ |/ V+ S
1 x1 |4 M) p& k. l( C$ z: q1 Q
" ^5 p. C' V% f+ U2 Z! w5 Z - 6 R- G* P; P! G5 V
2 v8 z+ I$ t( X1 n5 ^5 ~9 Z, Q ZDriver Info (not using libv4l2):7 y! g n) b& F$ m, F+ c2 x. y
4 n" J* ?) r0 x - 5 }& P, V9 c7 @, N: |% T, v. j
4 I* Z, g/ W4 u5 E
Driver name : uvcvideo+ R0 B! [0 P& J
7 _& ~" _/ v$ b4 i l$ A5 Z# v - 6 \' h* [! s2 W" n0 |7 m, D0 h
! m* _9 v! b5 [! D9 L5 ^; z Card type : USB2.0 PC CAMERA% C6 ^9 E: n) J' h" r ^
! T6 b# U% a5 e; a% Y
- $ t( s7 i8 m' }% O8 ]7 ?
; C$ Z, \/ ?) g6 b6 D, Q0 w Bus info : usb-sunxi-ehci-1
5 K7 G# c: }1 \ }! I1 E! U* U3 I
* G: k6 B9 i% t& r" m8 a; u
* `# B0 d+ v; D$ `, p6 Z1 G$ [4 g0 x. e7 P, D' ~; L% n
Driver version : 3.10.65
# q. U# n' w$ G" `# p2 J# T3 i" b' K; p# j" X
8 S; z6 K0 P+ ?* G2 S2 r( `
$ D |0 W$ w3 ]- q Capabilities : 0x04000001" v7 p) L- n% I! [8 z4 V+ f$ V
+ ~6 C) p) M2 p. s
- 1 S- c) |7 z$ Z
$ k( s/ T" i/ s* P2 n
Video Capture+ p# H: w6 q1 h, N: m
: k6 A5 M- y% `6 t5 C
2 Q( c/ T: y$ U3 W; T% i1 E1 R& `, ^2 i* g
Streaming
% m- X- B R9 G9 H9 ?! j7 w
. N* [; Z/ d7 F5 O ?# X- + M- q ~5 Y% M7 B0 O3 b1 X
8 M( k% o! Y) Z
Video input : 0 (Camera 1: ok)1 H1 |# u4 t4 `4 g% G0 V9 ^
, j8 M4 P( U! U5 M& B* ?6 b; k
- 0 R0 `$ S, r4 k" ]" G& R4 [8 L
c/ C8 }1 E, Q t1 \, cFormat Video Capture:
* p' q0 W; H+ p6 t6 M# A7 O% _
# E: Z- [' h2 B9 p1 m! } - # {. }0 @' [2 o8 r1 V
' T: S! q! @( P; Y& y5 a: l6 f% G
Width/Height : 640/480
( q2 u+ V: a% t. t: h! \3 E G, T3 s7 \6 v, R" y* A
' z8 Y" ^1 f. A8 k1 X3 U
9 h K# u, o1 c Pixel Format : 'YUYV'
( S$ m5 j3 P$ a. h2 b4 Z3 ?
3 |. ?( P6 i9 Q1 g, _4 R- 4 F/ h3 N; M& B- U
9 Q$ o% Z5 ]% O- E) D( L- m$ h
Field : None
% O( [ e7 |# O+ z* Q6 C8 k* ?' N# X0 p9 z0 t
- % `; P; O4 s) n4 d/ \& J j, @
8 P. ^" G/ f+ r4 I5 m' |4 f Bytes per Line : 1280# w& V- @* ^, S- T+ b; S
- @3 Z# m5 N' i
% T! N D2 \3 i1 c+ @" F7 t: @9 y7 n
Size Image : 614400+ H- i$ {+ g0 j( n
0 d$ K1 v( @- Y% u k' T- + |) s, a# ?) i: k8 Q9 {
5 }5 o& D" N! _; R
Colorspace : Default4 w' q9 a$ k8 D: A) ?: y
, b/ m1 Q3 o! H& Z4 }
- 7 \5 u3 a/ `. p
, {- l8 v; h! |7 z8 N/ C
Transfer Function : Default+ Z3 l% ^& J! V* U, j
2 n( @% {- Y' u& F( Y
# S% D3 V1 \- p# N+ {2 F
, e5 x' s6 K8 X8 q! z* t YCbCr Encoding : Default
9 b9 Z% W& `: N4 i
8 Z9 U8 E' x; q2 L: D5 x- 3 W7 t, ]# W% f8 y% \
( u- ^1 V1 n( i6 w4 J+ n$ t( n* K" g
Quantization : Default
9 e3 c, {6 _% E! M! o
m. k$ ?) [. @' U- z9 L/ B
4 @" Q C" j6 ~- W. \. @1 E: ]3 b# w+ s' I7 @0 z
Crop Capability Video Capture:
$ G V* n" V- t6 D" |5 c6 h. D3 V& d/ `* p
7 B5 _/ f6 w( X# p
, a, w# W r: N: N4 `8 H Bounds : Left 0, Top 0, Width 640, Height 480
( r) |; N* l! u+ N# w! G
8 q5 {- p4 E1 V" n* D) M) S- ; c& A+ {# d6 M. i7 U$ e
& O p) m7 W1 ~1 [# m
Default : Left 0, Top 0, Width 640, Height 480 0 g. r$ g* n/ m |9 b- O
' E3 k! {5 W$ f' h5 g) Y
- , D% f% U7 h* N
! o3 ^( \9 \: e7 \; s1 c
Pixel Aspect: 1/1
& c7 n0 P' p" C( _' x
8 W( ?: K5 F# A# x" | - ' \7 m. o, m9 g1 W' X h9 o
* ?" w6 H& ~" l3 T: Y) [
Streaming Parameters VideoCapture:; |, V- y R2 r
% D. U L1 b& z B& M - B- ^ k7 B6 l* v
0 E) y2 r8 T+ z& Y3 M( ~5 Q Capabilities : timepeRFrame
5 x# i5 N5 J( |0 l! @$ X- a+ ~- d( v' X* ^
- $ V% B/ I$ _! x
7 a$ R' `) H' [5 y
Frames per second: 30.000 (30/1)
4 L5 n/ Z( h( B+ K2 O, Z4 O- p6 i* S' p7 d
) ^6 Y5 Z, Q0 ~) {+ H6 g/ q! c/ B
9 |1 f* i- ]! E8 I( f Read buffers : 0
3 d, D. S: B. G6 T
, B/ u4 i; y) V9 l" |- ; v! G, m6 C ~7 u7 o. o! i3 A3 P
! t+ T) z8 e) l( O) I
brightness (int) : min=0 max=255 step=1 default=128value=128
, C; r0 ?% j7 K4 ^, p4 O4 `
9 k5 U( b" U* C7 q- g! R; f' ^! G
% @" I+ O1 j8 L0 F7 M4 k7 }8 Q1 _4 t% \) {
contrast (int) : min=0 max=255 step=1 default=135value=135
) q" U) `3 y% p _+ b$ o' P! X, g' l5 n/ j' D M
# r) v. ?9 }: O; o# j; E' X3 `( j0 I' C1 s
saturation (int) : min=0 max=255 step=1 default=75 value=75 , H; p2 N; c, \$ P, O0 o2 G- [* ^
1 i+ p6 D' a! I% b- 4 v4 t [. m: i* p3 X- @$ [
3 ^! Z3 b/ Q" y/ n hue (int) : min=-127 max=127 step=1 default=0 value=0 9 S# r$ I7 V" ]! t' i( o7 u9 F, _! ~
: S- V6 j t% X- d - 9 ]* v0 s9 h+ u4 [1 }* `
0 {* X1 ?5 k# o/ }1 W9 v
gamma (int) : min=1 max=8 step=1 default=4 value=4
* ]7 V6 \2 g( S' G6 G
' j/ |% d/ T8 b0 i' X - & M, L! ?" S) z
8 J, m) o& L% U6 I* @# @power_line_frequency (menu) : min=0 max=2 default=1 value=1
' O7 u9 `% `1 X5 j# f5 a1 r
1 Y/ s" L" h9 l: R8 D+ _. ]
) z5 q8 x; C: J! Q' B) _0 s. L2 u& a- H
sharpness (int) : min=0 max=15 step=1 default=5 value=5; C1 `$ N4 K$ v+ l1 h0 |( _
7 [7 ?3 `, P5 r+ g' O8 T
. |, j5 s4 J0 k" G" c8 B' Q9 q8 F/ z, p8 _2 }3 M% a5 T
backlight_compensation (int) : min=1 max=5 step=1 default=1 value=1
. e8 N2 F1 j8 c' z3 I* }6 I9 @8 E
* L0 U$ Q2 A( V9 }
/ d# X: K1 I. E
! ?# T4 j. t" m$ g* C
我们使用了两种型号的USB摄像头,按照手册说明使用内置的uvccamera程序进行测试,不过都没有成功,得到的错误信息如下图所示。 ![]()
![]()
我们使用FFmpeg可以抓取视频,命令行如下: ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv
! N! _( S3 l7 i" T- w' _/ M! _) j% Y使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下: ffplay -s 640x480 -pix_fmt yuyv422 out.yuv
1 I8 [1 c( g# V1 r上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行: ffmpeg -y -t 15 -r 25 -f video4linux2 -i /dev/video0 out3.mp4-timestamps bs5 \4 M& i/ n# Z {
其中的-r 25表示每秒采样25帧,这个参数必须有,否则FFmpeg可能会不断地采集并压缩同一视频帧。-r参数超过30没有什么意义,因为USB摄像头的最大能力就是30fps。
! q" R; [4 y0 H0 V% |' @% g飞凌嵌入式OKA40i-C开发板可以对于1080P的视频压缩达到45fps,所以对USB摄像头的视频压缩应该没有什么压力。 : d' R: l- j' o9 W' V1 V: s
3. FFmpeg性能测试 FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下:
) u% ^$ L9 i% C9 \9 P; ~0 h ffmpeg-benchmark -i translate.mp4 -f null –6 H" F" w r$ }* Y/ |1 Q! K
得到的测试数据如下: - - p1 E9 j% L, I* \
$ w; ?% X7 J/ v. @1 _' E! p
video:
7 v ?6 |: M! T, f. V$ \
: }/ `4 i \9 w) K - + a3 B- B, n& Y& P/ Q
. R/ i3 l5 t2 {1 I3 V8 c: }( p148kB& ~" }- d; p& h# q( f, e
& E" F5 z% c! Y- k B
) v$ {( J. H& G0 |0 D0 e" B- Z8 A% R# C* {& _. `
audio:
. s5 p$ [) d7 M. j1 S; o7 R1 k% }5 Z& `2 k2 O9 k; v. ~, z
- 8 V) i A2 i; _7 n4 p) o
' T* F. {( e% k$ k4 t' n9 V; L
3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing, _6 W, b0 q N+ Y+ U# K5 J( U
- P# E" o$ A0 f% g
/ ]% d) W) b# T! v- i2 ?$ E" b% I v/ P0 H, E
overhead:
( _9 x" L# ]" Q' H1 ^, `
" j! d0 j& c$ o! Y% M0 y
( L [; q+ M1 e; T, g' f) N2 a* Z' k- ], D6 Y8 V3 y2 f
unknown
; z' F' n0 ]* o; I0 p( E* h1 ? {% H$ J
- ! \! a$ z9 \$ y1 b% u0 N( Y; I Z: K
# h6 p6 k% M4 z; fbench:
0 |/ Z. ]! m4 J* L, I0 |0 O$ J6 M; Z0 Q7 h# m/ ]
- ~+ \% I) z5 {* `' ]* ?( `
{0 x0 g! r! C1 V @/ h' Q# i
utime=2.820s stime=0.110s rtime=0.956s
$ a; z( R3 A. X/ r" ^) u' _& A) T
% X3 B* `2 H% Z; D
4 t L7 z8 ^/ p+ Q" G& v3 b
% M# L+ j/ [$ H# f/ Sbench:
! Z% g4 a# {+ H4 ?
# l3 p9 ?, T& W$ X/ A$ {' i
+ r( R. ^( z5 u; I, f6 N( _2 @: g/ H7 K
maxrss=14208kB
: p3 o% P3 n# u ]) F5 G
" X7 K- }+ \. V# E0 ^0 w/ y6 `( ?/ @, x( b6 T2 M
5 r0 Y4 l6 ]) I/ J4 x3 m, F由于我手上暂时没有其他的开发板可以对比,于是就通过我用了5年的i7-6500笔记本测试了一下,测试结果如下:
& o9 Q b8 {' Z
) `7 g6 {) `; ~# i: q. m2 o$ q/ Qvideo:+ Y. t( @* s# X; A7 W0 y- q
, K' |- C4 I3 b/ d5 O0 P& ]) [* q
" c3 z; z. B5 X% ]2 z* L2 e. r1 k3 L& x$ C/ \( ]8 V
241kB
* {+ q' E& f0 Y. v4 b& T; ?2 R: @# k4 R' A- {
5 `! x) `( p1 X$ H2 I/ t; ^2 i5 p, c+ H; w
audio:
7 ?! M' Q+ f) E7 F' ?8 ]# r2 q k! o1 u5 J! a) w( [! ~7 e9 ?
- + e1 b/ }# f+ u7 ^( y+ P. K
( G/ b$ X) u8 E8 u5 |3428kB subtitle:0kB other streams:0kB globalheaders:0kB muxing
' h1 D) h/ E9 G" _- o
1 p$ g/ g) r @# U8 @7 k
9 M7 t; d% ?) I9 ?! w+ S1 \5 Q9 m1 W4 X
/ U3 M9 p" G; p" i) v& Zoverhead:
. x1 c5 @, t$ X! M& ^) M. G* \, m5 {- q% n0 |; o4 _/ M, {
9 D- V; `$ }6 b) n9 E7 Y T4 W) |7 k
unknown9 y4 K6 Y7 i0 R. k
' n$ G% w9 T: }+ U) J* G- 0 ?/ n8 s# y& \0 T
$ }3 P( `8 S$ y7 A
bench:
* p! y2 L/ s8 i- _- }/ w7 b; n6 J2 w% t
- O/ X6 Q9 p. [2 M
/ @6 o2 P- Q0 B' s* P6 jutime=0.391s stime=0.000s rtime=0.228s, @* M* L) Z! r+ Z) L% n
5 }0 j9 v# Q3 Q- % Z! [3 r' G! v0 t! ~ B
( M, [8 n1 N! J& `* Tbench:
3 {" U7 i$ k1 h( @' I; g8 N( t
# x$ F. W! i& A( _! S' ^
2 {" M3 `/ `3 o7 O) [; U
1 [: {: j% f9 ~' M/ W* Pmaxrss=20316kB6 l* [: |: H( p7 |
- G3 H$ {- `- [+ Z' x8 H# k1 w" e, K& Q4 h$ D* J- b( [
2 Y9 L7 i+ Q2 B* ?! o) q
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
0 F" D" S3 p$ U: [使用Wireshark可以看到在PC机的1234端口收到大量来自OKA40i-C开发板的H.264视频流。 ![]() ' E% b9 \- ~4 E+ i& O. Y: l3 @
! v) _5 _2 I: t% G
如果想在PC上显示视频流,需要建立一个SDP文件,它描述视频流中的端口和编码信息。
1 T/ J4 f0 g1 {- \& L3 n6 {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
) n$ w2 D- a: I8 q* G4 s下面就是使用VLC显示的接收到的视频流。 ![]()
4 q* a7 V e" ]. F9 o% P. ]$ S5 B- F/ [, V5 K6 e$ M
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
7 b. v b0 H3 ?* ] |