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

用全志A40i开发板玩转FFmpeg

[复制链接]

该用户从未签到

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

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. g

2. USB摄像头测试

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

  • 0 ?/ v! r9 u( h
v4l2-ctl --list-devices
; G7 _1 S3 o$ z0 W

可以看到/dev/video0就是我们的USB摄像头,如下图。

使用下面的命令可以看到该摄像头的全部参数:

  •   C3 w- }1 p3 S' i
v4l2-ctl -d  /dev/video0 --all

  • / m$ n( {' r7 w+ z4 i6 A
  • 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 q
    3 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 y
    0 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: G
    8 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 N
    3 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$ A
    6 t1 \, U: C, o) y2 O0 \
    brightness (int)    : min=0 max=255 step=1 default=128value=128               
    " y( H1 E% ~# r
    7 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' W
    5 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可以抓取视频,命令行如下:

  • 3 m9 x. z; }7 r8 ]8 l; }
ffmpeg -f video4linux2 -s 640x480 -pix_fmt yuyv422 -i /dev/video0 out.yuv& K. ]. Z0 g( _* B6 s; m

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


  •   ]7 c. t# X3 i+ j
ffplay -s 640x480 -pix_fmt yuyv422 out.yuv
9 `) @9 X; a9 ?- F# b9 M9 U* I

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

  • 7 |! X' Q  f. Q% b7 K
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视频就行解码测试,命令行如下:

  • 3 `: l% `( H7 S7 y( q
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, W
    3 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' i
    9 @( 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 q
    7 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( l
    2 @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( A
    7 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- a

4.  FFmpeg产生实时视频流

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

  • / e2 Q' j) t) |! h
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文件,如:

  • . H0 v1 A, x+ p0 Z" k1 _
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
  • TA的每日心情
    开心
    2023-1-11 15:38
  • 签到天数: 1 天

    [LV.1]初来乍到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-7-28 20:11 , Processed in 0.140625 second(s), 23 queries , Gzip On.

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

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

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