.. SPDX-FileCopyrightText: 2019-2020 Intel Corporation
..
.. SPDX-License-Identifier: CC-BY-4.0

========================================
Working Directly with VA-API for Linux\*
========================================

|msdk_full_name| takes care of all memory and synchronization related operations in the VA-API.
The application may need to extend |msdk_full_name| functionality by working directly
with the VA-API for Linux\*, for example to implement a customized external allocator.
This section describes basic memory management and synchronization techniques.

To create the VA surface pool, the application should call the vaCreateSurfaces
function:

.. literalinclude:: ../snippets/appnd_e.c
   :language: c++
   :start-after: /*beg1*/
   :end-before: /*end1*/
   :lineno-start: 1

To destroy the surface pool, the application should call the vaDestroySurfaces
function:

.. literalinclude:: ../snippets/appnd_e.c
   :language: c++
   :start-after: /*beg2*/
   :end-before: /*end2*/
   :lineno-start: 1

If the application works with hardware acceleration through |msdk_full_name|, then it can
access surface data immediately after successful completion of
the :cpp:func:`MFXVideoCORE_SyncOperation` call. If the application works with
hardware acceleration directly, then it must check surface status before
accessing data in video memory. This check can be done asynchronously by calling
the vaQuerySurfaceStatus function or synchronously by calling the vaSyncSurface
function.

After successful synchronization, the application can access surface data.
Accessing surface data is performed in two steps:

#. Create VAImage from surface.
#. Map image buffer to system memory.

After mapping, the VAImage.offsets[3] array holds offsets to each color
plain in a mapped buffer and the VAImage.pitches[3] array holds color plain
pitches in bytes. For packed data formats, only first entries in these
arrays are valid. The following example shows how to access data in a NV12 surface:

.. literalinclude:: ../snippets/appnd_e.c
   :language: c++
   :start-after: /*beg3*/
   :end-before: /*end3*/
   :lineno-start: 1


After processing data in a VA surface, the application should release resources
allocated for the mapped buffer and VAImage object:

.. literalinclude:: ../snippets/appnd_e.c
   :language: c++
   :start-after: /*beg4*/
   :end-before: /*end4*/
   :lineno-start: 1

In some cases, in order to retrieve encoded bitstream data from video memory,
the application must use the VABuffer to store data. The following example shows
how to create, use, and destroy the VABuffer:

.. literalinclude:: ../snippets/appnd_e.c
   :language: c++
   :start-after: /*beg5*/
   :end-before: /*end5*/
   :lineno-start: 1

Note that the vaMapBuffer function returns pointers to different objects
depending on the mapped buffer type. The VAImage is a plain data buffer and the
encoded bitstream is a VACodedBufferSegment structure. The application cannot use
VABuffer for synchronization. If encoding, it is recommended to synchronize
using the VA surface as described above.
