Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HACK: Route v4l2m2m codecs to rkmpp via ENV variable #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hbiyik
Copy link

@hbiyik hbiyik commented Jan 10, 2024

Screenshot from 2024-01-10 22-27-17
Screenshot from 2024-01-10 22-27-30

So this allows firefox (or any other app user v4l2m2m with ffmpeg, vlc?) to import DRMPrime frames from rkmpp* decoders/encoders directly. So it is kind of 0 copy for the browser which is very cool.

I am not proud of the hack since it is in the middle of ffmpeg code but it works. May be there is cleaner way to do this.

How this works: Firefox has enabled v4l2m2m support for raspberry pi, and it uses ffmpeg to communicate with V4l2 interface, Firefox does not ioctl itself, instead just imports the AVCodec, but initially it executes a binary called v4l2test to query capabilites of a target device. With the env flag FFMPEG_RKMPP_DEC_V4L2M2M=1 ffmpeg routes the v4l2 encoders or decoder to rkmpp variants, and with PR #1 RKMPP codecs provide the DRMPRime frames with HwFramesContext, they do not need to initialized with AVdevice or v4l2device at all. So rkmpp decoders/encoders act as v4l2m2m av codecs.

How to test:

  • Make sure you have a /dev/video[n] device, it does not matter what it is, it is only needed for firefox to be fooled.
  • Compile the ffmpeg from here . Basically it is this repo with PRs merged.
  • Download firefox >=116, make sure it is linked against ffmpeg 6.1. (Normally firefox has a wrapper around different versions of ffmpeg but just dont risk it).
  • Replace the /usr/lib/firefox/v4l2test with below python script. You can do the same with shell as well. It would be a good idea to backup the original v4l2testbinary. This is how we fool the FF that there is actually a v4l2m2m device where there is not
#!/usr/bin/python
import sys

print(f"RKMPP Routing v4l2m2m to mpp with args {sys.argv[1:]}", file=sys.stderr)
print("V4L2_SUPPORTED", file=sys.stdout)
print("TRUE", file=sys.stdout)
print("V4L2_CAPTURE_FMTS", file=sys.stdout)
print("NV12", file=sys.stdout)
print("V4L2_OUTPUT_FMTS", file=sys.stdout)
print("H264 VP9 AV1 HEVC", file=sys.stdout)

Launch the firefox with RDD security sandbox disabled, v4l2 routed to mpp as below.

MOZ_DISABLE_RDD_SANDBOX=1 FFMPEG_RKMPP_DEC_V4L2M2M=1 firefox

Currently only h264 seems to be allowed with that flow, there seems to be VP9 hevc and AV1 or other codecs support but it seems they are blocked somewhere (some config value?). I think this can be tackled somehow and we can have a fully functional browser with HW Decoding / Encoding Enabled.

Above SS is a H264 1080p@60 SS from twitch, there seems to be an offset issue somewhere, see above color displacement, again this can also be tackled.

I am sending this PR not to be merged actually it is quite ugly, but to show the benefits of mainlining, If at least the decoder and encoder of this codec would be mainlined, we could easily PR the firefox to enable other codecs through some configs. Just wanted to show the potential here.

nyanmisaka pushed a commit that referenced this pull request Apr 17, 2024
In close_output(), a dummy frame is created with format NONE passed
to enc_open(), which isn't prepared for it. The NULL pointer
dereference happened at
av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth.

When fgt.graph is NULL, skip fg_output_frame() since there is
nothing to output.

frame #0: 0x0000005555bc34a4 ffmpeg_g`enc_open(opaque=0xb400007efe2db690, frame=0xb400007efe2d9f70) at ffmpeg_enc.c:235:44
frame #1: 0x0000005555bef250 ffmpeg_g`enc_open(sch=0xb400007dde2d4090, enc=0xb400007e4e2daad0, frame=0xb400007efe2d9f70) at ffmpeg_sched.c:1462:11
frame #2: 0x0000005555bee094 ffmpeg_g`send_to_enc(sch=0xb400007dde2d4090, enc=0xb400007e4e2daad0, frame=0xb400007efe2d9f70) at ffmpeg_sched.c:1571:19
frame #3: 0x0000005555bee01c ffmpeg_g`sch_filter_send(sch=0xb400007dde2d4090, fg_idx=0, out_idx=0, frame=0xb400007efe2d9f70) at ffmpeg_sched.c:2154:12
frame #4: 0x0000005555bcf124 ffmpeg_g`close_output(ofp=0xb400007e4e2d85b0, fgt=0x0000007d1790eb08) at ffmpeg_filter.c:2225:15
frame #5: 0x0000005555bcb000 ffmpeg_g`fg_output_frame(ofp=0xb400007e4e2d85b0, fgt=0x0000007d1790eb08, frame=0x0000000000000000) at ffmpeg_filter.c:2317:16
frame #6: 0x0000005555bc7e48 ffmpeg_g`filter_thread(arg=0xb400007eae2ce7a0) at ffmpeg_filter.c:2836:15
frame #7: 0x0000005555bee568 ffmpeg_g`task_wrapper(arg=0xb400007d8e2db478) at ffmpeg_sched.c:2200:21

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants