找回密码
 注册
关于网站域名变更的通知
查看: 498|回复: 1
打印 上一主题 下一主题

用全志A40i开发板玩转FFmpeg

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-12-17 09:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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 v

2. USB摄像头测试

OKA40i-C开发板接口丰富,它支持USB摄像头、CMOS-OV5640摄像头、模拟摄像头。把USB摄像头插入开发板,然后使用


  • 5 R( e* R: c* ~  x/ N
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
  • ' `# B8 i2 K$ x) v( C5 @
  • & 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  G
    2 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) ?( h
    4 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  l
    8 |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# h
    1 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  f
    2 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可以抓取视频,命令行如下:

  • : B  D+ K, M4 R0 t* @) k
ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv
/ u5 v8 N3 P& O0 y1 W4 m

使用Windows版本的ffplay可以正常播放抓取的视频,命令行如下:

  • ) r" t1 I$ U* M
ffplay -s 640x480 -pix_fmt yuyv422 out.yuv! Q7 H0 y4 c; i- ~+ L- \! n7 X

上面保存的是YUV格式的原始视频,如果要保存压缩视频,可以用下面的命令行:

  • 1 h! ?" P" t+ ]# Y* Z
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' O

3. FFmpeg性能测试

FFmpeg有个benchmark参数可以方便进行性能测试。我们对A40i开发板自带的一个MP4视频就行解码测试,命令行如下:


  • ; A3 ]. z2 _9 ~* a
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 p
    3 ^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 S

4.  FFmpeg产生实时视频流

FFmpeg可以支持实时视频流的发送和接收,从而可以把OKA40i-C开发板上的视频实时发送到PC上,由PC上的软件实时接收并显示。我们可以使用下面的命令将OKA40i-C开发板上的一个MP4转换为RTP码流发送的PC上:

  • 3 U; [5 B' S* }" _
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文件,如:

  • 1 ?0 @( C5 k% p
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
  • TA的每日心情
    开心
    2023-1-11 15:38
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2022-12-19 08:38 | 只看该作者
    步骤很详细,小白式操作
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-23 14:38 , Processed in 0.140625 second(s), 24 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表