/** * 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; }
/** * gst_video_frame_map_id: * @frame: pointer to #GstVideoFrame * @info: a #GstVideoInfo * @buffer: the buffer to map * @id: the frame id to map * @flags: #GstMapFlags * * Use @info and @buffer to fill in the values of @frame with the video frame * information of frame @id. * * When @id is -1, the default frame is mapped. When @id != -1, this function * will return %FALSE when there is no GstVideoMeta with that id. * * All video planes of @buffer will be mapped and the pointers will be set in * @frame->data. * * Returns: %TRUE on success. */ gboolean gst_video_frame_map_id (GstVideoFrame * frame, GstVideoInfo * info, GstBuffer * buffer, gint id, GstMapFlags flags) { GstVideoMeta *meta; gint i; g_return_val_if_fail (frame != NULL, FALSE); g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); if (id == -1) meta = gst_buffer_get_video_meta (buffer); else meta = gst_buffer_get_video_meta_id (buffer, id); /* copy the info */ frame->info = *info; if (meta) { frame->info.finfo = gst_video_format_get_info (meta->format); frame->info.width = meta->width; frame->info.height = meta->height; frame->id = meta->id; frame->flags = meta->flags; for (i = 0; i < info->finfo->n_planes; i++) if (!gst_video_meta_map (meta, i, &frame->map[i], &frame->data[i], &frame->info.stride[i], flags)) goto frame_map_failed; } else { /* no metadata, we really need to have the metadata when the id is * specified. */ if (id != -1) goto no_metadata; frame->id = id; frame->flags = 0; if (!gst_buffer_map (buffer, &frame->map[0], flags)) goto map_failed; /* do some sanity checks */ if (frame->map[0].size < info->size) goto invalid_size; /* set up pointers */ for (i = 0; i < info->finfo->n_planes; i++) { frame->data[i] = frame->map[0].data + info->offset[i]; } } frame->buffer = gst_buffer_ref (buffer); frame->meta = meta; /* buffer flags enhance the frame flags */ if (GST_VIDEO_INFO_IS_INTERLACED (info)) { if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED)) frame->flags |= GST_VIDEO_FRAME_FLAG_INTERLACED; if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF)) frame->flags |= GST_VIDEO_FRAME_FLAG_TFF; if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_RFF)) frame->flags |= GST_VIDEO_FRAME_FLAG_RFF; if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_FLAG_ONEFIELD)) frame->flags |= GST_VIDEO_FRAME_FLAG_ONEFIELD; } return TRUE; /* ERRORS */ no_metadata: { GST_ERROR ("no GstVideoMeta for id %d", id); return FALSE; } frame_map_failed: { GST_ERROR ("failed to map video frame plane %d", i); while (--i >= 0) gst_video_meta_unmap (meta, i, &frame->map[i]); return FALSE; } map_failed: { GST_ERROR ("failed to map buffer"); return FALSE; } invalid_size: { GST_ERROR ("invalid buffer size %" G_GSIZE_FORMAT " < %" G_GSIZE_FORMAT, frame->map[0].size, info->size); gst_buffer_unmap (buffer, &frame->map[0]); return FALSE; } }