Part Number: J784S4XEVM
Tool/software:
Hi,
We are using edgeai-gst-plugins in our GStreamer pipeline with OpenVX and v4l2h265enc. We noticed image corruption when v4l2h265enc uses dma-buf import. Our "simplified" pipeline:
gst-launch-1.0 videotestsrc pattern=smpte num-buffers=30 ! video/x-raw, format=NV12, width=1920, height=1080 , framerate=30/1 ! tiovxmultiscaler ! video/x-raw, format=NV12, width=1280, height=720, framerate=30/1 ! OUR_CUSTOM_ELEMENT ! tiovxmemalloc ! video/x-raw,stride-y-align=32 ! v4l2h265enc output-io-mode=5 ! h265parse ! mp4mux ! filesink location=/tmp/out.mp4 sync=false -v
With this pipeline, we see image corruption like shown below:

The corruption pattern is not consistent and changes from frame to frame. It looks like a cache coherency issue. However, the pipeline that doesn't use dma-buf import (output-io-mode=0) works without problems. But this causes video frame copying, which we need to avoid for performance reasons.
gst-launch-1.0 videotestsrc pattern=smpte num-buffers=30 ! video/x-raw, format=NV12, width=1920, height=1080 , framerate=30/1 ! tiovxmultiscaler ! video/x-raw, format=NV12, width=1280, height=720, framerate=30/1 ! OUR_CUSTOM_ELEMENT ! tiovxmemalloc ! video/x-raw,stride-y-align=32 ! v4l2h265enc output-io-mode=0 ! h265parse ! mp4mux ! filesink location=/tmp/out.mp4 sync=false -v

OUR_CUSTOM_ELEMENT: Our custom GStreamer element is very simple in this case. It just gets the vx_image from the buffer, maps it, sets the content, and unmaps it. Below is example code that shows the corruption. In both working and non-working cases, our custom element is the same. The corruption only happens with v4l2h265enc output-io-mode=5.
static GstFlowReturn gst_tiovx_custom_transform_ip(GstBaseTransform *trans, GstBuffer *buf)
{
auto self{trans};
vx_uint32 constexpr OVX_ARRAY_PRIMARY_IMAGE_INDEX{0};
auto meta{reinterpret_cast<GstTIOVXImageMeta *>(gst_buffer_get_meta(buf, GST_TYPE_TIOVX_IMAGE_META_API))};
if (not meta)
{
GST_ERROR("gst_buffer_get_meta failed: GstTIOVXImageMeta missing!");
return GST_FLOW_ERROR;
}
vx_reference fullImageReference{vxGetObjectArrayItem(meta->array, OVX_ARRAY_PRIMARY_IMAGE_INDEX)};
if (not fullImageReference) {
GST_ELEMENT_ERROR(self, STREAM, FAILED, ("vxGetObjectArrayItem failed"), (NULL));
return GST_FLOW_ERROR;
}
const int patchX = 320;
const int patchY = 180;
vx_image fullImage{reinterpret_cast<vx_image>(fullImageReference)};
vx_rectangle_t const rect = {patchX, patchY, patchX*3, patchY*3};
vx_map_id map_id{};
void *ptr{nullptr};
vx_imagepatch_addressing_t addr{};
for (vx_uint32 plane{0}; plane < NV12_PLANE_COUNT; ++plane)
{
if (vxMapImagePatch(fullImage, &rect, plane, &map_id, &addr, &ptr, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X) != VX_SUCCESS)
{
GST_ELEMENT_ERROR(self, STREAM, FAILED, ("vxMapImagePatch failed"), (NULL));
return GST_FLOW_ERROR;
}
auto const yRows{addr.dim_y * addr.scale_y / VX_SCALE_UNITY};
for (vx_uint32 y = 0; y < yRows; y++)
{
vx_uint8 *rowPtr = (vx_uint8 *)ptr + y * addr.stride_y;
auto const xBytes{addr.dim_x * addr.stride_x * addr.scale_x / VX_SCALE_UNITY};
memset(rowPtr, 0,xBytes);
}
if (vxUnmapImagePatch(fullImage, map_id) != VX_SUCCESS)
{
GST_ELEMENT_ERROR(self, STREAM, FAILED, ("vxUnmapImagePatch failed"), (NULL));
return GST_FLOW_ERROR;
}
}
vxReleaseReference (&fullImageReference);
return GST_FLOW_OK;
}Could you please look into this and help fix the issue? Are there any interoperability issues? Is there anything we missed here to keep tiovx and dma buf consistent