My workflow is a C++ application utilizing OpenCV and other libraries that will:
- Decode several rtsp streams
- Perform inference and other processing
- Draw metadata on frames
- Encode each stream to h264 using OpenCV + gstreamer with omxh264enc
Here is the gstreamer pipeline I am using:
appsrc ! video/x-raw, format=(string)BGR ! videoconvert
! video/x-raw, format=(string)I420, framerate=(fraction)15/1
! omxh264enc preset-level=3 profile=8 insert-sps-pps=1 qp-range=8,24:8,24:8,24
! video/x-h264,level=(string)5.2,stream-format=byte-stream
! h264parse ! qtmux ! filesink location=file.mp4
I’m not sure if the qp-range is optimal, but it works and seems to produce sufficient quality vs size. I’m not familiar with h264 quantization parameters.
To reproduce the error I isolated the encoding portion of my processing pipeline so that it will:
- Load a 30 second video
- Create 4 or 8 encoder objects
- Push frames into each encoder in a loop to create 30 second recordings in a loop
After some time, usually a few minutes one of the encoders throws the following error:
Framerate set to : 15 at NvxVideoEncoderSetParameterH264: Profile = 100, Level = 52
NvMMLiteVideoEncDoWork: Surface resolution (1 x 3145728) smaller than encode resolution (1920 x 1080)
VENC: NvMMLiteVideoEncDoWork: 4207: BlockSide error 0x4
Event_BlockError from 330BlockAvcEnc : Error code - 4
Sending error event from 330BlockAvcEnc
This call appears to block the calling thread indefinitely as well. If I attempt to cause a core dump using kill -SIGSEGV, the stack is corrupted.
When running with UndefinedBehaviorSanitizer I will sometimes get the following stack trace when this error occurs:
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==3147==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x007f37f34e98 bp 0x007f313d0140 sp 0x007f313cffa0 T3172)
==3147==The signal is caused by a READ memory access.
==3147==Hint: address points to the zero page.
#0 0x7f37f34e94 in gst_query_find_allocation_meta (/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstomx.so+0xae94)
#1 0x7f37f36a00 in gst_query_find_allocation_meta (/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstomx.so+0xca00)
#2 0x7f37f36b20 in gst_query_find_allocation_meta (/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstomx.so+0xcb20)
#3 0x7f37f4d3b0 (/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstomx.so+0x233b0)
#4 0x7f7507fd8c in gst_element_change_state (/usr/lib/aarch64-linux-gnu/libgstreamer-1.0.so.0+0x62d8c)
I have tried using nvv4l2h264enc as well with the following pipeline:
appsrc ! video/x-raw, format=(string)BGR ! videoconvert ! video/x-raw, format=(string)I420, framerate=(fraction)10/1
! nvvidconv ! video/x-raw(memory:NVMM), format=(string)I420
! nvv4l2h264enc profile=4 preset-level=3 insert-sps-pps=1 iframeinterval=10
! video/x-h264,stream-format=byte-stream ! h264parse! qtmux ! filesink location=file.mp4
This pipeline appears to cause a memory leak on the dma buffers. Monitoring /sys/kernel/debug/nvmap/iovmm/allocations shows an increase of roughly 1.5MB every time I write a video.
Does anyone know what is going on here?