mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
gst: Implement SPA_META_VideoTransform support
Many Gstreamer elements support transforming buffers via the `image-orientation` tag. Use it to implement support for the new VideoTransform meta. In order for Gstreamer pipelines to enable support for these tags usually the rotate method has to be set to `auto` or `automatic`, e.g. `videoflip method=automatic`, `glimagesink rotate-method=automatic` or `waylandsink rotate-method=auto`.
This commit is contained in:
parent
fa799aac86
commit
2ed7afb76c
4 changed files with 52 additions and 2 deletions
|
|
@ -115,6 +115,8 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b)
|
|||
data->crop = spa_buffer_find_meta_data (b->buffer, SPA_META_VideoCrop, sizeof(*data->crop));
|
||||
if (data->crop)
|
||||
gst_buffer_add_video_crop_meta(buf);
|
||||
data->videotransform =
|
||||
spa_buffer_find_meta_data (b->buffer, SPA_META_VideoTransform, sizeof(*data->videotransform));
|
||||
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
|
||||
pool_data_quark,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct _GstPipeWirePoolData {
|
|||
GstBuffer *buf;
|
||||
gboolean queued;
|
||||
struct spa_meta_region *crop;
|
||||
struct spa_meta_videotransform *videotransform;
|
||||
};
|
||||
|
||||
struct _GstPipeWirePool {
|
||||
|
|
|
|||
|
|
@ -514,6 +514,25 @@ on_remove_buffer (void *_data, struct pw_buffer *b)
|
|||
}
|
||||
}
|
||||
|
||||
static const char * const transform_map[] = {
|
||||
[SPA_META_TRANSFORMATION_None] = "rotate-0",
|
||||
[SPA_META_TRANSFORMATION_90] = "rotate-90",
|
||||
[SPA_META_TRANSFORMATION_180] = "rotate-180",
|
||||
[SPA_META_TRANSFORMATION_270] = "rotate-270",
|
||||
[SPA_META_TRANSFORMATION_Flipped] = "flip-rotate-0",
|
||||
[SPA_META_TRANSFORMATION_Flipped90] = "flip-rotate-270",
|
||||
[SPA_META_TRANSFORMATION_Flipped180] = "flip-rotate-180",
|
||||
[SPA_META_TRANSFORMATION_Flipped270] = "flip-rotate-90",
|
||||
};
|
||||
|
||||
static const char *spa_transform_value_to_gst_image_orientation(uint32_t transform_value)
|
||||
{
|
||||
if (transform_value >= SPA_N_ELEMENTS(transform_map))
|
||||
transform_value = SPA_META_TRANSFORMATION_None;
|
||||
|
||||
return transform_map[transform_value];
|
||||
}
|
||||
|
||||
static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc)
|
||||
{
|
||||
struct pw_buffer *b;
|
||||
|
|
@ -521,6 +540,7 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc)
|
|||
GstPipeWirePoolData *data;
|
||||
struct spa_meta_header *h;
|
||||
struct spa_meta_region *crop;
|
||||
struct spa_meta_videotransform *videotransform;
|
||||
guint i;
|
||||
|
||||
b = pw_stream_dequeue_buffer (pwsrc->stream);
|
||||
|
|
@ -568,6 +588,27 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc)
|
|||
meta->height = crop->region.size.height;
|
||||
}
|
||||
}
|
||||
|
||||
videotransform = data->videotransform;
|
||||
if (videotransform) {
|
||||
if (pwsrc->transform_value != videotransform->transform) {
|
||||
GstEvent *tag_event;
|
||||
const char* tag_string;
|
||||
|
||||
tag_string =
|
||||
spa_transform_value_to_gst_image_orientation(videotransform->transform);
|
||||
|
||||
GST_LOG_OBJECT (pwsrc, "got new videotransform: %u / %s",
|
||||
videotransform->transform, tag_string);
|
||||
|
||||
tag_event = gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION,
|
||||
tag_string, NULL));
|
||||
gst_pad_push_event (GST_BASE_SRC_PAD (pwsrc), tag_event);
|
||||
|
||||
pwsrc->transform_value = videotransform->transform;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < b->buffer->n_datas; i++) {
|
||||
struct spa_data *d = &b->buffer->datas[i];
|
||||
GstMemory *pmem = gst_buffer_peek_memory (data->buf, i);
|
||||
|
|
@ -913,7 +954,7 @@ on_param_changed (void *data, uint32_t id,
|
|||
pwsrc->negotiated = pwsrc->caps != NULL;
|
||||
|
||||
if (pwsrc->negotiated) {
|
||||
const struct spa_pod *params[3];
|
||||
const struct spa_pod *params[4];
|
||||
struct spa_pod_builder b = { NULL };
|
||||
uint8_t buffer[512];
|
||||
uint32_t buffers = CLAMP (16, pwsrc->min_buffers, pwsrc->max_buffers);
|
||||
|
|
@ -939,9 +980,13 @@ on_param_changed (void *data, uint32_t id,
|
|||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoCrop),
|
||||
SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_region)));
|
||||
params[3] = spa_pod_builder_add_object (&b,
|
||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform),
|
||||
SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_videotransform)));
|
||||
|
||||
GST_DEBUG_OBJECT (pwsrc, "doing finish format");
|
||||
pw_stream_update_params (pwsrc->stream, params, 3);
|
||||
pw_stream_update_params (pwsrc->stream, params, SPA_N_ELEMENTS(params));
|
||||
} else {
|
||||
GST_WARNING_OBJECT (pwsrc, "finish format with error");
|
||||
pw_stream_set_error (pwsrc->stream, -EINVAL, "unhandled format");
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ struct _GstPipeWireSrc {
|
|||
GstPipeWirePool *pool;
|
||||
GstClock *clock;
|
||||
GstClockTime last_time;
|
||||
|
||||
enum spa_meta_videotransform_value transform_value;
|
||||
};
|
||||
|
||||
struct _GstPipeWireSrcClass {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue