mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
link: improve renegotiation
Only suspend an idle node when we need to configure a different format.
This commit is contained in:
parent
910318d71f
commit
3b5a308645
20 changed files with 190 additions and 38 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
project('pipewire', 'c',
|
project('pipewire', 'c',
|
||||||
version : '0.0.1.1',
|
version : '0.1.0',
|
||||||
meson_version : '>= 0.36.0',
|
meson_version : '>= 0.36.0',
|
||||||
default_options : [ 'warning_level=1',
|
default_options : [ 'warning_level=1',
|
||||||
'c_std=gnu99',
|
'c_std=gnu99',
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ int pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_membl
|
||||||
return SPA_RESULT_ERRNO;
|
return SPA_RESULT_ERRNO;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
|
char filename[] = "/dev/shm/pipewire-tmpfile.XXXXXX";
|
||||||
mem->fd = mkostemp(filename, O_CLOEXEC);
|
mem->fd = mkostemp(filename, O_CLOEXEC);
|
||||||
if (mem->fd == -1) {
|
if (mem->fd == -1) {
|
||||||
pw_log_error("Failed to create temporary file: %s\n", strerror(errno));
|
pw_log_error("Failed to create temporary file: %s\n", strerror(errno));
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "spa/node.h"
|
#include "spa/node.h"
|
||||||
#include "spa/format-builder.h"
|
#include "spa/format-builder.h"
|
||||||
|
#include "spa/lib/format.h"
|
||||||
|
|
||||||
#include "pipewire/client/pipewire.h"
|
#include "pipewire/client/pipewire.h"
|
||||||
#include "pipewire/client/interfaces.h"
|
#include "pipewire/client/interfaces.h"
|
||||||
|
|
|
||||||
|
|
@ -611,6 +611,7 @@ struct spa_format *pw_core_find_format(struct pw_core *core,
|
||||||
|
|
||||||
pw_log_debug("core %p: finding best format %d %d", core, out_state, in_state);
|
pw_log_debug("core %p: finding best format %d %d", core, out_state, in_state);
|
||||||
|
|
||||||
|
/* when a port is configured but the node is idle, we can reconfigure with a different format */
|
||||||
if (out_state > PW_PORT_STATE_CONFIGURE && output->node->info.state == PW_NODE_STATE_IDLE)
|
if (out_state > PW_PORT_STATE_CONFIGURE && output->node->info.state == PW_NODE_STATE_IDLE)
|
||||||
out_state = PW_PORT_STATE_CONFIGURE;
|
out_state = PW_PORT_STATE_CONFIGURE;
|
||||||
if (in_state > PW_PORT_STATE_CONFIGURE && input->node->info.state == PW_NODE_STATE_IDLE)
|
if (in_state > PW_PORT_STATE_CONFIGURE && input->node->info.state == PW_NODE_STATE_IDLE)
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ struct pw_global;
|
||||||
*
|
*
|
||||||
* \subpage page_resource
|
* \subpage page_resource
|
||||||
*
|
*
|
||||||
|
* \subpage page_node
|
||||||
|
*
|
||||||
|
* \subpage page_link
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \page page_core Core
|
/** \page page_core Core
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <spa/video/format.h>
|
#include <spa/video/format.h>
|
||||||
#include <spa/pod-utils.h>
|
#include <spa/pod-utils.h>
|
||||||
|
|
||||||
|
#include <spa/lib/format.h>
|
||||||
#include <spa/lib/props.h>
|
#include <spa/lib/props.h>
|
||||||
|
|
||||||
#include "pipewire/client/pipewire.h"
|
#include "pipewire/client/pipewire.h"
|
||||||
|
|
@ -108,7 +109,7 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
|
||||||
{
|
{
|
||||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||||
int res = SPA_RESULT_ERROR, res2;
|
int res = SPA_RESULT_ERROR, res2;
|
||||||
struct spa_format *format;
|
struct spa_format *format, *current;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
|
|
||||||
if (in_state != PW_PORT_STATE_CONFIGURE && out_state != PW_PORT_STATE_CONFIGURE)
|
if (in_state != PW_PORT_STATE_CONFIGURE && out_state != PW_PORT_STATE_CONFIGURE)
|
||||||
|
|
@ -120,13 +121,39 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
|
||||||
if (format == NULL)
|
if (format == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
format = spa_format_copy(format);
|
||||||
|
|
||||||
if (out_state > PW_PORT_STATE_CONFIGURE && this->output->node->info.state == PW_NODE_STATE_IDLE) {
|
if (out_state > PW_PORT_STATE_CONFIGURE && this->output->node->info.state == PW_NODE_STATE_IDLE) {
|
||||||
pw_node_set_state(this->output->node, PW_NODE_STATE_SUSPENDED);
|
if ((res = spa_node_port_get_format(this->output->node->node,
|
||||||
out_state = PW_PORT_STATE_CONFIGURE;
|
SPA_DIRECTION_OUTPUT,
|
||||||
|
this->output->port_id,
|
||||||
|
(const struct spa_format **) ¤t)) < 0) {
|
||||||
|
asprintf(&error, "error get output format: %d", res);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (spa_format_compare(current, format) < 0) {
|
||||||
|
pw_log_debug("link %p: output format change, renegotiate", this);
|
||||||
|
pw_node_set_state(this->output->node, PW_NODE_STATE_SUSPENDED);
|
||||||
|
out_state = PW_PORT_STATE_CONFIGURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pw_node_update_state(this->output->node, PW_NODE_STATE_RUNNING, NULL);
|
||||||
}
|
}
|
||||||
if (in_state > PW_PORT_STATE_CONFIGURE && this->input->node->info.state == PW_NODE_STATE_IDLE) {
|
if (in_state > PW_PORT_STATE_CONFIGURE && this->input->node->info.state == PW_NODE_STATE_IDLE) {
|
||||||
pw_node_set_state(this->input->node, PW_NODE_STATE_SUSPENDED);
|
if ((res = spa_node_port_get_format(this->input->node->node,
|
||||||
in_state = PW_PORT_STATE_CONFIGURE;
|
SPA_DIRECTION_INPUT,
|
||||||
|
this->input->port_id,
|
||||||
|
(const struct spa_format **) ¤t)) < 0) {
|
||||||
|
asprintf(&error, "error get input format: %d", res);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (spa_format_compare(current, format) < 0) {
|
||||||
|
pw_log_debug("link %p: input format change, renegotiate", this);
|
||||||
|
pw_node_set_state(this->input->node, PW_NODE_STATE_SUSPENDED);
|
||||||
|
in_state = PW_PORT_STATE_CONFIGURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pw_node_update_state(this->input->node, PW_NODE_STATE_RUNNING, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pw_log_debug("link %p: doing set format", this);
|
pw_log_debug("link %p: doing set format", this);
|
||||||
|
|
@ -157,13 +184,18 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
|
||||||
pw_work_queue_add(impl->work, this->input->node, res2, complete_ready, this->input);
|
pw_work_queue_add(impl->work, this->input->node, res2, complete_ready, this->input);
|
||||||
res = res2 != SPA_RESULT_OK ? res2 : res;
|
res = res2 != SPA_RESULT_OK ? res2 : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->info.format)
|
||||||
|
free(this->info.format);
|
||||||
|
this->info.format = format;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
{
|
pw_link_update_state(this, PW_LINK_STATE_ERROR, error);
|
||||||
pw_link_update_state(this, PW_LINK_STATE_ERROR, error);
|
if (format)
|
||||||
return res;
|
free(format);
|
||||||
}
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct spa_param *find_param(struct spa_param **params, int n_params, uint32_t type)
|
static struct spa_param *find_param(struct spa_param **params, int n_params, uint32_t type)
|
||||||
|
|
@ -637,16 +669,14 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
{
|
this->output->buffers = NULL;
|
||||||
this->output->buffers = NULL;
|
this->output->n_buffers = 0;
|
||||||
this->output->n_buffers = 0;
|
this->output->allocated = false;
|
||||||
this->output->allocated = false;
|
this->input->buffers = NULL;
|
||||||
this->input->buffers = NULL;
|
this->input->n_buffers = 0;
|
||||||
this->input->n_buffers = 0;
|
this->input->allocated = false;
|
||||||
this->input->allocated = false;
|
pw_link_update_state(this, PW_LINK_STATE_ERROR, error);
|
||||||
pw_link_update_state(this, PW_LINK_STATE_ERROR, error);
|
return res;
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_start(struct pw_link *this, uint32_t in_state, uint32_t out_state)
|
static int do_start(struct pw_link *this, uint32_t in_state, uint32_t out_state)
|
||||||
|
|
@ -810,6 +840,9 @@ static void pw_link_free(struct pw_link *link)
|
||||||
|
|
||||||
pw_work_queue_destroy(impl->work);
|
pw_work_queue_destroy(impl->work);
|
||||||
|
|
||||||
|
if (link->info.format)
|
||||||
|
free(link->info.format);
|
||||||
|
|
||||||
if (impl->buffer_owner == link)
|
if (impl->buffer_owner == link)
|
||||||
pw_memblock_free(&impl->buffer_mem);
|
pw_memblock_free(&impl->buffer_mem);
|
||||||
|
|
||||||
|
|
@ -997,14 +1030,10 @@ do_link_remove(struct spa_loop *loop,
|
||||||
|
|
||||||
if (this->rt.input) {
|
if (this->rt.input) {
|
||||||
spa_list_remove(&this->rt.input_link);
|
spa_list_remove(&this->rt.input_link);
|
||||||
if (spa_list_is_empty(&this->rt.input->rt.links))
|
|
||||||
pw_port_pause_rt(this->rt.input);
|
|
||||||
this->rt.input = NULL;
|
this->rt.input = NULL;
|
||||||
}
|
}
|
||||||
if (this->rt.output) {
|
if (this->rt.output) {
|
||||||
spa_list_remove(&this->rt.output_link);
|
spa_list_remove(&this->rt.output_link);
|
||||||
if (spa_list_is_empty(&this->rt.output->rt.links))
|
|
||||||
pw_port_pause_rt(this->rt.output);
|
|
||||||
this->rt.output = NULL;
|
this->rt.output = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,17 @@ extern "C" {
|
||||||
#include <pipewire/server/port.h>
|
#include <pipewire/server/port.h>
|
||||||
#include <pipewire/server/main-loop.h>
|
#include <pipewire/server/main-loop.h>
|
||||||
|
|
||||||
|
/** \page page_link Link
|
||||||
|
*
|
||||||
|
* \section page_link_overview Overview
|
||||||
|
*
|
||||||
|
* A link is the connection between 2 nodes (\ref page_node). Nodes are
|
||||||
|
* linked together on ports.
|
||||||
|
*
|
||||||
|
* The link is responsible for negotiating the format and buffers for
|
||||||
|
* the nodes.
|
||||||
|
*/
|
||||||
|
|
||||||
/** \class pw_link
|
/** \class pw_link
|
||||||
*
|
*
|
||||||
* PipeWire link interface.
|
* PipeWire link interface.
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,16 @@ extern "C" {
|
||||||
#include <pipewire/server/client.h>
|
#include <pipewire/server/client.h>
|
||||||
#include <pipewire/server/data-loop.h>
|
#include <pipewire/server/data-loop.h>
|
||||||
|
|
||||||
|
/** \page page_node Node
|
||||||
|
*
|
||||||
|
* \section page_node_overview Overview
|
||||||
|
*
|
||||||
|
* The node object processes data. The node has a list of
|
||||||
|
* input and output ports (\ref page_port) on which it
|
||||||
|
* will receive and send out buffers respectively.
|
||||||
|
*
|
||||||
|
* The node wraps an SPA node object.
|
||||||
|
*/
|
||||||
/** \class pw_node
|
/** \class pw_node
|
||||||
*
|
*
|
||||||
* PipeWire node class.
|
* PipeWire node class.
|
||||||
|
|
|
||||||
|
|
@ -162,15 +162,11 @@ struct pw_link *pw_port_link(struct pw_port *output_port,
|
||||||
return link;
|
return link;
|
||||||
|
|
||||||
same_node:
|
same_node:
|
||||||
{
|
asprintf(error, "can't link a node to itself");
|
||||||
asprintf(error, "can't link a node to itself");
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
was_linked:
|
was_linked:
|
||||||
{
|
asprintf(error, "input port was already linked");
|
||||||
asprintf(error, "input port was already linked");
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
no_mem:
|
no_mem:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,6 @@ spa_pod_builder_push_format(struct spa_pod_builder *builder,
|
||||||
SPA_POD_TYPE_ID,media_subtype, \
|
SPA_POD_TYPE_ID,media_subtype, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
|
|
||||||
int
|
|
||||||
spa_format_filter(const struct spa_format *format,
|
|
||||||
const struct spa_format *filter,
|
|
||||||
struct spa_pod_builder *result);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -59,3 +59,20 @@ spa_format_filter(const struct spa_format *format,
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spa_format_compare(const struct spa_format *format1,
|
||||||
|
const struct spa_format *format2)
|
||||||
|
{
|
||||||
|
if (format1 == NULL || format2 == NULL)
|
||||||
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
if (SPA_FORMAT_MEDIA_TYPE(format1) != SPA_FORMAT_MEDIA_TYPE(format2) ||
|
||||||
|
SPA_FORMAT_MEDIA_SUBTYPE(format1) != SPA_FORMAT_MEDIA_SUBTYPE(format2))
|
||||||
|
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||||
|
|
||||||
|
return spa_props_compare(SPA_POD_CONTENTS(struct spa_format, format1),
|
||||||
|
SPA_POD_CONTENTS_SIZE(struct spa_format, format1),
|
||||||
|
SPA_POD_CONTENTS(struct spa_format, format2),
|
||||||
|
SPA_POD_CONTENTS_SIZE(struct spa_format, format2));
|
||||||
|
}
|
||||||
|
|
|
||||||
40
spa/lib/format.h
Normal file
40
spa/lib/format.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* Simple Plugin API
|
||||||
|
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPA_LIBFORMAT_H__
|
||||||
|
#define __SPA_LIBFORMAT_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <spa/props.h>
|
||||||
|
|
||||||
|
int spa_format_filter(const struct spa_format *format,
|
||||||
|
const struct spa_format *filter,
|
||||||
|
struct spa_pod_builder *result);
|
||||||
|
|
||||||
|
int spa_format_compare(const struct spa_format *format1,
|
||||||
|
const struct spa_format *format2);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SPA_LIBFORMAT_H__ */
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
spalib_headers = [
|
spalib_headers = [
|
||||||
'debug.h',
|
'debug.h',
|
||||||
|
'format.h',
|
||||||
'props.h',
|
'props.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -310,3 +310,40 @@ spa_props_filter(struct spa_pod_builder *b,
|
||||||
}
|
}
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spa_props_compare(const struct spa_pod *props1,
|
||||||
|
uint32_t props1_size,
|
||||||
|
const struct spa_pod *props2,
|
||||||
|
uint32_t props2_size)
|
||||||
|
{
|
||||||
|
const struct spa_pod *pr;
|
||||||
|
|
||||||
|
SPA_POD_FOREACH(props1, props1_size, pr) {
|
||||||
|
struct spa_pod_prop *p1, *p2;
|
||||||
|
void *a1, *a2;
|
||||||
|
|
||||||
|
if (pr->type != SPA_POD_TYPE_PROP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p1 = (struct spa_pod_prop *) pr;
|
||||||
|
|
||||||
|
if ((p2 = find_prop(props2, props2_size, p1->body.key)) == NULL)
|
||||||
|
return SPA_RESULT_INCOMPATIBLE_PROPS;
|
||||||
|
|
||||||
|
/* incompatible property types */
|
||||||
|
if (p1->body.value.type != p2->body.value.type)
|
||||||
|
return SPA_RESULT_INCOMPATIBLE_PROPS;
|
||||||
|
|
||||||
|
if (p1->body.flags & SPA_POD_PROP_FLAG_UNSET ||
|
||||||
|
p2->body.flags & SPA_POD_PROP_FLAG_UNSET)
|
||||||
|
return SPA_RESULT_INCOMPATIBLE_PROPS;
|
||||||
|
|
||||||
|
a1 = SPA_MEMBER(p1, sizeof(struct spa_pod_prop), void);
|
||||||
|
a2 = SPA_MEMBER(p2, sizeof(struct spa_pod_prop), void);
|
||||||
|
|
||||||
|
if (compare_value(p1->body.value.type, a1, a2) != 0)
|
||||||
|
return SPA_RESULT_INCOMPATIBLE_PROPS;
|
||||||
|
}
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ int spa_props_filter(struct spa_pod_builder *b,
|
||||||
const struct spa_pod *filter,
|
const struct spa_pod *filter,
|
||||||
uint32_t filter_size);
|
uint32_t filter_size);
|
||||||
|
|
||||||
|
int spa_props_compare(const struct spa_pod *props1,
|
||||||
|
uint32_t props1_size,
|
||||||
|
const struct spa_pod *props2,
|
||||||
|
uint32_t props2_size);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
|
|
||||||
#include <lib/debug.h>
|
#include <lib/debug.h>
|
||||||
|
#include <lib/format.h>
|
||||||
|
|
||||||
#include "alsa-utils.h"
|
#include "alsa-utils.h"
|
||||||
|
|
||||||
#define CHECK(s,msg) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", snd_strerror(err)); return err; }
|
#define CHECK(s,msg) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", snd_strerror(err)); return err; }
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <spa/node.h>
|
#include <spa/node.h>
|
||||||
#include <spa/audio/format-utils.h>
|
#include <spa/audio/format-utils.h>
|
||||||
#include <spa/format-builder.h>
|
#include <spa/format-builder.h>
|
||||||
|
#include <lib/format.h>
|
||||||
#include <lib/props.h>
|
#include <lib/props.h>
|
||||||
|
|
||||||
#define NAME "audiomixer"
|
#define NAME "audiomixer"
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <spa/list.h>
|
#include <spa/list.h>
|
||||||
#include <spa/audio/format-utils.h>
|
#include <spa/audio/format-utils.h>
|
||||||
#include <spa/format-builder.h>
|
#include <spa/format-builder.h>
|
||||||
|
#include <lib/format.h>
|
||||||
#include <lib/props.h>
|
#include <lib/props.h>
|
||||||
|
|
||||||
#define NAME "audiotestsrc"
|
#define NAME "audiotestsrc"
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#include <spa/list.h>
|
#include <spa/list.h>
|
||||||
#include <spa/video/format-utils.h>
|
#include <spa/video/format-utils.h>
|
||||||
#include <spa/format-builder.h>
|
#include <spa/format-builder.h>
|
||||||
|
|
||||||
|
#include <lib/format.h>
|
||||||
#include <lib/props.h>
|
#include <lib/props.h>
|
||||||
|
|
||||||
#define NAME "videotestsrc"
|
#define NAME "videotestsrc"
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <spa/format-builder.h>
|
#include <spa/format-builder.h>
|
||||||
#include <spa/param-alloc.h>
|
#include <spa/param-alloc.h>
|
||||||
#include <lib/props.h>
|
#include <lib/props.h>
|
||||||
|
#include <lib/format.h>
|
||||||
|
|
||||||
#define NAME "volume"
|
#define NAME "volume"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue