mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	videoconvert: refactor add_video_formats
Rework the function a little so that it can take a list of formats and only add the supported formats from that list and only once. It can optionally select only the DSP formats.
This commit is contained in:
		
							parent
							
								
									df2369f6e1
								
							
						
					
					
						commit
						0ebf664515
					
				
					 1 changed files with 80 additions and 54 deletions
				
			
		| 
						 | 
				
			
			@ -278,35 +278,43 @@ static void emit_info(struct impl *this, bool full)
 | 
			
		|||
struct format_info {
 | 
			
		||||
	enum AVPixelFormat pix_fmt;
 | 
			
		||||
	uint32_t format;
 | 
			
		||||
	uint32_t dsp_format;
 | 
			
		||||
#define FORMAT_DSP	(1<<0)
 | 
			
		||||
#define FORMAT_COMMON	(1<<1)
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined AV_PIX_FMT_AYUV
 | 
			
		||||
#define VIDEO_FORMAT_DSP_AYUV SPA_VIDEO_FORMAT_AYUV
 | 
			
		||||
#else
 | 
			
		||||
#define VIDEO_FORMAT_DSP_AYUV SPA_VIDEO_FORMAT_Y444
 | 
			
		||||
#endif
 | 
			
		||||
#define VIDEO_FORMAT_DSP_RGBA SPA_VIDEO_FORMAT_RGBA
 | 
			
		||||
 | 
			
		||||
static struct format_info format_info[] =
 | 
			
		||||
{
 | 
			
		||||
#if defined AV_PIX_FMT_AYUV
 | 
			
		||||
	{ AV_PIX_FMT_AYUV,  SPA_VIDEO_FORMAT_AYUV, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_AYUV,  SPA_VIDEO_FORMAT_AYUV, VIDEO_FORMAT_DSP_AYUV, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
#else
 | 
			
		||||
	{ AV_PIX_FMT_YUV444P, SPA_VIDEO_FORMAT_Y444, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YUV444P, SPA_VIDEO_FORMAT_Y444, VIDEO_FORMAT_DSP_AYUV, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
#endif
 | 
			
		||||
	{ AV_PIX_FMT_RGBA,  SPA_VIDEO_FORMAT_RGBA, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_RGBA,  SPA_VIDEO_FORMAT_RGBA, VIDEO_FORMAT_DSP_RGBA, FORMAT_DSP | FORMAT_COMMON },
 | 
			
		||||
 | 
			
		||||
	{ AV_PIX_FMT_YUYV422, SPA_VIDEO_FORMAT_YUY2, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_UYVY422, SPA_VIDEO_FORMAT_UYVY, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YVYU422, SPA_VIDEO_FORMAT_YVYU, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YUV420P, SPA_VIDEO_FORMAT_I420, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YUYV422, SPA_VIDEO_FORMAT_YUY2, VIDEO_FORMAT_DSP_AYUV, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_UYVY422, SPA_VIDEO_FORMAT_UYVY, VIDEO_FORMAT_DSP_AYUV, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YVYU422, SPA_VIDEO_FORMAT_YVYU, VIDEO_FORMAT_DSP_AYUV, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_YUV420P, SPA_VIDEO_FORMAT_I420, VIDEO_FORMAT_DSP_AYUV, FORMAT_COMMON },
 | 
			
		||||
 | 
			
		||||
	//{ AV_PIX_FMT_BGR0,  SPA_VIDEO_FORMAT_BGRx },
 | 
			
		||||
	//{ AV_PIX_FMT_BGRA,  SPA_VIDEO_FORMAT_BGRA },
 | 
			
		||||
	//{ AV_PIX_FMT_ARGB,  SPA_VIDEO_FORMAT_ARGB },
 | 
			
		||||
	//{ AV_PIX_FMT_ABGR,  SPA_VIDEO_FORMAT_ABGR },
 | 
			
		||||
	{ AV_PIX_FMT_BGR0,  SPA_VIDEO_FORMAT_BGRx, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_BGRA,  SPA_VIDEO_FORMAT_BGRA, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_ARGB,  SPA_VIDEO_FORMAT_ARGB, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_ABGR,  SPA_VIDEO_FORMAT_ABGR, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
 | 
			
		||||
	//{ AV_PIX_FMT_NONE,  SPA_VIDEO_FORMAT_YV12 },
 | 
			
		||||
 | 
			
		||||
	//{ AV_PIX_FMT_RGB0,  SPA_VIDEO_FORMAT_RGBx },
 | 
			
		||||
	//{ AV_PIX_FMT_0RGB,  SPA_VIDEO_FORMAT_xRGB },
 | 
			
		||||
	//{ AV_PIX_FMT_0BGR,  SPA_VIDEO_FORMAT_xBGR },
 | 
			
		||||
	{ AV_PIX_FMT_RGB0,  SPA_VIDEO_FORMAT_RGBx, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_0RGB,  SPA_VIDEO_FORMAT_xRGB, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
	{ AV_PIX_FMT_0BGR,  SPA_VIDEO_FORMAT_xBGR, VIDEO_FORMAT_DSP_RGBA, FORMAT_COMMON },
 | 
			
		||||
 | 
			
		||||
	//{ AV_PIX_FMT_RGB24,   SPA_VIDEO_FORMAT_RGB },
 | 
			
		||||
	//{ AV_PIX_FMT_BGR24,   SPA_VIDEO_FORMAT_BGR },
 | 
			
		||||
| 
						 | 
				
			
			@ -392,13 +400,19 @@ static struct format_info format_info[] =
 | 
			
		|||
	//{ AV_PIX_FMT_NONE, SPA_VIDEO_FORMAT_BGRA_102LE },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static enum AVPixelFormat format_to_pix_fmt(uint32_t format)
 | 
			
		||||
static struct format_info *format_info_for_format(uint32_t format)
 | 
			
		||||
{
 | 
			
		||||
	SPA_FOR_EACH_ELEMENT_VAR(format_info, i) {
 | 
			
		||||
		if (i->format == format)
 | 
			
		||||
			return i->pix_fmt;
 | 
			
		||||
			return i;
 | 
			
		||||
	}
 | 
			
		||||
	return AV_PIX_FMT_NONE;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum AVPixelFormat format_to_pix_fmt(uint32_t format)
 | 
			
		||||
{
 | 
			
		||||
	struct format_info *i = format_info_for_format(format);
 | 
			
		||||
	return i ? i->pix_fmt : AV_PIX_FMT_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_format(struct dir *dir, uint32_t *format, struct spa_rectangle *size,
 | 
			
		||||
| 
						 | 
				
			
			@ -1088,19 +1102,52 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
 | 
			
		|||
	return -ENOTSUP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_video_formats(struct spa_pod_builder *b, uint32_t def)
 | 
			
		||||
static void add_video_formats(struct spa_pod_builder *b,
 | 
			
		||||
		uint32_t *vals, uint32_t n_vals, bool is_dsp)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t i;
 | 
			
		||||
	struct spa_pod_frame f[1];
 | 
			
		||||
	uint32_t ids[SPA_N_ELEMENTS(format_info) + 1], n_ids = 0, i, j, fmt;
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_format, 0);
 | 
			
		||||
	spa_pod_builder_push_choice(b, &f[0], SPA_CHOICE_Enum, 0);
 | 
			
		||||
	if (def == SPA_ID_INVALID)
 | 
			
		||||
		def = format_info[0].format;
 | 
			
		||||
	spa_pod_builder_id(b, def);
 | 
			
		||||
	for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
 | 
			
		||||
		if (format_info[i].pix_fmt != AV_PIX_FMT_NONE)
 | 
			
		||||
			spa_pod_builder_id(b, format_info[i].format);
 | 
			
		||||
 | 
			
		||||
	if (n_vals == 0) {
 | 
			
		||||
		 vals = &format_info[0].format;
 | 
			
		||||
		 n_vals = 1;
 | 
			
		||||
	}
 | 
			
		||||
	/* all supported formats */
 | 
			
		||||
	for (i = 0; i < n_vals; i++) {
 | 
			
		||||
		struct format_info *fi = format_info_for_format(vals[i]);
 | 
			
		||||
		if (fi == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		fmt = is_dsp ? fi->dsp_format : fi->format;
 | 
			
		||||
 | 
			
		||||
		for (j = 0; j < n_ids; j++) {
 | 
			
		||||
			if (ids[j] == fmt)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		if (j == n_ids)
 | 
			
		||||
			ids[n_ids++] = fmt;
 | 
			
		||||
	}
 | 
			
		||||
	/* then add all other supported formats */
 | 
			
		||||
	SPA_FOR_EACH_ELEMENT_VAR(format_info, fi) {
 | 
			
		||||
		if (fi->pix_fmt == AV_PIX_FMT_NONE)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		fmt = is_dsp ? fi->dsp_format : fi->format;
 | 
			
		||||
 | 
			
		||||
		for (j = 0; j < n_ids; j++) {
 | 
			
		||||
			if (fmt == ids[j])
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		if (j == n_ids)
 | 
			
		||||
			ids[n_ids++] = fmt;
 | 
			
		||||
	}
 | 
			
		||||
	for (i = 0; i < n_ids; i++) {
 | 
			
		||||
		spa_pod_builder_id(b, ids[i]);
 | 
			
		||||
		if (i == 0)
 | 
			
		||||
			spa_pod_builder_id(b, ids[i]);
 | 
			
		||||
	}
 | 
			
		||||
	spa_pod_builder_pop(b, &f[0]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,7 +1155,7 @@ static void add_video_formats(struct spa_pod_builder *b, uint32_t def)
 | 
			
		|||
static struct spa_pod *transform_format(struct impl *this, struct port *port, const struct spa_pod *format,
 | 
			
		||||
		uint32_t id, struct spa_pod_builder *b)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t media_type, media_subtype;
 | 
			
		||||
	uint32_t media_type, media_subtype, fmt;
 | 
			
		||||
	struct spa_pod_object *obj;
 | 
			
		||||
	const struct spa_pod_prop *prop;
 | 
			
		||||
	struct spa_pod_frame f[2];
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,14 +1176,15 @@ static struct spa_pod *transform_format(struct impl *this, struct port *port, co
 | 
			
		|||
		case SPA_FORMAT_mediaSubtype:
 | 
			
		||||
			spa_pod_builder_prop(b, prop->key, prop->flags);
 | 
			
		||||
			spa_pod_builder_id(b, SPA_MEDIA_SUBTYPE_raw);
 | 
			
		||||
			fmt = SPA_VIDEO_FORMAT_I420;
 | 
			
		||||
			switch (media_subtype) {
 | 
			
		||||
			case SPA_MEDIA_SUBTYPE_raw:
 | 
			
		||||
				break;
 | 
			
		||||
			case SPA_MEDIA_SUBTYPE_mjpg:
 | 
			
		||||
				add_video_formats(b, SPA_VIDEO_FORMAT_I420);
 | 
			
		||||
				add_video_formats(b, &fmt, 1, port->is_dsp);
 | 
			
		||||
				break;
 | 
			
		||||
			case SPA_MEDIA_SUBTYPE_h264:
 | 
			
		||||
				add_video_formats(b, SPA_VIDEO_FORMAT_I420);
 | 
			
		||||
				add_video_formats(b, &fmt, 1, port->is_dsp);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1144,37 +1192,15 @@ static struct spa_pod *transform_format(struct impl *this, struct port *port, co
 | 
			
		|||
			break;
 | 
			
		||||
		case SPA_FORMAT_VIDEO_format:
 | 
			
		||||
		{
 | 
			
		||||
			uint32_t i, j, n_vals, choice, *id_vals;
 | 
			
		||||
			uint32_t n_vals, choice, *id_vals;
 | 
			
		||||
			struct spa_pod *val = spa_pod_get_values(&prop->value, &n_vals, &choice);
 | 
			
		||||
 | 
			
		||||
			if (!spa_pod_is_id(val))
 | 
			
		||||
				return 0;
 | 
			
		||||
 | 
			
		||||
			spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_format, 0);
 | 
			
		||||
			spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0);
 | 
			
		||||
			id_vals = SPA_POD_BODY(val);
 | 
			
		||||
			spa_pod_builder_id(b, id_vals[0]);
 | 
			
		||||
			/* first add all supported formats */
 | 
			
		||||
			for (i = 1; i < n_vals; i++) {
 | 
			
		||||
				for (j = 0; j < i; j++) {
 | 
			
		||||
					if (id_vals[j] == id_vals[i])
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
				if (j == i && format_to_pix_fmt(id_vals[i]) != AV_PIX_FMT_NONE)
 | 
			
		||||
					spa_pod_builder_id(b, id_vals[i]);
 | 
			
		||||
			}
 | 
			
		||||
			/* then add all other supported formats */
 | 
			
		||||
			for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
 | 
			
		||||
				if (format_info[i].pix_fmt == AV_PIX_FMT_NONE)
 | 
			
		||||
					continue;
 | 
			
		||||
				for (j = 1; j < n_vals; j++) {
 | 
			
		||||
					if (format_info[i].format == id_vals[j])
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
				if (j == n_vals)
 | 
			
		||||
					spa_pod_builder_id(b, format_info[i].format);
 | 
			
		||||
			}
 | 
			
		||||
			spa_pod_builder_pop(b, &f[1]);
 | 
			
		||||
 | 
			
		||||
			add_video_formats(b, id_vals, n_vals, port->is_dsp);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			@ -1320,7 +1346,7 @@ static int all_formats(struct impl *this, struct port *port, uint32_t id,
 | 
			
		|||
			SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_video),
 | 
			
		||||
			SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
 | 
			
		||||
			0);
 | 
			
		||||
		add_video_formats(b, SPA_ID_INVALID);
 | 
			
		||||
		add_video_formats(b, NULL, 0, port->is_dsp);
 | 
			
		||||
		*param = spa_pod_builder_pop(b, &f[0]);
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue