mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 04:00:37 +00:00
v4l2object: scale the encoded sizeimage based on maximum resolution
The default 2MB ENCODED_BUFFER_SIZE can't support some 4K video playback. We now detect the driver reported maximum resolution and choose an appropriate default bitstream size accordingly. For 4K video these results in around 4MB buffer instead of 2MB. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4549>
This commit is contained in:
parent
2bbc2a4c52
commit
25c00b5ba2
2 changed files with 46 additions and 5 deletions
|
@ -53,7 +53,7 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
||||||
#define DEFAULT_PROP_TV_NORM 0
|
#define DEFAULT_PROP_TV_NORM 0
|
||||||
#define DEFAULT_PROP_IO_MODE GST_V4L2_IO_AUTO
|
#define DEFAULT_PROP_IO_MODE GST_V4L2_IO_AUTO
|
||||||
|
|
||||||
#define ENCODED_BUFFER_SIZE (2 * 1024 * 1024)
|
#define ENCODED_BUFFER_MIN_SIZE (256 * 1024)
|
||||||
#define GST_V4L2_DEFAULT_WIDTH 320
|
#define GST_V4L2_DEFAULT_WIDTH 320
|
||||||
#define GST_V4L2_DEFAULT_HEIGHT 240
|
#define GST_V4L2_DEFAULT_HEIGHT 240
|
||||||
|
|
||||||
|
@ -2994,6 +2994,8 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
|
||||||
goto enum_framesizes_failed;
|
goto enum_framesizes_failed;
|
||||||
|
|
||||||
if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
||||||
|
guint32 maxw = 0, maxh = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
GST_LOG_OBJECT (v4l2object->dbg_obj, "got discrete frame size %dx%d",
|
GST_LOG_OBJECT (v4l2object->dbg_obj, "got discrete frame size %dx%d",
|
||||||
size.discrete.width, size.discrete.height);
|
size.discrete.width, size.discrete.height);
|
||||||
|
@ -3010,8 +3012,16 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
|
||||||
results = g_list_prepend (results, tmp);
|
results = g_list_prepend (results, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (w > maxw && h > maxh) {
|
||||||
|
maxw = w;
|
||||||
|
maxh = h;
|
||||||
|
}
|
||||||
|
|
||||||
size.index++;
|
size.index++;
|
||||||
} while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
|
} while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
|
||||||
|
|
||||||
|
v4l2object->max_width = maxw;
|
||||||
|
v4l2object->max_height = maxh;
|
||||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj,
|
GST_DEBUG_OBJECT (v4l2object->dbg_obj,
|
||||||
"done iterating discrete frame sizes");
|
"done iterating discrete frame sizes");
|
||||||
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
|
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
|
||||||
|
@ -3057,6 +3067,9 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
|
||||||
|
|
||||||
/* no point using the results list here, since there's only one struct */
|
/* no point using the results list here, since there's only one struct */
|
||||||
gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
|
gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
|
||||||
|
|
||||||
|
v4l2object->max_width = maxw;
|
||||||
|
v4l2object->max_height = maxh;
|
||||||
}
|
}
|
||||||
} else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
|
} else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
|
||||||
guint32 maxw, maxh;
|
guint32 maxw, maxh;
|
||||||
|
@ -3086,6 +3099,9 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
|
||||||
|
|
||||||
/* no point using the results list here, since there's only one struct */
|
/* no point using the results list here, since there's only one struct */
|
||||||
gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
|
gst_v4l2_object_update_and_append (v4l2object, pixelformat, ret, tmp);
|
||||||
|
|
||||||
|
v4l2object->max_width = maxw;
|
||||||
|
v4l2object->max_height = maxh;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goto unknown_type;
|
goto unknown_type;
|
||||||
|
@ -3717,6 +3733,19 @@ field_to_str (enum v4l2_field f)
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
calculate_max_sizeimage (GstV4l2Object * v4l2object, guint pixel_bitdepth)
|
||||||
|
{
|
||||||
|
guint max_width, max_height;
|
||||||
|
guint sizeimage;
|
||||||
|
|
||||||
|
max_width = v4l2object->max_width;
|
||||||
|
max_height = v4l2object->max_height;
|
||||||
|
sizeimage = max_width * max_height * pixel_bitdepth / 8 / 2;
|
||||||
|
|
||||||
|
return MAX (ENCODED_BUFFER_MIN_SIZE, sizeimage);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
gboolean try_only, GstV4l2Error * error)
|
gboolean try_only, GstV4l2Error * error)
|
||||||
|
@ -3730,6 +3759,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
GstVideoInfo info;
|
GstVideoInfo info;
|
||||||
GstVideoAlignment align;
|
GstVideoAlignment align;
|
||||||
gint width, height, fps_n, fps_d;
|
gint width, height, fps_n, fps_d;
|
||||||
|
guint pixel_bitdepth = 8;
|
||||||
gint n_v4l_planes;
|
gint n_v4l_planes;
|
||||||
gint i = 0;
|
gint i = 0;
|
||||||
gboolean is_mplane;
|
gboolean is_mplane;
|
||||||
|
@ -3928,6 +3958,14 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
"%" GST_FOURCC_FORMAT " stride: %d", width, height,
|
"%" GST_FOURCC_FORMAT " stride: %d", width, height,
|
||||||
GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0));
|
GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0));
|
||||||
|
|
||||||
|
s = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
if (gst_structure_has_field (s, "bit-depth-chroma")) {
|
||||||
|
gst_structure_get_uint (s, "bit-depth-chroma", &pixel_bitdepth);
|
||||||
|
GST_DEBUG_OBJECT (v4l2object->element, "Got pixel bit depth %u from caps",
|
||||||
|
pixel_bitdepth);
|
||||||
|
}
|
||||||
|
|
||||||
memset (&format, 0x00, sizeof (struct v4l2_format));
|
memset (&format, 0x00, sizeof (struct v4l2_format));
|
||||||
format.type = v4l2object->type;
|
format.type = v4l2object->type;
|
||||||
|
|
||||||
|
@ -3952,7 +3990,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
|
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
|
||||||
format.fmt.pix_mp.plane_fmt[0].sizeimage = ENCODED_BUFFER_SIZE;
|
format.fmt.pix_mp.plane_fmt[0].sizeimage =
|
||||||
|
calculate_max_sizeimage (v4l2object, pixel_bitdepth);
|
||||||
} else {
|
} else {
|
||||||
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
|
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
|
||||||
|
|
||||||
|
@ -3971,7 +4010,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
format.fmt.pix.bytesperline = stride;
|
format.fmt.pix.bytesperline = stride;
|
||||||
|
|
||||||
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
|
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
|
||||||
format.fmt.pix.sizeimage = ENCODED_BUFFER_SIZE;
|
format.fmt.pix.sizeimage =
|
||||||
|
calculate_max_sizeimage (v4l2object, pixel_bitdepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Desired format is %dx%d, format "
|
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Desired format is %dx%d, format "
|
||||||
|
@ -4164,8 +4204,6 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
|
||||||
goto invalid_planes;
|
goto invalid_planes;
|
||||||
|
|
||||||
/* used to check colorimetry and interlace mode fields presence */
|
/* used to check colorimetry and interlace mode fields presence */
|
||||||
s = gst_caps_get_structure (caps, 0);
|
|
||||||
|
|
||||||
if (gst_v4l2_object_get_interlace_mode (format.fmt.pix.field,
|
if (gst_v4l2_object_get_interlace_mode (format.fmt.pix.field,
|
||||||
&info.interlace_mode)) {
|
&info.interlace_mode)) {
|
||||||
if (gst_structure_has_field (s, "interlace-mode")) {
|
if (gst_structure_has_field (s, "interlace-mode")) {
|
||||||
|
|
|
@ -228,6 +228,9 @@ struct _GstV4l2Object {
|
||||||
* on slow USB firmwares. When this is set, gst_v4l2_set_format() will modify
|
* on slow USB firmwares. When this is set, gst_v4l2_set_format() will modify
|
||||||
* the caps to reflect what was negotiated during fixation */
|
* the caps to reflect what was negotiated during fixation */
|
||||||
gboolean skip_try_fmt_probes;
|
gboolean skip_try_fmt_probes;
|
||||||
|
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2ObjectClassHelper {
|
struct _GstV4l2ObjectClassHelper {
|
||||||
|
|
Loading…
Reference in a new issue