/** * gst_video_overlay_composition_new: * @rectangle: (transfer none): a #GstVideoOverlayRectangle to add to the * composition * * Creates a new video overlay composition object to hold one or more * overlay rectangles. * * Returns: (transfer full): a new #GstVideoOverlayComposition. Unref with * gst_video_overlay_composition_unref() when no longer needed. * * Since: 0.10.36 */ GstVideoOverlayComposition * gst_video_overlay_composition_new (GstVideoOverlayRectangle * rectangle) { GstVideoOverlayComposition *comp; /* FIXME: should we allow empty compositions? Could also be expressed as * buffer without a composition on it. Maybe there are cases where doing * an empty new + _add() in a loop is easier? */ g_return_val_if_fail (GST_IS_VIDEO_OVERLAY_RECTANGLE (rectangle), NULL); comp = (GstVideoOverlayComposition *) gst_mini_object_new (GST_TYPE_VIDEO_OVERLAY_COMPOSITION); comp->rectangles = g_new0 (GstVideoOverlayRectangle *, RECTANGLE_ARRAY_STEP); comp->rectangles[0] = gst_video_overlay_rectangle_ref (rectangle); comp->num_rectangles = 1; comp->seq_num = gst_video_overlay_get_seqnum (); /* since the rectangle was created earlier, its seqnum is smaller than ours */ comp->min_seq_num_used = rectangle->seq_num; GST_LOG ("new composition %p: seq_num %u with rectangle %p", comp, comp->seq_num, rectangle); return comp; }
/** * gst_video_overlay_composition_add_rectangle: * @comp: a #GstVideoOverlayComposition * @rectangle: (transfer none): a #GstVideoOverlayRectangle to add to the * composition * * Adds an overlay rectangle to an existing overlay composition object. This * must be done right after creating the overlay composition. * * Since: 0.10.36 */ void gst_video_overlay_composition_add_rectangle (GstVideoOverlayComposition * comp, GstVideoOverlayRectangle * rectangle) { g_return_if_fail (GST_IS_VIDEO_OVERLAY_COMPOSITION (comp)); g_return_if_fail (GST_IS_VIDEO_OVERLAY_RECTANGLE (rectangle)); g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (comp) == 1); if (comp->num_rectangles % RECTANGLE_ARRAY_STEP == 0) { comp->rectangles = g_renew (GstVideoOverlayRectangle *, comp->rectangles, comp->num_rectangles + RECTANGLE_ARRAY_STEP); }
/** * gst_vaapi_subpicture_new_from_overlay_rectangle: * @display: a #GstVaapiDisplay * @rect: a #GstVideoOverlayRectangle * * Helper function that creates a new #GstVaapiSubpicture from a * #GstVideoOverlayRectangle. A new #GstVaapiImage is also created * along the way and attached to the resulting subpicture. The * subpicture holds a unique reference to the underlying image. * * Return value: the newly allocated #GstVaapiSubpicture object */ GstVaapiSubpicture * gst_vaapi_subpicture_new_from_overlay_rectangle (GstVaapiDisplay * display, GstVideoOverlayRectangle * rect) { GstVaapiSubpicture *subpicture; GstVideoFormat format; GstVaapiImage *image; GstVaapiImageRaw raw_image; GstBuffer *buffer; guint8 *data; gfloat global_alpha; guint width, height, stride; guint hw_flags, flags; GstVideoMeta *vmeta; GstMapInfo map_info; g_return_val_if_fail (GST_IS_VIDEO_OVERLAY_RECTANGLE (rect), NULL); /* XXX: use gst_vaapi_image_format_from_video() */ #if G_BYTE_ORDER == G_LITTLE_ENDIAN format = GST_VIDEO_FORMAT_BGRA; #else format = GST_VIDEO_FORMAT_ARGB; #endif if (!gst_vaapi_display_has_subpicture_format (display, format, &hw_flags)) return NULL; flags = hw_flags & from_GstVideoOverlayFormatFlags (gst_video_overlay_rectangle_get_flags (rect)); buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect, to_GstVideoOverlayFormatFlags (flags)); if (!buffer) return NULL; vmeta = gst_buffer_get_video_meta (buffer); if (!vmeta) return NULL; width = vmeta->width; height = vmeta->height; if (!gst_video_meta_map (vmeta, 0, &map_info, (gpointer *) & data, (gint *) & stride, GST_MAP_READ)) return NULL; image = gst_vaapi_image_new (display, format, width, height); if (!image) return NULL; raw_image.format = format; raw_image.width = width; raw_image.height = height; raw_image.num_planes = 1; raw_image.pixels[0] = data; raw_image.stride[0] = stride; if (!gst_vaapi_image_update_from_raw (image, &raw_image, NULL)) { GST_WARNING ("could not update VA image with subtitle data"); gst_vaapi_object_unref (image); return NULL; } subpicture = gst_vaapi_subpicture_new (image, flags); gst_vaapi_object_unref (image); gst_video_meta_unmap (vmeta, 0, &map_info); if (!subpicture) return NULL; if (flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA) { global_alpha = gst_video_overlay_rectangle_get_global_alpha (rect); if (!gst_vaapi_subpicture_set_global_alpha (subpicture, global_alpha)) return NULL; } return subpicture; }