-
Notifications
You must be signed in to change notification settings - Fork 5.3k
bcm2835-v4l2-codec: Fix alignment of frames for deinterlace #5176
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
base: rpi-5.15.y
Are you sure you want to change the base?
bcm2835-v4l2-codec: Fix alignment of frames for deinterlace #5176
Conversation
The deinterlacer requires a height alignment of 16 so add it to the list of roles that get fixed up. Signed-off-by: John Cox <[email protected]>
|
How is this failing without the change? I have a suspicion that ffmpeg produces non-16 aligned height images and we are currently deinterlacing those fine, and this change may stop that working. But I'd need to check to be sure. |
|
I'll let John confirm, but he was saying that setting 1920x1080 was failing as V4L2 accepted it at S_FMT, but the firmware then rejected it. Checking the firmware, it does claim to only need an alignment to a multiple of 2 lines, so I guess something else is at play. So the slice height must either be a multiple of 16, or greater than the aligned up full height. |
|
The commit you reference says: So I think this commit is breaking this case. |
|
I found the issue as I'd built an ISP resize component and the easiest way was to common it with the deinterlace code (apart from some extra parameter setting for the ISP the code is all but identical for the two operations). This (fairly obviously) required me to have the ability to set different sizes on src & dest. The old code copied src geometry to dest geometry, the new simply sets the desired dest size and relies on S_FMT to fix up anything that is wrong (which, as I understand it, is the V4L2 way - and makes sense too). Src is set before dest so if the filter needs identical src & dest then it has the opportunity to enforce that. The S_FMTs both work - and so do the S_SELECTIONs which define the actual active area within the frame geometry. The call that fails is the REQBUFS on the dest (which I do before src but I can't see why that would matter). It fails with an EINVAL because (according to the V4L2 logging) the firmware rejects the src port format set. This shouldn't happen. S_FMT should not be able to create a format that won't be accepted by the firmware. I've tested the above fix against my new code and it does work. |
REQBUFS calls |
I think that caters for your case, and still allows FFmpeg's |
|
Ummm... I may be being thick but surely if f->fmt.pix_mp.height is a multiple of 16 then ALIGN(f->fmt.pix_mp.height, 16) == f->fmt.pix_mp.height and that is the only case where the "if" will not be true and so the above code is equivalent to doing the ALIGN unconditionally? |
|
Ah, I want to be looking at the selection height, not the buffer height. Except that of course comes in through a totally different API (s_selection). How to rationalise that isn't clear (you could trim down the selection during s_selection, but that then leaves a very odd situation). |
|
That is, at best, tricky. S_FMT must, I think, happen before S_SELECTION and must return the numbers that are actually going to be used. |
Indeed. |
|
If you do S_FMT without S_SELECTION you will expect the passed width/height to be valid. S_SELECTION is not required before REQBUFS. |
Indeed. |
|
Going back to the original thing. I am not aware of any general requirement that ffmpeg frames are over allocated as align(height,16)+2, we certainly don't do that on h/w decode for either stateful or stateless. Some s/w decoders do that on their dest frames 'cos it is convenient to have a line of edge replication for inter prediction (I did that ages ago). The current deinterlacer doesn't do it either. So if all of that works then I think we are inventing problems. |
|
See https://ffmpeg.org/doxygen/trunk/libavcodec_2utils_8c_source.html#l00141 |
|
The other thing that is worth mentioning is that as it stands v4l2m2m deinterlace & scale are drmprime only src & dest so their interaction with s/w components is quite limited. (deinterlace advertised s/w YUV420 support but didn't actually do it). |
|
That function is for returning appropriate buffer sizes s.t. that an external allocator can feed the correct sizes into an existing s/w decoders which often require greater allocs - they don't prescribe the sizes of anything else. |
|
I've just tested standard rpios bullseye, with kodi installed through apt and hw decode disabled. Note when playing successfully, kodi reports:
|
|
OK fair enough - how does decoder frame alloc occur in this scenario? I'm pretty sure that the deinterlace doesn't have an actual s/w frame import and requires a drmprime frame. |
|
We use I don't believe I specify or care about the geometry of the deinterlace output - from kodi's view that is just a handle that just gets displayed. |
|
Well I don't know what the correct answer is. The current code is wrong - you shouldn't be able to have a successful S_FMT that causes REQBUFS to fail. Having selection limits that are less than S_FMT width/height is definitely unexpected even if legal. |
|
The only fix to avoid REQBUFS failing is to "correct" the selection in S_SELECTION. |
The deinterlacer requires a height alignment of 16 so add it to the list of roles that get fixed up.
Signed-off-by: John Cox [email protected]