<div dir="ltr">Hi,<div><br><div>This issue is tracked here <a href="https://bugs.freedesktop.org/show_bug.cgi?id=98285" target="_blank">https://bugs.freedesktop.org/s<wbr>how_bug.cgi?id=98285</a></div><div>This is due to a limitation in libva API which only supports 1 FD per VaSurface.</div><div>It is enough for intel-driver because NV12 is only 1 bo. But in nouveau driver, NV12 is 2 separates bo (omitting the interlaced pb).</div><div><br></div><div><div>Note that this libva API limitation is also a problem for AMD hardware because NV12 is also 2 non-contiguous bo (see function 'si_video_buffer_create' and 'nouveau_vp3_video_buffer_crea<wbr>te' mesa source). I do not know if this is HW requirement, or if using one contiguous bo with offset handling would work. So currently there is 2 independent calls to pipe->screen->resource_crea<wbr>te. But maybe it would also work if the second resource would somehow has the same underlying memory but with an offset.</div></div><div><br></div><div>The workaround for now is to convert it to RGB: (the following pipeline works on both nvidia and amd hardware)</div><div><br></div><div>GST_GL_PLATFORM=egl GST_GL_API=gles2 gst-launch-1.0 filesrc location=test.mp4 ! qtdemux ! h264parse ! vaapih264dec ! vaapipostproc ! "video/x-raw(memory:DMABuf), format=<b>RGBA</b>" ! glimagesink</div><div><br></div><div>In the pipeline above, vaapipostproc will receive a NV12 vaSurface as input and will convert it to a RGBA vaSurface. And export it as 1 dmabuf FD. Which will be imported by glimagesink by using eglCreateImage. This is not a full zero-copy, but at least this is zero-cpu-copy, the conversion being done on the gpu. </div><div><br></div><div>Cheers</div><div>Julien</div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 16 August 2017 at 03:06, Ilia Mirkin <span dir="ltr"><<a href="mailto:imirkin@alum.mit.edu" target="_blank">imirkin@alum.mit.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">[adding Julien, who did the nouveau va-api integration.]<br>
<span class=""><br>
On Tue, Aug 15, 2017 at 9:59 AM, Philipp Kerling <<a href="mailto:pkerling@casix.org">pkerling@casix.org</a>> wrote:<br>
> Hi,<br>
><br>
> I recently noticed that hardware video decoding with the nouveau driver<br>
> and libva does not play nicely with Wayland and decided to dig a bit.<br>
><br>
> To use libva in conjunction with Wayland in EGL applications, you<br>
> usually export the surface dmabuf via vaDeriveImage &<br>
> vaAcquireBufferHandle and then import it in EGL via eglCreateImageKHR &<br>
> EGL_LINUX_DMA_BUF_EXT.<br>
> However, this does not work with nouveau.<br>
><br>
> The first problem I could identify is that nouveau uses NV12 as buffer<br>
> format and mesa vaDeriveImage cannot handle that (see FourCCs handled<br>
> in vlVaDeriveImage). It seems to be easy to add though (just have to<br>
> set num_planes/offset etc. correctly), and I did so locally. Also,<br>
> nouveau always sets the interlaced flag on the buffer, which<br>
> vlVaDeriveImage also errors out on. Not sure why it does that and what<br>
> to do with that currently, I just removed the check locally.<br>
<br>
</span>The hw decoder produces an interlaced NV12 image -- i.e. the Y plane<br>
is 2 images and the UV plane is 2 images, below one another. This is<br>
in firmware written in falcon (VP3+) or xtensa (VP2) microcode by<br>
NVIDIA. There is no open-source implementation, and thus would be<br>
tricky to change. It's possible that this firmware supports other<br>
output formats as well ... but we're not presently aware of it.<br>
Presumably the 10-bit decoding is done *somehow*.<br>
<span class=""><br>
><br>
> Then I hit another problem, which is that NV12 uses two planes and thus<br>
> has an offset into the buffer for the second plane, but nouveau cannot<br>
> handle offsets in eglCreateImageKHR (see nouveau_screen_bo_from_handle<br>
> which has a check for this).<br>
<br>
</span>The VP2-era hardware decoder (G84..G200, minus G98) wants a single<br>
output buffer - you enter it in as a single base address and then an<br>
offset to the UV plane. It's a 32-bit offset but a 40-bit VA space.<br>
Later decoder generations (VP3+) have a separate address for both Y<br>
and UV planes. Actually looking over the VP2 logic (which I'm sad to<br>
say I wrote many years ago), it *might* be possible to have separate<br>
buffers for the final output image (in the second VP step).<br>
<span class=""><br>
> Is there an easy/obvious way to add handling for the offset parameter<br>
> in nouveau_screen.c? This might be all that is currently breaking hwdec<br>
> on nouveau+Wayland, but I couldn't test it of course, so there might<br>
> still be other problems lurking.<br>
<br>
</span>Well, strictly speaking this should be easy - while nouveau_bo has no<br>
offset, nv04_resource does - specifically things tend to use<br>
nv04_resource->address. I believe this offset stuff was added<br>
recently, and I don't know much about EGL or Wayland or ... well a lot<br>
of the new hotness. So e.g. in nv50_miptree_from_handle you could set<br>
the mt->base.address = bo->offset + whandle->offset; I wonder if the<br>
tiling stuff will be an issue -- the decoder can get *very* picking<br>
about tiling -- somehow you'll have to ensure that the images are<br>
allocated with proper tiling flags set -- see how nvc0_miptree_create<br>
calls nvc0_miptree_init_layout_<wbr>video, which sets tile_mode to 0x10.<br>
That's not by coincidence.<br>
<br>
BTW, note that you can't use a decoder in one thread and GL commands<br>
in another thread. This will cause death in nouveau. Also note that<br>
there are known (but unfixed) artifacts when decoding some H.264<br>
videos.<br>
<br>
Feel free to join us in #nouveau on <a href="http://irc.freenode.net" rel="noreferrer" target="_blank">irc.freenode.net</a>.<br>
<br>
Cheers,<br>
<br>
  -ilia<br>
</blockquote></div><br></div>