The following pipeline converts NV12 to RGB and performs scaling from 1920x1080 to 640x480.
gst-launch-1.0 -v \
videotestsrc num-buffers=10 ! video/x-raw,format=NV12,width=1920,height=1080 \
! vvas_xmulticrop xclbin-location=/run/media/mmcblk0p1/x_plus_ml.xclbin \
! video/x-raw,format=RGB,width=640,height=480 ! filesink location=out_480p.rgb
The following pipeline performs pre-processing along with color space conversion and scaling on output buffers.
gst-launch-1.0 -v \
videotestsrc num-buffers=10 ! video/x-raw,format=NV12,width=1920,height=1080 \
! vvas_xmulticrop ppe-on-main-buffer=true alpha-r=124 alpha-g=116 alpha-b=104 beta-r=0.547 beta-g=0.56 beta-b=0.557 xclbin-location=/run/media/mmcblk0p1/x_plus_ml.xclbin \
! video/x-raw,format=RGB,width=640,height=480 ! filesink location=out_480p.rgb
The pipeline performs static cropping at (x,y) = (100,80) and (width,height)= (1280,720); this cropped buffers gets scaled to 640x480 and converted to RGB.
gst-launch-1.0 -v \
videotestsrc num-buffers=10 ! video/x-raw,format=NV12,width=1920,height=1080 \
! vvas_xmulticrop s-crop-x=100 s-crop-y=80 s-crop-width=1280 s-crop-height=720 xclbin-location=/run/media/mmcblk0p1/x_plus_ml.xclbin \
! video/x-raw,format=RGB,width=640,height=480 ! filesink location=out_480p.rgb
The following code shows how to add GstVideoRegionOfInterestMeta for dynamic cropping.
GstVideoRegionOfInterestMeta *meta;
meta = gst_buffer_add_video_region_of_interest_meta (buffer, "roi-crop-meta", 0, 0, 0, 0);
if (meta) {
meta->id = id;
meta->parent_id = p_id;
meta->x = x;
meta->y = y;
meta->w = w;
meta->h = h;
printf("meta: x:%u y:%u, w:%u h:%u", meta->x, meta->y, meta->w, meta->h);
}
The following code shows how to read GstVideoRegionOfInterestMeta and how to extract a dynamically cropped buffer/object.
read_crop_meta (GstBuffer *buf) {
gpointer state = NULL;
GstMeta *_meta;
while ((_meta = gst_buffer_iterate_meta_filtered (buf, &state,
GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE))) {
GstStructure *s = NULL;
GstVideoRegionOfInterestMeta *roi_meta =
(GstVideoRegionOfInterestMeta *) _meta;
if (g_strcmp0("roi-crop-meta", g_quark_to_string (roi_meta->roi_type))) {
//This is not the metadata we are looking for
continue;
}
//Got the ROI crop metadata, prepare output buffer
//Extract dynamically cropped buffer from this meta
s = gst_video_region_of_interest_meta_get_param (roi_meta, "roi-buffer");
if (s) {
GstBuffer *sub_buffer = NULL;
gst_structure_get (s, "sub-buffer", GST_TYPE_BUFFER, &sub_buffer, NULL);
if (sub_buffer) {
//use sub_buffer and unref it
dump_dynamically_cropped_buffer (sub_buffer);
} else {
printf("couldn't get sub buffer");
}
} else {
printf("couldn't get expected struct");
}
}
return TRUE;
}
The following code shows how to read/dump dynamically cropped buffers.
static gboolean
dump_dynamically_cropped_buffer (GstBuffer *sub_buffer)
{
//Read GstVideoMeta from the buffer, dump the buffer to file
GstVideoMeta *vmeta = NULL;
FILE *fp;
gchar name[256] = { 0 };
guint i, j, n_planes;
GstVideoFrame out_frame = { 0 };
GstVideoFrame new_frame = { 0 };
GstVideoInfo *vinfo;
GstBuffer *new_outbuf;
guint8 *data_ptr, *out_ptr;
guint w, h;
gint src_stride;
const GstVideoFormatInfo *finfo;
gint comp[GST_VIDEO_MAX_COMPONENTS];
const GstVideoInfo *sinfo;
if (!sub_buffer) {
return FALSE;
}
vmeta = gst_buffer_get_video_meta (sub_buffer);
if (!vmeta) {
printf ("couldn't get video meta\n");
return FALSE;
}
sprintf (name, "dynbuf_%ux%u_%s.yuv", vmeta->width, vmeta->height,
gst_video_format_to_string (vmeta->format));
fp = fopen (name, "wb");
if (!fp) {
return FALSE;
}
vinfo = gst_video_info_new ();
gst_video_info_set_format (vinfo, vmeta->format, vmeta->width, vmeta->height);
new_outbuf = gst_buffer_new_and_alloc (GST_VIDEO_INFO_SIZE (vinfo));
if (!new_outbuf) {
printf ("couldn't allocate buffer\n");
gst_video_info_free (vinfo);
fclose (fp);
return FALSE;
}
gst_video_frame_map (&out_frame, vinfo, sub_buffer, GST_MAP_READ);
gst_video_frame_map (&new_frame, vinfo, new_outbuf,
GST_MAP_READ | GST_MAP_WRITE);
sinfo = &out_frame.info;
finfo = sinfo->finfo;
n_planes = finfo->n_planes;
for (i = 0; i < n_planes; i++) {
gst_video_format_info_component (finfo, i, comp);
data_ptr = out_frame.data[i];
out_ptr = new_frame.data[i];
w = GST_VIDEO_FRAME_COMP_WIDTH (&out_frame, comp[0])
* GST_VIDEO_FRAME_COMP_PSTRIDE (&out_frame, comp[0]);
h = GST_VIDEO_FRAME_COMP_HEIGHT (&out_frame, comp[0]);
src_stride = GST_VIDEO_INFO_PLANE_STRIDE (sinfo, i);
for (j = 0; j < h; j++) {
memcpy (out_ptr, data_ptr, w);
data_ptr += src_stride;
out_ptr += w;
}
fwrite (new_frame.data[i], 1, w * h, fp);
}
gst_video_frame_unmap (&out_frame);
gst_video_frame_unmap (&new_frame);
gst_video_info_free (vinfo);
gst_buffer_unref (new_outbuf);
fclose (fp);
gst_buffer_unref (sub_buffer);
return TRUE;
}