anpaza / afrd

Auto Frame Rate Daemon for 64-bit AMLogic CPUs
GNU General Public License v3.0
35 stars 7 forks source link

Auto Frame Rate Daemon (AFRD)

This is a Linux daemon for AMLogic SoC based boxes to switch screen framerate to most suitable during video play. The daemon uses kernel uevent-based notifications, available in AMLogic 3.14 kernels from summer 2017. Earlier kernels won't emit notifications at the start and end of playing video, so the daemon won't work.

Unfortunately, this uevent is gone from kernel 4.9 (used for Android 7 and 8), so afrd can't use frame rate notifications on newer kernels. Instead, afrd will use video decoder notifications that are emitted at the start and end of playback.

The daemon can be linked either with BioniC (for Android) or with glibc (for plain Linux OSes).

Versions up to 0.1.* use kernel uevent notifications emmited by AMLogic kernels starting from summer 2017, used in some Android 6.0 and 7.0 firmwares. Unfortunately, somewhere around start of 2018 AMLogic broke its own code and since then these uevents are not generated (altough part of the respective code is still in kernel). Here are a example FRAME_RATE_HINT uevent generated when a 29.976 fps movie is started:

change@/devices/virtual/tv/tv
    ACTION=change
    DEVPATH=/devices/virtual/tv/tv
    SUBSYSTEM=tv
    FRAME_RATE_HINT=3203
    MAJOR=254
    MINOR=0
    DEVNAME=tv
    SEQNUM=2787

and when the movie stops:

change@/devices/virtual/tv/tv
    ACTION=change
    DEVPATH=/devices/virtual/tv/tv
    SUBSYSTEM=tv
    FRAME_RATE_END_HINT
    MAJOR=254
    MINOR=0
    DEVNAME=tv
    SEQNUM=2788

Since version 0.2.0 afrd supports detecting movie framerate by catching uevent's generated when a hardware decoder is started or stopped. These events are present on both older and newer kernels, thus afrd can work with almost every AMLogic kernel out there:

add@/devices/vdec.25/amvdec_h264.0
    ACTION=add
    DEVPATH=/devices/vdec.25/amvdec_h264.0
    SUBSYSTEM=platform
    MODALIAS=platform:amvdec_h264
    SEQNUM=2786

remove@/devices/vdec.25/amvdec_h264.0
    ACTION=remove
    DEVPATH=/devices/vdec.25/amvdec_h264.0
    SUBSYSTEM=platform
    MODALIAS=platform:amvdec_h264
    SEQNUM=2789

These events do not contain the movie frame rate, thus in addition to these events afrd has to query the video decoder driver, its status is available from /sys/class/vdec/vdec_status:

vdec channel 0 statistics:
  device name : amvdec_h264
  frame width : 1920
 frame height : 1080
   frame rate : 24 fps
     bit rate : 856 kbps
       status : 63
    frame dur : 4000
   frame data : 19 KB
  frame count : 230
   drop count : 0
fra err count : 0
 hw err count : 0
   total data : 1197 KB

The "frame dur" field is used if not 0 (the actual frame rate is 96000/frame_dur), and "frame rate" field is used otherwise (with 23 fps being 23.976, 29 being 29.970 and 59 being 59.94 fps).

Configuration file

AFRD uses a simple configuration file that can be used to customize its behavior. The file contains either comment lines, starting with the '#' character, or key=value pairs.

If a key contains several values, list elements are always separated by white spaces.

Every 5 seconds afrd will check the last-modified timestamp on the loaded config file. If config file is changed, afrd reloads it.

The following parameters are recognized by AFRD:

AFRd API

AFRd has an API which can be used to cooperate with video player software in order to get a better user experience. In particular, software may tell afrd in advance what is the frame rate of the video, so that afrd doesn't have to guess it.

The API is available by sending UDP datagrams to address 127.0.0.1, port 50505. The protocol is purely textual, each datagram may contain multiple commands, each command on a separate line.

The format of each line is:

<command> [<arguments> ...]

The following commands are available:

To test the API you may use the 'nc' tool that is part of busybox, which can be easily installed if you didn't already. Example dialog with afrd, lines starting with '>' are outgoing, others are incoming:

1|u211:/ # nc -u 127.0.0.1 50505
>help
frame_rate_hint <fr>
    tell afrd the video starting in <1.0 seconds will use <fr>/1000 frames per second (e.g. 23976 = 23.976 fps)
refresh_rate <rr>
    tell afrd to set display refresh rate as close to <rr>/1000 Hz as possible, no arg to restore original rate
color_space <cs>
    override colorspace, empty arg tor restore default behavior
status
    get current afrd status
reconf
    tell afrd to reload configuration file as soon as possible

>status
enabled:1
active:0
blackened:0
version:0.2.5
build:2019-03-31 21:17:38
current hz:50000
original hz:50000

>refresh_rate 59940

>status
enabled:1
active:1
blackened:0
version:0.2.5
build:2019-03-31 21:17:38
current hz:59941
original hz:50000

>refresh_rate

>status
enabled:1
active:0
blackened:0
version:0.2.5
build:2019-03-31 21:17:38
current hz:50000
original hz:50000

>color_space rgb,8bit,full
>refresh_rate 50000

Note how afrd remembers original refresh rate when you switch it for the first time, and how it restores refresh rate when the command 'refresh_rate' without parameters is issued.