[unofficial] LibreElec (Nexus) 11.0.1 for RPi3

  • Hello all,

    This is an unofficial test build of LibreELEC 11.0.1 with RPi3 HW acceleration support.

    Kernel

    Linux 5.10.110 is preferred in this build, because it has decent support for Legacy DispmanX and MMAL support. Kernel is 64-bit but the userspace is 32-bit for compatibility reasons. It is based on official RPi kernel releases on github.

    Windowing System

    DispmanX support is back on this test build (yay!) to achieve closer rendering performance on LE9.x releases. It's implemented to Kodi from scratch and it is not based on @popcornmix's previous work. I didn't test it yet, but DispmanX based VNC servers should work out of the box.

    Audio Improvements

    I did some minor changes to bcm2835_snd kernel module. Now it supports S/PDIF passthrough over HDMI (on my configuration at least). There is no need to do extra changes in the Kodi code to provide support.

    Video Improvements

    All video rendering should be done by MMAL, hopefully. There are two layers for rendering. One for the MMAL renderer and one for the DispmanX EGL renderer.

    Supported Codecs

    H264, MP4V, H263, MJPEG, VP6, VP8, THEO, MP2V, VC1:

    -1080p HW accelerated decoding and rendering support through MMAL.

    -Unfortunately you'll need license for MP2V and VC1 as always.

    HEVC:

    -720p QPU accelerated decoding, HW accelerated rendering support through MMAL.

    -1080p decoding works if you have low bitrate streams.

    -10-bit streams are not supported yet. (hangs if you try to play.)

    AV1:

    -720p SW decoding with libdav1d. Rendering is HW accelerated through MMAL.

    -1080p may be possible, please test it.

    VP9:

    -1080p multi-threaded SW decoding with ffmpeg. Rendering is done by MMAL.

    Known Bugs/Limitations

    -Only HDMI output works. Composite video out and LCD's are not supported yet.

    -Deinterlacing is not supported yet.

    -3D streams are not supported.

    -CEC may be broken. (I don't have any supported display to test it.) (works)

    Planned Features

    -HW accelerated texture decoding.

    -10-bit HEVC decoding. (done)

    -Deinterlacing.

    -SDTV and LCD support.

    Changes in 11.0.1.2

    -Appled a workaround to prevent crash at the end of stream.

    Download Links

    Latest Release: LibreELEC 11.0.1.2

    Previous Releases

    Edited 5 times, last by ardaoktay (April 13, 2023 at 2:50 PM).

  • This is an unofficial test build of LibreELEC 11.0.1 with RPi3 HW acceleration support.

    Interesting.

    You should include a link to the source you have built from (both to give users an idea of what they are running, and to comply with the GPL2 licence).

  • Interesting.

    You should include a link to the source you have built from (both to give users an idea of what they are running, and to comply with the GPL2 licence).

    Thank you for your kind warning popcornmix, you are absolutely right. I've uploaded the code on GitHub.

    Kodi: https://github.com/radakayot/xbmc-rpi3

    FFmpeg: https://github.com/radakayot/FFmpeg-xbmc-rpi3

    LibreELEC: https://github.com/radakayot/LibreELEC.tv

    I could create pull requests for all, if it's appropriate.

    Since I've caught your attention, do you have any recommendations for "mmal_port_disable" and "mmal_port_flush" infinite lock-ups? :)

  • I could create pull requests for all, if it's appropriate.

    No need. A fork is fine for a custom release like this. A tag (of each tree) for any released binary would be useful for associating source code with binary.

    Since I've caught your attention, do you have any recommendations for "mmal_port_disable" and "mmal_port_flush" infinite lock-ups? :)

    I'm afraid these sort of issues are hard to debug.

    The mmal buffers that are submitted and retrieved from mmal calls include linked list pointers.

    If you ever do anything wrong with one of these, like submitting it twice, freeing it when it's still in use etc, you'll likely get a subsequent crash or hang.

    Do you get the same behaviour on a genuine LE9 image? If not, then what are the differences?

  • No need. A fork is fine for a custom release like this. A tag (of each tree) for any released binary would be useful for associating source code with binary.

    Sure, I've just did. So, is it okay to release new versions of LibreELEC as a fork? I'm planning to maintain this fork as long as possible.

    Do you get the same behaviour on a genuine LE9 image? If not, then what are the differences?

    As I've said, it's not based on your implementation of LE9. I didn't use any OMX components to render. I also didn't use port connections between decoder and renderer. But video_render component crashes on some occasions even if input port buffer release callback happens. I tried to flush renderer queue on input format change. I think the problem happens because there is always a single buffer left in the renderer, and I can't tell if it's used by firmware or not before disabling/flushing the port.

    Is there any reliable way to determine the buffer is no longer needed by the renderer component?

  • If you are going to release/maintain images please set BUILDER_NAME="ardaoktay" in .libreelec/options so we can track the image in active-install stats. This means you can also ask occasionally to discover how many (or few) users you are entertaining :)

  • If you are going to release/maintain images please set BUILDER_NAME="ardaoktay" in .libreelec/options so we can track the image in active-install stats.

    I definitely will chewitt, thanks for the tip.

    This means you can also ask occasionally to discover how many (or few) users you are entertaining :)

    Lol, probably a few because device is kind of outdated. But this device definitely deserves more love.

    Besides that, I would love to hear your thoughts about versioning. I want to go as much as parallel with official LibreELEC releases. If I have patches between releases, is it okay to use semantic versioning like "11.0.1-u1"?

  • As I've said, it's not based on your implementation of LE9. I didn't use any OMX components to render. I also didn't use port connections between decoder and renderer. But video_render component crashes on some occasions even if input port buffer release callback happens. I tried to flush renderer queue on input format change. I think the problem happens because there is always a single buffer left in the renderer, and I can't tell if it's used by firmware or not before disabling/flushing the port.

    Is there any reliable way to determine the buffer is no longer needed by the renderer component?

    Just to clarify LE9 has two independent HW acceleration methods, MMAL and openmax.

    The (default) MMAL decoder uses the MMAL renderer and doesn't use openmax in any way.

    MMAL works with buffers that you submit (mmal_port_send_buffer) and receive (through callback function given to mmal_port_enable).

    The rule is once you've submitted a buffer it is owned by the firmware until it is returned in the callback.

  • Just to clarify LE9 has two independent HW acceleration methods, MMAL and openmax.

    The (default) MMAL decoder uses the MMAL renderer and doesn't use openmax in any way.

    Oh, I see. Sorry about the confusion on my side. Thanks again for your all hard work on LE9 btw, it really inspired me as you can see from the sources.

    MMAL works with buffers that you submit (mmal_port_send_buffer) and receive (through callback function given to mmal_port_enable).

    The rule is once you've submitted a buffer it is owned by the firmware until it is returned in the callback.

    While using decoder and isp component, that rule works perfectly. But as far as I can observe, the renderer component always holds single a buffer in the queue. When the stream stops, I stop sending input buffers to renderer and I disable the input port. But in rare occasions, mmal_port_disable never returns and locks the thread. Same happens on mmal_port_flush too. I'm suspecting the crash happens when renderer is accessing that last buffer while I try flush or disable the port. Is there any way to empty the rendering queue or at least a way to ensure it is safe to disable renderer input port?

    I'm not sure if it's related or not, but the undesired result that I'm observing similar to this issue.

  • I'm afraid MMAL is a bit of a black box to me - I've not worked on the internals.

    I've just used it a client, and like you, have had a number of hard to debug issues.

    One thing you need to be careful of is the MMAL callbacks are run from the normal MMAL processing thread.

    If you block in the callback you will stop any further progress.

    So callbacks should never block. If you need to do blocking work, then you need a separate task and just signal it from the callback.

    I'm a little concerned that ProcessOutputCallback may do that.

    Attaching gdb after things have locked up and looking at the threads that are blocked may be illuminating.

  • I'm afraid MMAL is a bit of a black box to me - I've not worked on the internals.

    I've just used it a client, and like you, have had a number of hard to debug issues.

    I see, same here :)

    One thing you need to be careful of is the MMAL callbacks are run from the normal MMAL processing thread.

    If you block in the callback you will stop any further progress.

    Actually that piece of information is really useful. So, I could try to abuse callbacks to slow down or accelerate internal decoding process on demand.

    I'm a little concerned that ProcessOutputCallback may do that.

    Interestingly enough, that part runs without hiccups. I was worried about making recursive mmal api calls from a mmal callback, but in that situation it works fine.

    Attaching gdb after things have locked up and looking at the threads that are blocked may be illuminating.

    I did, it looks like vc.ril.video_renderer thread waiting for a mutex. If I unlock the mutex manually and continue, I couldn't create any new mmal components until the next reboot.

    Edit: Btw, are callbacks blocks the whole component, or separated by ports on it?