v4l2convert: Cannot scale 1080p H264 frame with dmabuf-import on 1920x1080 screen
Hi,
My environment is:
- Device: Apalis iMX6
- OS: Debian 11
- Kernel: 5.10.19
- GStreamer: 1.18.4
In short, my problem is when scale 1080 H264 video, the decoder return frame with actual size is 1920x1088. Then v4l2allocator
queues buffer with bytesused
is 4177920 (2x1920x1088), but videobuf2-v4l2
from kernel refuses it because it is larger than plane length which is 4147200 (2x1920x1080).
I will try my best to describe my problem.
I got an error when tried to scale 1080p H264 video to 720p with v4l2convert
and dmabuf-import
on 1920x1080 screen. My pipeline is:
$ gst-launch-1.0 filesrc location=jellyfish-15-mbps-hd-h264.mkv \
! matroskademux ! h264parse \
! v4l2h264dec capture-io-mode=dmabuf \
! v4l2convert output-io-mode=dmabuf-import \
! video/x-raw,width=1280,height=720 ! fakesink
...
0:00:01.031328667 4834 0x18da568 ERROR v4l2allocator gstv4l2allocator.c:1275:gst_v4l2_allocator_qbuf:<v4l2convert0:pool0:sink:allocator> failed queueing buffer 0: Invalid argument
0:00:01.031843667 4834 0x18da568 ERROR v4l2bufferpool gstv4l2bufferpool.c:1208:gst_v4l2_buffer_pool_qbuf:<v4l2convert0:pool0:sink> could not queue a buffer 0
0:00:01.032128000 4834 0x18da568 ERROR v4l2bufferpool gstv4l2bufferpool.c:2109:gst_v4l2_buffer_pool_process:<v4l2convert0:pool0:sink> failed to queue buffer
ERROR: from element /GstPipeline:pipeline0/GstMatroskaDemux:matroskademux0: Internal data stream error.
Additional debug info:
../gst/matroska/matroska-demux.c(5869): gst_matroska_demux_loop (): /GstPipeline:pipeline0/GstMatroskaDemux:matroskademux0:
streaming stopped, reason error (-5)
ERROR: pipeline doesn't want to preroll.
...
The pipeline could run if v4l2convert
doesn't use dmabuf-import
, but with very poor performance.
After some debug, I found that although the video cap is 1920x1080, the actual H264 frame size is 1920x1088. This makes queueing buffer fail because bytesused
is larger than plane's length.
// from sys/v4l2/gstv4l2allocator.c
if (obj->ioctl (obj->video_fd, VIDIOC_QBUF, &group->buffer) < 0) { // group->buffer.bytesused is 4177920
GST_ERROR_OBJECT (allocator, "failed queueing buffer %i: %s",
group->buffer.index, g_strerror (errno));
// from linux drivers/media/common/videobuf2/videobuf2-v4l2.c
/*
* __verify_length() - Verify that the bytesused value for each plane fits in
* the plane length and that the data offset doesn't exceed the bytesused value.
*/
static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
...
length = (b->memory == VB2_MEMORY_USERPTR) // b->memory is VB2_MEMORY_DMABUF
? b->length : vb->planes[0].length;
if (b->bytesused > length) // b->bytesused is 4177920, length is 4147200
return -EINVAL;
How I can pass this problem? Should v4l2allocator
crop the size of buffer before queueing?
I think #790 (closed) may fail with same reason, because the captured image also has size 1920x1088, based on information of /dev/video1
.
Thank you very much,
Trung