moonlight-stream / moonlight-embedded

Gamestream client for embedded systems
https://github.com/moonlight-stream/moonlight-embedded/wiki
GNU General Public License v3.0
1.5k stars 326 forks source link

Update Amlogic decoder #860

Closed TheChoconut closed 1 year ago

TheChoconut commented 1 year ago

Description These commits allow the Amlogic decoder to work on boxes running CoreELEC. It has only been tested on the linux kernel 4.9.269.

[lazy load libamcodec] It is required as libamcodec.so provided by CoreELEC has unresolved symbols. Since we are only using the libamcodec to provide VPU support and other libraries are not used, this fixes the build on CoreELEC.

[update amlogic decoder] New parameters added as they are required for the latest version of proprietary libamcodec. This commit might have to be modified since not everyone has the same header files...

  1. It is creating a frame_buffer as a temporary buffer so that the whole frame can be sent to the decoder at once.

All the other solutions may work but at some point the frames get rejected with EBUSY, causing latency, stuttering and variations in speed. I don't know if we can somehow get the buffer list to have more data at once, but increasing the packet size has not fixed this.

[set disable_video to false on startup]

  1. Set disable_video to false on startup. Kodi in CoreELEC sets this value to true when video is not playing so the screen will be black without this. It can be fixed by running prescripts but I feel like this would be okay to do in moonlight too.

  2. Modifies aml_submit_decode_unit so it first copies all the buffer data into frame_buffer and is then provided to libamcodec.

I recommend to get this tested on more devices before being pushed to upstream. People on CoreELEC seem to have problems with this version, although in my testing I have identified that ALSA audio handling seems to be breaking the video thread. As audio gets delayed, underruns occur. This further causes the timings to break and either moonlight blocks the frames or the video thread can't keep up.

Furthermore, it is important to test this with multiple boards and configurations of VFM maps, as it seems that /sys/class/vfm/map breaks things.

cgutman commented 1 year ago

a48d8ad6befd154700cd21f695b1a2a5d6a99fd2 and 4ff088223b37b0ca077805dff061c3b766c1d6c3 look safe to merge as is. Would you mind if I cherry-picked those into master?

New parameters added as they are required for the latest version of proprietary libamcodec. This commit might have to be modified since not everyone has the same header files...

I noticed that codecParam.dec_mode = STREAM_TYPE_FRAME doesn't compile for me on Vero, but codecParam.decoder_type = DECODER_TYPE_FRAME_MODE does.

What's the deal with all these versions of libamcodec? Is one newer than the other or all they all just incompatible forks of each other?

It is creating a frame_buffer as a temporary buffer so that the whole frame can be sent to the decoder at once.

Yeah, this approach seems fine. It's what pretty much all of the other decoders do also.

I recommend to get this tested on more devices before being pushed to upstream. People on CoreELEC seem to have problems with this version, although in my testing I have identified that ALSA audio handling seems to be breaking the video thread. As audio gets delayed, underruns occur. This further causes the timings to break and either moonlight blocks the frames or the video thread can't keep up.

Is this related to codec_checkin_pts()? Maybe it's some sort of A/V sync thing?

Furthermore, it is important to test this with multiple boards and configurations of VFM maps, as it seems that /sys/class/vfm/map breaks things.

Yeah I saw you were always spawning the display thread in your fork regardless of whether amlvideo was present in the VFM map.

What does cat /sys/class/vfm/map output on your Amlogic devices?

TheChoconut commented 1 year ago

Not sure how these libamcodec versions differ. Mostly this has been trial and error...

The output of cat /sys/class/vfm/map on my device is:

[00]  default { decoder(0) amvideo}
[01]  dvblpath { dvbldec(0) amvideo}
[02]  dvelpath { dveldec(0) dvel}
[03]  dvhdmiin { dv_vdin(0) amvideo}
[04]  vdec-map-0 { vdec.h265.00(1) amlvideo(1) ppmgr(1) deinterlace(1) amvideo}

provider list:
   vdec.h265.00
   amlvideo
   ppmgr
   deinterlace

receiver list:
   video_render.0
   video_render.1
   amvideo
   videopip
   deinterlace
   ppmgr
   amlvideo
   aml_video.1