mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -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