The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

aux/gst: Support odd I420/GRAY8 frame widths and heights

Add padding for odd width/height I420 and GRAY8 video frames
using videobox, and add warnings for corner cases where that
won't work.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2188>

authored by

Jan Schmidt and committed by
Marge Bot
4555f5e7 eb4d2cd9

+52 -7
+5
src/xrt/auxiliary/gstreamer/gst_internal.h
··· 71 71 72 72 //! Cached appsrc element. 73 73 GstElement *appsrc; 74 + 75 + //! Info about required / configured width/height padding 76 + bool need_even_dims; 77 + bool have_padded_height; 78 + bool have_padded_width; 74 79 }; 75 80 76 81
+46 -6
src/xrt/auxiliary/gstreamer/gst_sink.c
··· 55 55 } 56 56 57 57 static void 58 - complain_if_wrong_image_size(struct xrt_frame *xf) 58 + complain_if_wrong_image_size(struct gstreamer_sink *gs, struct xrt_frame *xf) 59 59 { 60 + if (!gs->need_even_dims) { 61 + return; 62 + } 63 + 60 64 // libx264 is the actual source of this requirement; it refuses to handle odd widths/heights when encoding I420 61 65 // subsampled content. OpenH264 should work, but it's easy enough to just force all users of this code to 62 66 // provide normal-sized inputs. 63 67 if (xf->width % 2 == 1) { 64 - U_LOG_W("Image width needs to be divisible by 2!"); 68 + if (!gs->have_padded_width) { 69 + U_LOG_W("Image width needs to be divisible by 2!"); 70 + } 71 + } else if (gs->have_padded_width) { 72 + U_LOG_W("Image width changed after we added padding!"); 65 73 } 74 + 66 75 if (xf->height % 2 == 1) { 67 - U_LOG_W("Image height needs to be divisible by 2!"); 76 + if (!gs->have_padded_height) { 77 + U_LOG_W("Image height needs to be divisible by 2!"); 78 + } 79 + } else if (gs->have_padded_height) { 80 + U_LOG_W("Image height changed after we added padding!"); 68 81 } 69 82 } 70 83 ··· 74 87 SINK_TRACE_MARKER(); 75 88 struct gstreamer_sink *gs = (struct gstreamer_sink *)xfs; 76 89 77 - complain_if_wrong_image_size(xf); 90 + complain_if_wrong_image_size(gs, xf); 78 91 79 92 GstBuffer *buffer; 80 93 GstFlowReturn ret; ··· 194 207 struct xrt_frame_sink **out_xfs) 195 208 { 196 209 const char *format_str = NULL; 210 + bool need_even_dims = false; 211 + 197 212 switch (format) { 198 213 case XRT_FORMAT_R8G8B8: format_str = "RGB"; break; 199 214 case XRT_FORMAT_R8G8B8A8: format_str = "RGBA"; break; 200 215 case XRT_FORMAT_R8G8B8X8: format_str = "RGBx"; break; 201 - case XRT_FORMAT_YUYV422: format_str = "YUY2"; break; 202 - case XRT_FORMAT_L8: format_str = "GRAY8"; break; 216 + case XRT_FORMAT_YUYV422: 217 + format_str = "YUY2"; 218 + need_even_dims = true; 219 + break; 220 + case XRT_FORMAT_L8: 221 + format_str = "GRAY8"; 222 + need_even_dims = true; 223 + break; 203 224 default: assert(false); break; 204 225 } 205 226 ··· 209 230 gs->node.destroy = destroy; 210 231 gs->gp = gp; 211 232 gs->appsrc = gst_bin_get_by_name(GST_BIN(gp->pipeline), appsrc_name); 233 + gs->need_even_dims = need_even_dims; 234 + 235 + if (need_even_dims) { 236 + /* Pad out height and width to multiple of 2 */ 237 + GstElement *vbox = gst_bin_get_by_name(GST_BIN(gp->pipeline), "vbox"); 238 + if (vbox != NULL) { 239 + if (height % 2) { 240 + g_object_set(G_OBJECT(vbox), "bottom", -1, NULL); 241 + gs->have_padded_height = true; 242 + } 243 + if (width % 2) { 244 + g_object_set(G_OBJECT(vbox), "width", -1, NULL); 245 + gs->have_padded_width = true; 246 + } 247 + gst_object_unref(vbox); 248 + } else if (height % 2 || width % 2) { 249 + U_LOG_W("Image height or width needs padding. Please add `videobox name=vbox' to the pipeline"); 250 + } 251 + } 212 252 213 253 214 254 GstCaps *caps = gst_caps_new_simple( //
+1 -1
src/xrt/state_trackers/gui/gui_window_record.c
··· 85 85 "appsrc name=\"%s\" ! " 86 86 "queue ! " 87 87 "videoconvert ! " 88 - "queue ! " 88 + "videobox name=vbox ! " 89 89 "x264enc bitrate=\"%s\" speed-preset=\"%s\" ! " 90 90 "video/x-h264,profile=main ! " 91 91 "h264parse ! "