[Libva] VPP Deinterlacing problem

Steven Toth stoth at kernellabs.com
Wed May 14 08:56:30 PDT 2014


Hi,

I'm looking for some help/guidance on implementing Motion Adaptive
deinterlacing.

Background: I'm working on a libva project that receives raw video
frames (720x480i) from a video4linux SD video capture device, largely
based around the test example projects. Intel IvyBridge platform, i965
driver. Testing / developing with 1.3.0 va and va-intel-driver on
Ubuntu 12.04. The solution works very well, no major issues, I can
encode for long periods of time, very stable code.

However, I was asked to add vpp deinterlacing support. Bob deinterlace
works fine, 30fps encoding is reliable. Motion Adaption isn't working
properly, or - my solution isn't working properly, the encoded output
looks like 15fps with duplicate frames.

Running various h264 analysis tools on the Motion Adaption clip,
stepping through the frames, the 30 fps is actually correct, but every
other frame is a repeat of the previous frame with some very minor
(very very minor) pixel variation. As a result, visually its playing
at 30fps but looks like 15 with odd pixel shimmering effects.

It feels like I've miss-understood the Motion Adaption VPP
configuration, so I'm hoping someone can point me in the right
direction.

My workflow is:
1. I upload the incoming raw video frame into the current source surface.
2. I perform vpp de-interlacing on the current source surface and pass
the prior source surface as single and only forward reference via the
pipeline_param struct. I call vaRenderPicture on the pipeline.
3. I then compress the current surface.
4. Handle the codec buffer of compressed data.
5. Repeat for each incoming raw video frame.

Question: Am I correct in think I should pass the previous source
surface as the single and only forward reference?
(num_forward_references is returned as 1, num_backwards_refs is 0).

Corrective fixes I've tried and failed with:

A. If I pass the current surface as the forward reference, no
deinterlacing takes place and the resulting video has 30fps smooth
playback, I assume the motion adaptive algorithm is trying to adapt
exactly the same frame (or rejects the same surface silently) and the
output video is smooth but interlaced.

B. If I pass the prior source surface -1 (IE current source surface -
2), or use any other value for the forward reference, I start to get
very odd temporal video effects. I assume the Motion Adaption
algorithm is trying to blend two very different non-adjacent temporal
frames and the output is clearly bad.

I'm only using an output_region in the pileline_params, not an input
region, as shown below.

Question: Does Motion Adaption implementation (unlike Bob) require two
distinct source surfaces plus an ADDITIONAL surface for the result?
Perhaps I have my pipeline tuned for Bob (based on GST samples) but
its not reliable for MA?

For completeness, the pipeline func is here:

static int func_deinterlace(VASurfaceID surface, unsigned int w,
unsigned int h, VASurfaceID forward_reference)
{
        VAStatus va_status;

        vaBeginPicture(va_dpy, vpp_context, surface);

        va_status = vaMapBuffer(va_dpy, vpp_pipeline_buf, (void
*)&vpp_pipeline_param);

        CHECK_VASTATUS(va_status, "vaMapBuffer");
        vpp_pipeline_param->surface              = surface;
        vpp_pipeline_param->surface_region       = NULL;
        vpp_pipeline_param->output_region        = &vpp_output_region;
        vpp_pipeline_param->output_background_color = 0;
        vpp_pipeline_param->filter_flags         = VA_FILTER_SCALING_HQ;
        vpp_pipeline_param->filters              = vpp_filter_bufs;
        vpp_pipeline_param->num_filters          = vpp_num_filter_bufs;
        va_status = vaUnmapBuffer(va_dpy, vpp_pipeline_buf);
        CHECK_VASTATUS(va_status, "vaUnmapBuffer");

        // Update reference frames for deinterlacing, if necessary
        vpp_forward_references[0] = forward_reference;
        vpp_pipeline_param->forward_references      = vpp_forward_references;
        vpp_pipeline_param->num_forward_references  =
vpp_num_forward_references;
        vpp_pipeline_param->backward_references     = vpp_backward_references;
        vpp_pipeline_param->num_backward_references =
vpp_num_backward_references;

        // Apply filters
        va_status = vaRenderPicture(va_dpy, vpp_context, &vpp_pipeline_buf, 1);
        CHECK_VASTATUS(va_status, "vaRenderPicture");

        vaEndPicture(va_dpy, vpp_context);
        return 0;

}

Perhaps my overall work simply isn't compatible with MA, IE I should
be loading the 'current incoming pixels' into the 'next source
surface' then passing this next source surface as a forward reference
to the current source?

Feedback welcome.

- Steve

-- 
Steven Toth - Kernel Labs
http://www.kernellabs.com


More information about the Libva mailing list