Re: [PATCHv5 6/8] vb2: add vb2_find_timestamp()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 19, 2018 at 6:18 PM Jonas Karlman <jonas@xxxxxxxxx> wrote:
>
> On 2018-12-19 08:16, Tomasz Figa wrote:
> > On Wed, Dec 19, 2018 at 4:04 PM Jonas Karlman <jonas@xxxxxxxxx> wrote:
> >> On 2018-12-19 06:10, Tomasz Figa wrote:
> >>> On Thu, Dec 13, 2018 at 9:28 PM Hans Verkuil <hverkuil-cisco@xxxxxxxxx> wrote:
> >>>> On 12/12/18 7:28 PM, Jonas Karlman wrote:
> >>>>> Hi Hans,
> >>>>>
> >>>>> Since this function only return DEQUEUED and DONE buffers,
> >>>>> it cannot be used to find a capture buffer that is both used for
> >>>>> frame output and is part of the frame reference list.
> >>>>> E.g. a bottom field referencing a top field that is already
> >>>>> part of the capture buffer being used for frame output.
> >>>>> (top and bottom field is output in same buffer)
> >>>>>
> >>>>> Jernej Škrabec and me have worked around this issue in cedrus driver by
> >>>>> first checking
> >>>>> the tag/timestamp of the current buffer being used for output frame.
> >>>>>
> >>>>>
> >>>>> // field pictures may reference current capture buffer and is not
> >>>>> returned by vb2_find_tag
> >>>>> if (v4l2_buf->tag == dpb->tag)
> >>>>>     buf_idx = v4l2_buf->vb2_buf.index;
> >>>>> else
> >>>>>     buf_idx = vb2_find_tag(cap_q, dpb->tag, 0);
> >>>>>
> >>>>>
> >>>>> What is the recommended way to handle such case?
> >>>> That is the right approach for this. Interesting corner case, I hadn't
> >>>> considered that.
> >>>>
> >>>>> Could vb2_find_timestamp be extended to allow QUEUED buffers to be returned?
> >>>> No, because only the driver knows what the current buffer is.
> >>>>
> >>>> Buffers that are queued to the driver are in state ACTIVE. But there may be
> >>>> multiple ACTIVE buffers and vb2 doesn't know which buffer is currently
> >>>> being processed by the driver.
> >>>>
> >>>> So this will have to be checked by the driver itself.
> >>> Hold on, it's a perfectly valid use case to have the buffer queued but
> >>> still used as a reference for previously queued buffers, e.g.
> >>>
> >>> QBUF(O, 0)
> >>> QBUF(C, 0)
> >>> REF(ref0, out_timestamp(0))
> >>> QBUF(O, 1)
> >>> QBUF(C, 1)
> >>> REF(ref0, out_timestamp(0))
> >>> QBUF(O, 2)
> >>> QBUF(C, 2)
> >>> <- driver returns O(0) and C(0) here
> >>> <- userspace also knows that any next frame will not reference C(0) anymore
> >>> REF(ref0, out_timestamp(2))
> >>> QBUF(O, 0)
> >>> QBUF(C, 0)
> >>> <- driver may pick O(1)+C(1) or O(2)+C(2) to decode here, but C(0)
> >>> which is the reference for it is already QUEUED.
> >>>
> >>> It's a perfectly fine scenario and optimal from pipelining point of
> >>> view, but if I'm not missing something, the current patch wouldn't
> >>> allow it.
> >> This scenario should never happen with FFmpeg + v4l2request hwaccel +
> >> Kodi userspace.
> >> FFmpeg would only QBUF O(0)+C(0) again after it has been presented on
> >> screen and Kodi have released the last reference to the AVFrame.
> >>
> > I skipped the display in the example indeed, but we can easily add it:
> >
> > QBUF(O, 0)
> > QBUF(C, 0)
> > REF(ref0, out_timestamp(0))
> > QBUF(O, 1)
> > QBUF(C, 1)
> > <- driver returns O(0) and C(0) here
> > <- userspace displays C(0)
> > REF(ref0, out_timestamp(0))
> > QBUF(O, 2)
> > QBUF(C, 2)
> > REF(ref0, out_timestamp(0))
> > QBUF(O, 3)
> > QBUF(C, 3)
> > <- driver returns O(1) and C(1) here
> > <- userspace displays C(1) and reclaims C(0)
> > <- userspace also knows that any next frame will not reference C(0) anymore
> > REF(ref0, out_timestamp(3))
> > QBUF(O, 0)
> > QBUF(C, 0)
> > <- driver may pick O(3)+C(3) to decode here, but C(0)
> > which is the reference for it is already QUEUED.
> >
> > Also the fact that FFmpeg wouldn't trigger such case doesn't mean that
> > it's an invalid one. If I remember correctly, Chromium would actually
> > trigger such, since we attempt to pipeline things as much as possible.
> I still think this may be an invalid use-case or otherwise bad handling
> from userspace. Since userspace knows that C(0) won't be referenced in
> next frame it should also know that it still has two frames queued for
> decoding that references C(0) frame and still have not been returned
> from decoder.
> And if the driver have not started decoding the requests/frames that
> reference C(0) how would it know that it cannot pick the now queued C(0)
> as output for next frame it decodes?

Because the application has queued 2 other CAPTURE buffers before
C(0), but indeed, if we assume that the driver can skip buffers (due
to some errors that I don't see how could happen in any real life
scenario), then that could fail.

> In FFmpeg case we only re-queue the buffer once all frames that
> references that buffer/frame have been output from decoder, I guess the
> main difference is that FFmpeg currently only keep one request in flight
> at the time (wait on request to finish before queue next), this may
> change in future as we continue to improve the v4l2request hwaccel.
>
> Regards,
> Jonas
> >
> >> The v4l2request hwaccel will keep a AVFrame pool with preallocated
> >> frames, AVFrame(x) is keeping userspace ref to O(x)+C(x).
> >> An AVFrame will not be released back to the pool until FFmpeg have
> >> removed it from DPB and Kodi have released it after it no longer is
> >> being presented on screen.
> >>
> >> E.g. an IPBIPB sequense with display order 0 2 1 3 5 4
> >>
> >> FFmpeg: AVFrame(0)
> >> QBUF: O(0)+C(0)
> >> DQBUF: O(0)+C(0)
> >> Kodi: AVFrame(0) returned from FFmpeg and presented on screen
> >> FFmpeg: AVFrame(1) with ref to AVFrame(0)
> >> QBUF: O(1)+C(1) with ref to timestamp(0)
> >> DQBUF: O(1)+C(1)
> >> FFmpeg: AVFrame(2) with ref to AVFrame(0)+AVFrame(1)
> >> QBUF: O(2)+C(2) with ref to timestamp(0)+timestamp(1)
> >> DQBUF: O(2)+C(2)
> >> Kodi: AVFrame(2) returned from FFmpeg and presented on screen
> >> Kodi: AVFrame(0) released (no longer presented)
> >> FFmpeg: AVFrame(3)
> >> QBUF: O(3)+C(3)
> >> DQBUF: O(3)+C(3)
> >> Kodi: AVFrame(1) returned from FFmpeg and presented on screen
> >> Kodi: AVFrame(2) released (no longer presented)
> >> FFmpeg: AVFrame(2) returned to pool
> >> FFmpeg: AVFrame(2) with ref to AVFrame(3)
> >> QBUF: O(2)+C(2) with ref to timestamp(3)
> >> DQBUF: O(2)+C(2)
> >> Kodi: AVFrame(3) returned from FFmpeg and presented on screen
> >> Kodi: AVFrame(1) released (no longer presented)
> >> FFmpeg: AVFrame(0)+AVFrame(1) returned to pool (no longer referenced)
> >> FFmpeg: AVFrame(0) with ref to AVFrame(3)+AVFrame(2)
> >> QBUF: O(0)+C(0) with ref to timestamp(3)+timestamp(2)
> >> DQBUF: O(0)+C(0)
> >> Kodi: AVFrame(0) returned from FFmpeg and presented on screen
> >> Kodi: AVFrame(3) released (no longer presented)
> >> and so on
> >>
> >> Here we can see that O(0)+C(0) will not be QBUF until after FFmpeg +
> >> Kodi have released all userspace refs to AVFrame(0).
> >> Above example was simplified, Kodi will normally keep a few decoded
> >> frames in buffer before being presented and FFmpeg will CREATE_BUF
> >> anytime the pool is empty and new O/C buffers is needed.
> >>
> >> Regards,
> >> Jonas
> >>
> >>> Best regards,
> >>> Tomasz




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux