This FFmpeg fork contains specific modifications to support hardware acceleration on Samsung A40 devices using the Multi-Format Codec (MFC) subsystem.
Main problem is that the V4L2 driver is non standard compliant, meaning ffmpeg will not work out of the box.
Compile on samsung galaxy a40 flashed with postmarket os. Run ./configure.sh followed by make.
Events from the V4L2 MFC driver aren't properly emitted, requiring the use of non-blocking I/O with busy loops to poll for encoder/decoder state changes instead of relying on select/poll operations. Otherwise it would just block waiting for events on the queues.
Switched from memory mapping (MMAP) to DMA-BUF for buffer management because the encoder capture queue doesn't support MMAP buffers operations.
The MFC driver does suport MMAP for the encoder, but the decoder capture queue only supports DMA-BUF. In this fork we switched to DMA-BUF entirely.
Implemented ION (Ion Memory Manager) for CMA (Contiguous Memory Allocator) buffer allocation, providing a significant boost in fps performance for video processing operations. This improved fps by ~20%, I guess due to the IOMMU overhead for non continious memory allocations.
Zero-copy mode between encoder and decoder was not implemented as it didn't provide performance benefits in this specific hardware configuration. I ran an experiment by simply not doing the memcpy between decoder capture and encoder output, which did not increased fps.
Running encoder and decoder separately achieves the promised 30fps, but when operated together, performance drops to ~20fps, indicating shared hardware resources or bandwidth limitations in the MFC subsystem.
Contains workarounds for a kernel bug where buffer offset values overflow from int32, reset to 0, causing MMAP operations to fail. When using MMAP for encoding, one needs to manually set the offset when mmaping the bufs and not use the value returned from the kernel driver.
Added injection of fake IDR (Instantaneous Decoder Refresh) frames that are subsequently skipped to ensure Chrome browser compatibility. While MP4 container metadata marks I-frames as keyframes, Chrome requires H.264 bitstream-level IDR marking. Firefox plays these fine, but Chrome will refuse if to play the video if we start from a later point in time. This makes sense because this hardware encoder only seems to insert a single IDR frame at the very beginning.
For HLS streaming, subsequent segments will thus not contain a true IDR frame, only an I frame which is tagged as IDR in the container. Chrome will then complain with:
Chrome error:
ISO-BMFF container metadata for video frame indicates that the frame is a keyframe, but the video frame contents indicate the opposite.
The workaround is to insert black IDR frames with zero duration and skip flags, repurposing the annexb bitstream filter for this functionality.
That will give the Chrome video decoder a proper IDR frame to start with the stream in some non-start segment. This is pretty hacky and ideally we could just get the hardware encoder to produce proper IDR frames - the I frames seem to be independent enough anyway, as they play well even if earlier frames are not present.