mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	impl-link: improve negotiation
Make a function to create a filter. This is a pod that has all valid
defaults fixated and the invalid ones left unfixated.
Use this filter is a first attempt to negotiate a link format. The
effect is that a format will be chosen first that matches all the valid
defaults as much as possible instead of negotiating to the first thing
that matches.
Suppose we have a higher priority port with the format:
 foo/bar
    key: { default:1024, min:1, max:2048 }
And another port with two params:
 foo/bar
    key: 512
    rate: 2/1
 foo/bar
    key: 1024
    rate: 30/1
By first trying key: 1024 we negotiate to the more specific second property
with the higher rate.
			
			
This commit is contained in:
		
							parent
							
								
									9255e07c3a
								
							
						
					
					
						commit
						faf5ae0c2f
					
				
					 2 changed files with 40 additions and 1 deletions
				
			
		| 
						 | 
					@ -379,6 +379,32 @@ spa_pod_filter(struct spa_pod_builder *b,
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPA_API_POD_FILTER int spa_pod_filter_object_make(struct spa_pod_object *pod)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct spa_pod_prop *res;
 | 
				
			||||||
 | 
						int count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPA_POD_OBJECT_FOREACH(pod, res) {
 | 
				
			||||||
 | 
							if (res->value.type == SPA_TYPE_Choice &&
 | 
				
			||||||
 | 
							    !SPA_FLAG_IS_SET(res->flags, SPA_POD_PROP_FLAG_DONT_FIXATE)) {
 | 
				
			||||||
 | 
								uint32_t nvals, choice;
 | 
				
			||||||
 | 
								struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice);
 | 
				
			||||||
 | 
								const void *vals = SPA_POD_BODY(v);
 | 
				
			||||||
 | 
								if (spa_pod_compare_is_valid_choice(v->type, v->size,
 | 
				
			||||||
 | 
											vals, vals, nvals, choice)) {
 | 
				
			||||||
 | 
									((struct spa_pod_choice*)&res->value)->body.type = SPA_CHOICE_None;
 | 
				
			||||||
 | 
									count++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					SPA_API_POD_FILTER int spa_pod_filter_make(struct spa_pod *pod)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!spa_pod_is_object(pod))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						return spa_pod_filter_object_make((struct spa_pod_object *)pod);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \}
 | 
					 * \}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
#include <spa/node/utils.h>
 | 
					#include <spa/node/utils.h>
 | 
				
			||||||
#include <spa/pod/parser.h>
 | 
					#include <spa/pod/parser.h>
 | 
				
			||||||
#include <spa/pod/compare.h>
 | 
					#include <spa/pod/compare.h>
 | 
				
			||||||
 | 
					#include <spa/pod/filter.h>
 | 
				
			||||||
#include <spa/param/param.h>
 | 
					#include <spa/param/param.h>
 | 
				
			||||||
#include <spa/debug/types.h>
 | 
					#include <spa/debug/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -336,6 +337,8 @@ static int link_find_format(struct pw_impl_link *this,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (state[0] == PW_IMPL_PORT_STATE_CONFIGURE && state[1] == PW_IMPL_PORT_STATE_CONFIGURE) {
 | 
						} else if (state[0] == PW_IMPL_PORT_STATE_CONFIGURE && state[1] == PW_IMPL_PORT_STATE_CONFIGURE) {
 | 
				
			||||||
 | 
							bool do_filter = true;
 | 
				
			||||||
 | 
							int count = 0;
 | 
				
			||||||
	      again:
 | 
						      again:
 | 
				
			||||||
		/* both ports need a format, we start with a format from port 0 and use that
 | 
							/* both ports need a format, we start with a format from port 0 and use that
 | 
				
			||||||
		 * as a filter for port 1. Because the filter has higher priority, its
 | 
							 * as a filter for port 1. Because the filter has higher priority, its
 | 
				
			||||||
| 
						 | 
					@ -353,11 +356,20 @@ static int link_find_format(struct pw_impl_link *this,
 | 
				
			||||||
				if (res < 0)
 | 
									if (res < 0)
 | 
				
			||||||
					*error = spa_aprintf("error %s enum formats: %s", dir[0],
 | 
										*error = spa_aprintf("error %s enum formats: %s", dir[0],
 | 
				
			||||||
							spa_strerror(res));
 | 
												spa_strerror(res));
 | 
				
			||||||
				else
 | 
									else if (do_filter && count > 0) {
 | 
				
			||||||
 | 
										do_filter = false;
 | 
				
			||||||
 | 
										idx[0] = 0;
 | 
				
			||||||
 | 
										goto again;
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
					*error = spa_aprintf("no more %s formats", dir[0]);
 | 
										*error = spa_aprintf("no more %s formats", dir[0]);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				goto error;
 | 
									goto error;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (do_filter && filter)
 | 
				
			||||||
 | 
								if ((res = spa_pod_filter_make(filter)) > 0)
 | 
				
			||||||
 | 
									count += res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug("%p: enum %s %d with filter: %p", this, dir[1], idx[1], filter);
 | 
							pw_log_debug("%p: enum %s %d with filter: %p", this, dir[1], idx[1], filter);
 | 
				
			||||||
		pw_log_pod(SPA_LOG_LEVEL_DEBUG, filter);
 | 
							pw_log_pod(SPA_LOG_LEVEL_DEBUG, filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1069,6 +1081,7 @@ static void port_param_changed(struct pw_impl_link *this, uint32_t id,
 | 
				
			||||||
	if (inport)
 | 
						if (inport)
 | 
				
			||||||
		pw_impl_port_update_state(inport, target, 0, NULL);
 | 
							pw_impl_port_update_state(inport, target, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_info("%p: format changed", this);
 | 
				
			||||||
	this->preparing = this->prepared = false;
 | 
						this->preparing = this->prepared = false;
 | 
				
			||||||
	link_update_state(this, PW_LINK_STATE_INIT, 0, NULL);
 | 
						link_update_state(this, PW_LINK_STATE_INIT, 0, NULL);
 | 
				
			||||||
	pw_impl_link_prepare(this);
 | 
						pw_impl_link_prepare(this);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue