diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index ecab1b093..758d994b6 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -34,73 +34,72 @@ #define MAX_PORTS 128 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + struct spa_list link; }; struct port { - struct spa_port_io *io; + struct spa_port_io *io; - bool have_format; - struct spa_port_info info; + bool have_format; + struct spa_port_info info; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - struct spa_list queue; - size_t queued_offset; - size_t queued_bytes; + struct spa_list queue; + size_t queued_offset; + size_t queued_bytes; }; struct type { - uint32_t node; - uint32_t format; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_audio format_audio; - struct spa_type_audio_format audio_format; - struct spa_type_command_node command_node; - struct spa_type_meta meta; - struct spa_type_data data; + uint32_t node; + uint32_t format; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_audio format_audio; + struct spa_type_audio_format audio_format; + struct spa_type_command_node command_node; + struct spa_type_meta meta; + struct spa_type_data data; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_audio_map (map, &type->format_audio); - spa_type_audio_format_map (map, &type->audio_format); - spa_type_command_node_map (map, &type->command_node); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_audio_map(map, &type->format_audio); + spa_type_audio_format_map(map, &type->audio_format); + spa_type_command_node_map(map, &type->command_node); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); } struct impl { - struct spa_handle handle; - struct spa_node node; + struct spa_handle handle; + struct spa_node node; - struct type type; - struct spa_type_map *map; - struct spa_log *log; + struct type type; + struct spa_type_map *map; + struct spa_log *log; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - int port_count; - int port_queued; - struct port in_ports[MAX_PORTS]; - struct port out_ports[1]; + int port_count; + int port_queued; + struct port in_ports[MAX_PORTS]; + struct port out_ports[1]; - bool have_format; - struct spa_audio_info format; - uint8_t format_buffer[4096]; + bool have_format; + struct spa_audio_info format; + uint8_t format_buffer[4096]; - bool started; + bool started; }; #define CHECK_PORT_NUM(this,d,p) (((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS) || \ @@ -123,786 +122,771 @@ struct impl { SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + this->started = true; + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + this->started = false; + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + this->callbacks = *callbacks; + this->user_data = user_data; + + return SPA_RESULT_OK; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports) + *n_input_ports = 0; + if (max_input_ports) + *max_input_ports = MAX_PORTS; + if (n_output_ports) + *n_output_ports = 1; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - this->started = true; - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - this->started = false; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this; + struct impl *this; + int i, idx; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - this->callbacks = *callbacks; - this->user_data = user_data; + if (input_ids) { + for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) { + if (this->in_ports[i].io) + input_ids[idx++] = i; + } + } + if (n_output_ports > 0 && output_ids) + output_ids[0] = 0; - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_FREE_IN_PORT(this, direction, port_id), + SPA_RESULT_INVALID_PORT); + + this->port_count++; + spa_list_init(&this->in_ports[port_id].queue); + + this->in_ports[port_id].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | + SPA_PORT_INFO_FLAG_REMOVABLE | + SPA_PORT_INFO_FLAG_OPTIONAL | SPA_PORT_INFO_FLAG_IN_PLACE; + return SPA_RESULT_OK; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; + struct spa_port_io *io; - if (n_input_ports) - *n_input_ports = 0; - if (max_input_ports) - *max_input_ports = MAX_PORTS; - if (n_output_ports) - *n_output_ports = 1; - if (max_output_ports) - *max_output_ports = 1; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; -} + this = SPA_CONTAINER_OF(node, struct impl, node); -static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - struct impl *this; - int i, idx; + spa_return_val_if_fail(CHECK_IN_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + io = this->in_ports[port_id].io; + if (io && io->buffer_id) + this->port_queued--; - this = SPA_CONTAINER_OF (node, struct impl, node); + this->in_ports[port_id].io = NULL; + this->port_count--; - if (input_ids) { - for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) { - if (this->in_ports[i].io) - input_ids[idx++] = i; - } - } - if (n_output_ports > 0 && output_ids) - output_ids[0] = 0; - - return SPA_RESULT_OK; -} - -static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_FREE_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->port_count++; - spa_list_init (&this->in_ports[port_id].queue); - - this->in_ports[port_id].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_REMOVABLE | - SPA_PORT_INFO_FLAG_OPTIONAL | - SPA_PORT_INFO_FLAG_IN_PLACE; - return SPA_RESULT_OK; -} - -static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) -{ - struct impl *this; - struct spa_port_io *io; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - io = this->in_ports[port_id].io; - if (io && io->buffer_id) - this->port_queued--; - - this->in_ports[port_id].io = NULL; - this->port_count--; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - struct impl *this; - int res; - struct spa_format *fmt; - uint8_t buffer[256]; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - uint32_t count, match; + struct impl *this; + int res; + struct spa_format *fmt; + uint8_t buffer[256]; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + uint32_t count, match; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - count = match = filter ? 0 : index; + count = match = filter ? 0 : index; -next: - spa_pod_builder_init (&b, buffer, sizeof (buffer)); + next: + spa_pod_builder_init(&b, buffer, sizeof(buffer)); - switch (count++) { - case 0: - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.audio, this->type.media_subtype.raw, - PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->type.audio_format.S16), - PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), - PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); - break; - default: - return SPA_RESULT_ENUM_END; - } - fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); + switch (count++) { + case 0: + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.audio, + this->type.media_subtype.raw, + PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, + this->type.audio_format.S16), + PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, + 44100, + 1, INT32_MAX), + PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, + 2, + 1, INT32_MAX)); + break; + default: + return SPA_RESULT_ENUM_END; + } + fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); - if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) - goto next; + if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) + goto next; - *format = SPA_POD_BUILDER_DEREF (&b, 0, struct spa_format); + *format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int clear_buffers(struct impl *this, struct port *port) +{ + if (port->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers %p", this, port); + port->n_buffers = 0; + spa_list_init(&port->queue); + } + return SPA_RESULT_OK; } static int -clear_buffers (struct impl *this, struct port *port) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - if (port->n_buffers > 0) { - spa_log_info (this->log, "audio-mixer %p: clear buffers %p", this, port); - port->n_buffers = 0; - spa_list_init (&port->queue); - } - return SPA_RESULT_OK; + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; + + if (format == NULL) { + port->have_format = false; + clear_buffers(this, port); + } else { + struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; + + if (info.media_type != this->type.media_type.audio || + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + this->format = info; + port->have_format = true; + } + + return SPA_RESULT_OK; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; - if (format == NULL) { - port->have_format = false; - clear_buffers (this, port); - } else { - struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; - if (info.media_type != this->type.media_type.audio || - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.audio, + this->type.media_subtype.raw, + PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, + this->format.info.raw.format), + PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, + this->format.info.raw.rate), + PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, + this->format.info.raw.channels)); + *format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); - if (!spa_format_audio_raw_parse (format, &info.info.raw, &this->type.format_audio)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - this->format = info; - port->have_format = true; - } - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - struct impl *this; - struct port *port; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct port *port; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; + port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; + *info = &port->info; - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; - - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.audio, this->type.media_subtype.raw, - PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->format.info.raw.format), - PROP (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, this->format.info.raw.rate), - PROP (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, this->format.info.raw.channels)); - *format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - struct impl *this; - struct port *port; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[0]; - *info = &port->info; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct port *port; + uint32_t i; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + + spa_return_val_if_fail(port->have_format, SPA_RESULT_NO_FORMAT); + + clear_buffers(this, port); + + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; + + b = &port->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = direction == SPA_DIRECTION_INPUT ? true : false; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + + if (!((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data != NULL)) { + spa_log_error(this->log, "volume %p: invalid memory on buffer %p", this, + buffers[i]); + return SPA_RESULT_ERROR; + } + if (!b->outstanding) + spa_list_insert(port->queue.prev, &b->link); + } + port->n_buffers = n_buffers; + + return SPA_RESULT_OK; } static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - struct impl *this; - struct port *port; - uint32_t i; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - - spa_return_val_if_fail (port->have_format, SPA_RESULT_NO_FORMAT); - - clear_buffers (this, port); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &port->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = direction == SPA_DIRECTION_INPUT ? true : false; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - - if (!((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data != NULL)) { - spa_log_error (this->log, "volume %p: invalid memory on buffer %p", this, buffers[i]); - return SPA_RESULT_ERROR; - } - if (!b->outstanding) - spa_list_insert (port->queue.prev, &b->link); - } - port->n_buffers = n_buffers; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT_NUM(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port->io = io; + + return SPA_RESULT_OK; +} + +static void recycle_buffer(struct impl *this, uint32_t id) +{ + struct port *port = &this->out_ports[0]; + struct buffer *b = &port->buffers[id]; + + if (!b->outstanding) { + spa_log_warn(this->log, NAME "%p: buffer %d not outstanding", this, id); + return; + } + + spa_list_insert(port->queue.prev, &b->link); + b->outstanding = false; + spa_log_trace(this->log, NAME " %p: recycle buffer %d", this, id); +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), + SPA_RESULT_INVALID_PORT); + + recycle_buffer(this, buffer_id); + + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; - struct port *port; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - port->io = io; - - return SPA_RESULT_OK; -} - -static void -recycle_buffer (struct impl *this, uint32_t id) -{ - struct port *port = &this->out_ports[0]; - struct buffer *b = &port->buffers[id]; - - if (!b->outstanding) { - spa_log_warn (this->log, NAME "%p: buffer %d not outstanding", this, id); - return; - } - - spa_list_insert (port->queue.prev, &b->link); - b->outstanding = false; - spa_log_trace (this->log, NAME " %p: recycle buffer %d", this, id); -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, SPA_DIRECTION_OUTPUT, port_id), SPA_RESULT_INVALID_PORT); - - recycle_buffer (this, buffer_id); - - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static inline void -add_port_data (struct impl *this, void *out, size_t outsize, struct port *port, int layer) +add_port_data(struct impl *this, void *out, size_t outsize, struct port *port, int layer) { - void *in; - size_t insize; - struct buffer *b; - struct spa_data *id; + void *in; + size_t insize; + struct buffer *b; + struct spa_data *id; - b = spa_list_first (&port->queue, struct buffer, link); + b = spa_list_first(&port->queue, struct buffer, link); - id = b->outbuf->datas; - in = SPA_MEMBER (id[0].data, port->queued_offset + id[0].chunk->offset, void); - insize = id[0].chunk->size - port->queued_offset; - outsize = SPA_MIN (outsize, insize); + id = b->outbuf->datas; + in = SPA_MEMBER(id[0].data, port->queued_offset + id[0].chunk->offset, void); + insize = id[0].chunk->size - port->queued_offset; + outsize = SPA_MIN(outsize, insize); - { - int i, size = outsize / 2; - int16_t *op = out, *ip = in; + { + int i, size = outsize / 2; + int16_t *op = out, *ip = in; - if (layer == 0) { - memcpy (op, ip, outsize); - } - else { - for (i = 0; i < size; i++) - op[i] = SPA_CLAMP (op[i] + ip[i], INT16_MIN, INT16_MAX); - } - } + if (layer == 0) { + memcpy(op, ip, outsize); + } else { + for (i = 0; i < size; i++) + op[i] = SPA_CLAMP(op[i] + ip[i], INT16_MIN, INT16_MAX); + } + } - port->queued_offset += outsize; - port->queued_bytes -= outsize; + port->queued_offset += outsize; + port->queued_bytes -= outsize; - if (outsize == insize) { - spa_log_trace (this->log, NAME " %p: return buffer %d on port %p %zd", - this, b->outbuf->id, port, outsize); - port->io->buffer_id = b->outbuf->id; - spa_list_remove (&b->link); - b->outstanding = true; - port->queued_offset = 0; - } else { - spa_log_trace (this->log, NAME " %p: keeping buffer %d on port %p %zd %zd", - this, b->outbuf->id, port, port->queued_bytes, outsize); - } + if (outsize == insize) { + spa_log_trace(this->log, NAME " %p: return buffer %d on port %p %zd", + this, b->outbuf->id, port, outsize); + port->io->buffer_id = b->outbuf->id; + spa_list_remove(&b->link); + b->outstanding = true; + port->queued_offset = 0; + } else { + spa_log_trace(this->log, NAME " %p: keeping buffer %d on port %p %zd %zd", + this, b->outbuf->id, port, port->queued_bytes, outsize); + } } -static int -mix_output (struct impl *this, size_t n_bytes) +static int mix_output(struct impl *this, size_t n_bytes) { - struct buffer *outbuf; - int i, layer; - struct port *outport; - struct spa_port_io *output; - struct spa_data *od; + struct buffer *outbuf; + int i, layer; + struct port *outport; + struct spa_port_io *output; + struct spa_data *od; - outport = &this->out_ports[0]; - output = outport->io; + outport = &this->out_ports[0]; + output = outport->io; - if (spa_list_is_empty (&outport->queue)) - return SPA_RESULT_OUT_OF_BUFFERS; + if (spa_list_is_empty(&outport->queue)) + return SPA_RESULT_OUT_OF_BUFFERS; - outbuf = spa_list_first (&outport->queue, struct buffer, link); - spa_list_remove (&outbuf->link); - outbuf->outstanding = true; + outbuf = spa_list_first(&outport->queue, struct buffer, link); + spa_list_remove(&outbuf->link); + outbuf->outstanding = true; - od = outbuf->outbuf->datas; - n_bytes = SPA_MIN (n_bytes, od[0].maxsize); - od[0].chunk->offset = 0; - od[0].chunk->size = n_bytes; - od[0].chunk->stride = 0; + od = outbuf->outbuf->datas; + n_bytes = SPA_MIN(n_bytes, od[0].maxsize); + od[0].chunk->offset = 0; + od[0].chunk->size = n_bytes; + od[0].chunk->stride = 0; - spa_log_trace (this->log, NAME " %p: dequeue output buffer %d %zd", - this, outbuf->outbuf->id, n_bytes); - for (layer = 0, i = 0; i < MAX_PORTS; i++) { - struct port *port = &this->in_ports[i]; + spa_log_trace(this->log, NAME " %p: dequeue output buffer %d %zd", + this, outbuf->outbuf->id, n_bytes); + for (layer = 0, i = 0; i < MAX_PORTS; i++) { + struct port *port = &this->in_ports[i]; - if (port->io == NULL || port->n_buffers == 0) - continue; + if (port->io == NULL || port->n_buffers == 0) + continue; - if (spa_list_is_empty (&port->queue)) { - spa_log_warn (this->log, NAME " %p: underrun stream %d", this, i); - port->queued_bytes = 0; - port->queued_offset = 0; - continue; - } - add_port_data (this, od[0].data, n_bytes, port, layer++); - } - output->buffer_id = outbuf->outbuf->id; - output->status = SPA_RESULT_HAVE_BUFFER; + if (spa_list_is_empty(&port->queue)) { + spa_log_warn(this->log, NAME " %p: underrun stream %d", this, i); + port->queued_bytes = 0; + port->queued_offset = 0; + continue; + } + add_port_data(this, od[0].data, n_bytes, port, layer++); + } + output->buffer_id = outbuf->outbuf->id; + output->status = SPA_RESULT_HAVE_BUFFER; - return SPA_RESULT_HAVE_BUFFER; + return SPA_RESULT_HAVE_BUFFER; } -static int -impl_node_process_input (struct spa_node *node) +static int impl_node_process_input(struct spa_node *node) { - struct impl *this; - uint32_t i; - struct port *outport; - size_t min_queued = SIZE_MAX; - struct spa_port_io *output; + struct impl *this; + uint32_t i; + struct port *outport; + size_t min_queued = SIZE_MAX; + struct spa_port_io *output; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - outport = &this->out_ports[0]; - output = outport->io; - spa_return_val_if_fail (output != NULL, SPA_RESULT_ERROR); + outport = &this->out_ports[0]; + output = outport->io; + spa_return_val_if_fail(output != NULL, SPA_RESULT_ERROR); - if (output->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; + if (output->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - for (i = 0; i < MAX_PORTS; i++) { - struct port *port = &this->in_ports[i]; - struct spa_port_io *input; + for (i = 0; i < MAX_PORTS; i++) { + struct port *port = &this->in_ports[i]; + struct spa_port_io *input; - if ((input = port->io) == NULL || port->n_buffers == 0) - continue; + if ((input = port->io) == NULL || port->n_buffers == 0) + continue; - if (port->queued_bytes == 0 && - input->status == SPA_RESULT_HAVE_BUFFER && - input->buffer_id != SPA_ID_INVALID) { - struct buffer *b = &port->buffers[input->buffer_id]; + if (port->queued_bytes == 0 && + input->status == SPA_RESULT_HAVE_BUFFER && input->buffer_id != SPA_ID_INVALID) { + struct buffer *b = &port->buffers[input->buffer_id]; - if (!b->outstanding) { - spa_log_warn (this->log, NAME " %p: buffer %u in use", this, input->buffer_id); - input->status = SPA_RESULT_INVALID_BUFFER_ID; - continue; - } + if (!b->outstanding) { + spa_log_warn(this->log, NAME " %p: buffer %u in use", this, + input->buffer_id); + input->status = SPA_RESULT_INVALID_BUFFER_ID; + continue; + } - b->outstanding = false; - input->buffer_id = SPA_ID_INVALID; - input->status = SPA_RESULT_OK; + b->outstanding = false; + input->buffer_id = SPA_ID_INVALID; + input->status = SPA_RESULT_OK; - spa_list_insert (port->queue.prev, &b->link); - port->queued_bytes += b->outbuf->datas[0].chunk->size; + spa_list_insert(port->queue.prev, &b->link); + port->queued_bytes += b->outbuf->datas[0].chunk->size; - spa_log_trace (this->log, NAME " %p: queue buffer %d on port %d %zd %zd", - this, b->outbuf->id, i, port->queued_bytes, min_queued); - } - if (port->queued_bytes > 0 && port->queued_bytes < min_queued) - min_queued = port->queued_bytes; - } + spa_log_trace(this->log, NAME " %p: queue buffer %d on port %d %zd %zd", + this, b->outbuf->id, i, port->queued_bytes, min_queued); + } + if (port->queued_bytes > 0 && port->queued_bytes < min_queued) + min_queued = port->queued_bytes; + } - if (min_queued != SIZE_MAX && min_queued > 0) { - output->status = mix_output (this, min_queued); - } else { - output->status = SPA_RESULT_NEED_BUFFER; - } - return output->status; + if (min_queued != SIZE_MAX && min_queued > 0) { + output->status = mix_output(this, min_queued); + } else { + output->status = SPA_RESULT_NEED_BUFFER; + } + return output->status; } -static int -impl_node_process_output (struct spa_node *node) +static int impl_node_process_output(struct spa_node *node) { - struct impl *this; - struct port *port; - struct spa_port_io *output; - int i; - size_t min_queued = SIZE_MAX; + struct impl *this; + struct port *port; + struct spa_port_io *output; + int i; + size_t min_queued = SIZE_MAX; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - port = &this->out_ports[0]; - output = port->io; - spa_return_val_if_fail (output != NULL, SPA_RESULT_ERROR); + port = &this->out_ports[0]; + output = port->io; + spa_return_val_if_fail(output != NULL, SPA_RESULT_ERROR); - if (output->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; + if (output->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - /* recycle */ - if (output->buffer_id != SPA_ID_INVALID) { - recycle_buffer (this, output->buffer_id); - output->buffer_id = SPA_ID_INVALID; - } - /* produce more output if possible */ - for (i = 0; i < MAX_PORTS; i++) { - struct port *port = &this->in_ports[i]; + /* recycle */ + if (output->buffer_id != SPA_ID_INVALID) { + recycle_buffer(this, output->buffer_id); + output->buffer_id = SPA_ID_INVALID; + } + /* produce more output if possible */ + for (i = 0; i < MAX_PORTS; i++) { + struct port *port = &this->in_ports[i]; - if (port->io == NULL || port->n_buffers == 0) - continue; + if (port->io == NULL || port->n_buffers == 0) + continue; - if (port->queued_bytes < min_queued) - min_queued = port->queued_bytes; - } - if (min_queued != SIZE_MAX && min_queued > 0) { - output->status = mix_output (this, min_queued); - } - else { - /* take requested output range and apply to input */ - for (i = 0; i < MAX_PORTS; i++) { - struct port *port = &this->in_ports[i]; - struct spa_port_io *input; + if (port->queued_bytes < min_queued) + min_queued = port->queued_bytes; + } + if (min_queued != SIZE_MAX && min_queued > 0) { + output->status = mix_output(this, min_queued); + } else { + /* take requested output range and apply to input */ + for (i = 0; i < MAX_PORTS; i++) { + struct port *port = &this->in_ports[i]; + struct spa_port_io *input; - if ((input = port->io) == NULL || port->n_buffers == 0) - continue; + if ((input = port->io) == NULL || port->n_buffers == 0) + continue; - if (port->queued_bytes == 0) { - input->range = output->range; - input->status = SPA_RESULT_NEED_BUFFER; - } - else { - input->status = SPA_RESULT_OK; - } - spa_log_trace (this->log, NAME " %p: port %d %d queued %zd, res %d", this, - i, output->range.min_size, port->queued_bytes, input->status); - } - } - return output->status; + if (port->queued_bytes == 0) { + input->range = output->range; + input->status = SPA_RESULT_NEED_BUFFER; + } else { + input->status = SPA_RESULT_OK; + } + spa_log_trace(this->log, NAME " %p: port %d %d queued %zd, res %d", this, + i, output->range.min_size, port->queued_bytes, input->status); + } + } + return output->status; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.node) + *interface = &this->node; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "an id-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + + this->out_ports[0].io = NULL; + this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | + SPA_PORT_INFO_FLAG_NO_REF; + spa_list_init(&this->out_ports[0].queue); + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "an id-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - - this->out_ports[0].io = NULL; - this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - spa_list_init (&this->out_ports[0].queue); - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_audiomixer_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_audiomixer_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/audiomixer/plugin.c b/spa/plugins/audiomixer/plugin.c index 99687238d..fd3bacda4 100644 --- a/spa/plugins/audiomixer/plugin.c +++ b/spa/plugins/audiomixer/plugin.c @@ -23,11 +23,9 @@ extern const struct spa_handle_factory spa_audiomixer_factory; int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) +spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); switch (index) { case 0: diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 2ec45806f..f8489aea9 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -34,137 +34,136 @@ #include #include -#define IMPL_NAME "audiotestsrc" +#define NAME "audiotestsrc" #define SAMPLES_TO_TIME(this,s) ((s) * SPA_NSEC_PER_SEC / (this)->current_format.info.raw.rate) #define BYTES_TO_SAMPLES(this,b) ((b)/(this)->bpf) #define BYTES_TO_TIME(this,b) SAMPLES_TO_TIME(this, BYTES_TO_SAMPLES (this, b)) struct type { - uint32_t node; - uint32_t clock; - uint32_t format; - uint32_t props; - uint32_t prop_live; - uint32_t prop_wave; - uint32_t prop_freq; - uint32_t prop_volume; - uint32_t wave_sine; - uint32_t wave_square; - struct spa_type_meta meta; - struct spa_type_data data; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_audio format_audio; - struct spa_type_audio_format audio_format; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + uint32_t node; + uint32_t clock; + uint32_t format; + uint32_t props; + uint32_t prop_live; + uint32_t prop_wave; + uint32_t prop_freq; + uint32_t prop_volume; + uint32_t wave_sine; + uint32_t wave_square; + struct spa_type_meta meta; + struct spa_type_data data; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_audio format_audio; + struct spa_type_audio_format audio_format; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->clock = spa_type_map_get_id (map, SPA_TYPE__Clock); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_live = spa_type_map_get_id (map, SPA_TYPE_PROPS__live); - type->prop_wave = spa_type_map_get_id (map, SPA_TYPE_PROPS__waveType); - type->prop_freq = spa_type_map_get_id (map, SPA_TYPE_PROPS__frequency); - type->prop_volume = spa_type_map_get_id (map, SPA_TYPE_PROPS__volume); - type->wave_sine = spa_type_map_get_id (map, SPA_TYPE_PROPS__waveType ":sine"); - type->wave_square = spa_type_map_get_id (map, SPA_TYPE_PROPS__waveType ":square"); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_audio_map (map, &type->format_audio); - spa_type_audio_format_map (map, &type->audio_format); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->clock = spa_type_map_get_id(map, SPA_TYPE__Clock); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live); + type->prop_wave = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType); + type->prop_freq = spa_type_map_get_id(map, SPA_TYPE_PROPS__frequency); + type->prop_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume); + type->wave_sine = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":sine"); + type->wave_square = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":square"); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_audio_map(map, &type->format_audio); + spa_type_audio_format_map(map, &type->audio_format); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); } struct props { - bool live; - uint32_t wave; - double freq; - double volume; + bool live; + uint32_t wave; + double freq; + double volume; }; #define MAX_BUFFERS 16 +#define MAX_PORTS 1 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - struct spa_meta_ringbuffer *rb; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + struct spa_meta_ringbuffer *rb; + struct spa_list link; }; struct impl; -typedef int (*render_func_t) (struct impl *this, void *samples, size_t n_samples); +typedef int (*render_func_t) (struct impl * this, void *samples, size_t n_samples); struct impl { - struct spa_handle handle; - struct spa_node node; - struct spa_clock clock; + struct spa_handle handle; + struct spa_node node; + struct spa_clock clock; - struct type type; - struct spa_type_map *map; - struct spa_log *log; - struct spa_loop *data_loop; + struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct spa_loop *data_loop; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct spa_source timer_source; - struct itimerspec timerspec; + struct spa_source timer_source; + struct itimerspec timerspec; - struct spa_port_info info; - uint32_t params[2]; - uint8_t params_buffer[1024]; - struct spa_port_io *io; + struct spa_port_info info; + uint8_t params_buffer[1024]; + struct spa_port_io *io; - bool have_format; - struct spa_audio_info current_format; - uint8_t format_buffer[1024]; - size_t bpf; - render_func_t render_func; - double accumulator; + bool have_format; + struct spa_audio_info current_format; + uint8_t format_buffer[1024]; + size_t bpf; + render_func_t render_func; + double accumulator; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - bool started; - uint64_t start_time; - uint64_t elapsed_time; + bool started; + uint64_t start_time; + uint64_t elapsed_time; - uint64_t sample_count; - struct spa_list empty; + uint64_t sample_count; + struct spa_list empty; }; -#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0) +#define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS) +#define CHECK_PORT(this,d,p) (CHECK_PORT_NUM(this,d,p) && this->io) #define DEFAULT_LIVE true #define DEFAULT_WAVE wave_sine #define DEFAULT_FREQ 440.0 #define DEFAULT_VOLUME 1.0 -static void -impl_reset_props (struct impl *this, struct props *props) +static void reset_props(struct impl *this, struct props *props) { - props->live = DEFAULT_LIVE; - props->wave = this->type. DEFAULT_WAVE; - props->freq = DEFAULT_FREQ; - props->volume = DEFAULT_VOLUME; + props->live = DEFAULT_LIVE; + props->wave = this->type.DEFAULT_WAVE; + props->freq = DEFAULT_FREQ; + props->volume = DEFAULT_VOLUME; } #define PROP(f,key,type,...) \ @@ -180,907 +179,891 @@ impl_reset_props (struct impl *this, struct props *props) SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, this->props.live), - PROP_EN (&f[1], this->type.prop_wave, SPA_POD_TYPE_ID, 3, this->props.wave, - this->type.wave_sine, - this->type.wave_square), - PROP_MM (&f[1], this->type.prop_freq, SPA_POD_TYPE_DOUBLE, this->props.freq, - 0.0, 50000000.0), - PROP_MM (&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE, this->props.volume, - 0.0, 10.0)); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, + this->props.live), + PROP_EN(&f[1], this->type.prop_wave, SPA_POD_TYPE_ID, 3, + this->props.wave, + this->type.wave_sine, + this->type.wave_square), + PROP_MM(&f[1], this->type.prop_freq, SPA_POD_TYPE_DOUBLE, + this->props.freq, + 0.0, 50000000.0), + PROP_MM(&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE, + this->props.volume, + 0.0, 10.0)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (props == NULL) { - impl_reset_props (this, &this->props); - } else { - spa_props_query (props, - this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, - this->type.prop_wave, SPA_POD_TYPE_ID, &this->props.wave, - this->type.prop_freq, SPA_POD_TYPE_DOUBLE, &this->props.freq, - this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume, - 0); - } + if (props == NULL) { + reset_props(this, &this->props); + } else { + spa_props_query(props, + this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, + this->type.prop_wave, SPA_POD_TYPE_ID, &this->props.wave, + this->type.prop_freq, SPA_POD_TYPE_DOUBLE, &this->props.freq, + this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume, + 0); + } - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - else - this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + else + this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; - return SPA_RESULT_OK; -} - -static inline int -send_have_output (struct impl *this) -{ - if (this->callbacks.have_output) - this->callbacks.have_output (&this->node, this->user_data); - return SPA_RESULT_OK; + return SPA_RESULT_OK; } #include "render.c" -static void -set_timer (struct impl *this, bool enabled) +static void set_timer(struct impl *this, bool enabled) { - if (this->callbacks.have_output || this->props.live) { - if (enabled) { - if (this->props.live) { - uint64_t next_time = this->start_time + this->elapsed_time; - this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; - this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 1; - } - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - } - timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); - } + if (this->callbacks.have_output || this->props.live) { + if (enabled) { + if (this->props.live) { + uint64_t next_time = this->start_time + this->elapsed_time; + this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; + this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 1; + } + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + } + timerfd_settime(this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); + } } -static void -read_timer (struct impl *this) +static void read_timer(struct impl *this) { - uint64_t expirations; + uint64_t expirations; - if (this->callbacks.have_output || this->props.live) { - if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t)) - perror ("read timerfd"); - } + if (this->callbacks.have_output || this->props.live) { + if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) < sizeof(uint64_t)) + perror("read timerfd"); + } +} + +static int make_buffer(struct impl *this) +{ + struct buffer *b; + struct spa_port_io *io = this->io; + int n_bytes, n_samples; + + read_timer(this); + + if (spa_list_is_empty(&this->empty)) { + set_timer(this, false); + spa_log_error(this->log, NAME " %p: out of buffers", this); + return SPA_RESULT_OUT_OF_BUFFERS; + } + b = spa_list_first(&this->empty, struct buffer, link); + spa_list_remove(&b->link); + b->outstanding = true; + + n_bytes = b->outbuf->datas[0].maxsize; + if (io->range.min_size != 0) { + n_bytes = SPA_MIN(n_bytes, io->range.min_size); + if (io->range.max_size < n_bytes) + n_bytes = io->range.max_size; + } + + spa_log_trace(this->log, NAME " %p: dequeue buffer %d %d %d", this, b->outbuf->id, + b->outbuf->datas[0].maxsize, n_bytes); + + if (b->rb) { + int32_t filled, avail; + uint32_t index, offset; + + filled = spa_ringbuffer_get_write_index(&b->rb->ringbuffer, &index); + avail = b->rb->ringbuffer.size - filled; + n_bytes = SPA_MIN(avail, n_bytes); + + n_samples = n_bytes / this->bpf; + + offset = index & b->rb->ringbuffer.mask; + + if (offset + n_bytes > b->rb->ringbuffer.size) { + uint32_t l0 = b->rb->ringbuffer.size - offset; + this->render_func(this, SPA_MEMBER(b->outbuf->datas[0].data, offset, void), + l0 / this->bpf); + this->render_func(this, b->outbuf->datas[0].data, + (n_bytes - l0) / this->bpf); + } else { + this->render_func(this, SPA_MEMBER(b->outbuf->datas[0].data, offset, void), + n_samples); + } + spa_ringbuffer_write_update(&b->rb->ringbuffer, index + n_bytes); + } else { + n_samples = n_bytes / this->bpf; + this->render_func(this, b->outbuf->datas[0].data, n_samples); + b->outbuf->datas[0].chunk->size = n_bytes; + b->outbuf->datas[0].chunk->offset = 0; + b->outbuf->datas[0].chunk->stride = 0; + } + + if (b->h) { + b->h->seq = this->sample_count; + b->h->pts = this->start_time + this->elapsed_time; + b->h->dts_offset = 0; + } + + this->sample_count += n_samples; + this->elapsed_time = SAMPLES_TO_TIME(this, this->sample_count); + set_timer(this, true); + + io->buffer_id = b->outbuf->id; + io->status = SPA_RESULT_HAVE_BUFFER; + + return io->status; +} + +static void on_output(struct spa_source *source) +{ + struct impl *this = source->data; + int res; + + res = make_buffer(this); + + if (res == SPA_RESULT_HAVE_BUFFER) + this->callbacks.have_output(&this->node, this->user_data); +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + struct timespec now; + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (this->started) + return SPA_RESULT_OK; + + clock_gettime(CLOCK_MONOTONIC, &now); + if (this->props.live) + this->start_time = SPA_TIMESPEC_TO_TIME(&now); + else + this->start_time = 0; + this->sample_count = 0; + this->elapsed_time = 0; + + this->started = true; + set_timer(this, true); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (!this->started) + return SPA_RESULT_OK; + + this->started = false; + set_timer(this, false); + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -make_buffer (struct impl *this) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - struct buffer *b; - struct spa_port_io *io = this->io; - int n_bytes, n_samples; + struct impl *this; - read_timer (this); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - if (spa_list_is_empty (&this->empty)) { - set_timer (this, false); - return SPA_RESULT_OUT_OF_BUFFERS; - } - b = spa_list_first (&this->empty, struct buffer, link); - spa_list_remove (&b->link); - b->outstanding = true; + this = SPA_CONTAINER_OF(node, struct impl, node); - n_bytes = b->outbuf->datas[0].maxsize; - if (io->range.min_size != 0) { - n_bytes = SPA_MIN (n_bytes, io->range.min_size); - if (io->range.max_size < n_bytes) - n_bytes = io->range.max_size; - } + if (this->data_loop == NULL && callbacks->have_output != NULL) { + spa_log_error(this->log, "a data_loop is needed for async operation"); + return SPA_RESULT_ERROR; + } + this->callbacks = *callbacks; + this->user_data = user_data; - spa_log_trace (this->log, IMPL_NAME " %p: dequeue buffer %d %d %d", this, b->outbuf->id, - b->outbuf->datas[0].maxsize, n_bytes); - - if (b->rb) { - int32_t filled, avail; - uint32_t index, offset; - - filled = spa_ringbuffer_get_write_index (&b->rb->ringbuffer, &index); - avail = b->rb->ringbuffer.size - filled; - n_bytes = SPA_MIN (avail, n_bytes); - - n_samples = n_bytes / this->bpf; - - offset = index & b->rb->ringbuffer.mask; - - if (offset + n_bytes > b->rb->ringbuffer.size) { - uint32_t l0 = b->rb->ringbuffer.size - offset; - this->render_func (this, SPA_MEMBER (b->outbuf->datas[0].data, offset, void), l0 / this->bpf); - this->render_func (this, b->outbuf->datas[0].data, (n_bytes - l0) / this->bpf); - } else { - this->render_func (this, SPA_MEMBER (b->outbuf->datas[0].data, offset, void), n_samples); - } - spa_ringbuffer_write_update (&b->rb->ringbuffer, index + n_bytes); - } else { - n_samples = n_bytes / this->bpf; - this->render_func (this, b->outbuf->datas[0].data, n_samples); - b->outbuf->datas[0].chunk->size = n_bytes; - b->outbuf->datas[0].chunk->offset = 0; - b->outbuf->datas[0].chunk->stride = 0; - } - - if (b->h) { - b->h->seq = this->sample_count; - b->h->pts = this->start_time + this->elapsed_time; - b->h->dts_offset = 0; - } - - this->sample_count += n_samples; - this->elapsed_time = SAMPLES_TO_TIME (this, this->sample_count); - set_timer (this, true); - - io->buffer_id = b->outbuf->id; - io->status = SPA_RESULT_HAVE_BUFFER; - - return io->status; -} - -static void -on_output (struct spa_source *source) -{ - struct impl *this = source->data; - int res; - - res = make_buffer (this); - - if (res == SPA_RESULT_HAVE_BUFFER) - send_have_output (this); + return SPA_RESULT_OK; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports) + *n_input_ports = 0; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 0; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - struct timespec now; - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (this->started) - return SPA_RESULT_OK; - - clock_gettime (CLOCK_MONOTONIC, &now); - if (this->props.live) - this->start_time = SPA_TIMESPEC_TO_TIME (&now); - else - this->start_time = 0; - this->sample_count = 0; - this->elapsed_time = 0; - - this->started = true; - set_timer (this, true); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (!this->started) - return SPA_RESULT_OK; - - this->started = false; - set_timer (this, false); - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); + return SPA_RESULT_OK; +} - if (this->data_loop == NULL && callbacks->have_output) { - spa_log_error (this->log, "a data_loop is needed for async operation"); - return SPA_RESULT_ERROR; - } - - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (n_input_ports) - *n_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 0; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; + int res; + struct spa_format *fmt; + uint8_t buffer[256]; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + uint32_t count, match; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + count = match = filter ? 0 : index; + + next: + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + switch (count++) { + case 0: + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.audio, + this->type.media_subtype.raw, + PROP_U_EN(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 5, + this->type.audio_format.S16, + this->type.audio_format.S16, + this->type.audio_format.S32, + this->type.audio_format.F32, + this->type.audio_format.F64), + PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, + 44100, + 1, INT32_MAX), + PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, + 2, + 1, INT32_MAX)); + break; + default: + return SPA_RESULT_ENUM_END; + } + fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + + if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) + goto next; + + *format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format); + + return SPA_RESULT_OK; +} + +static int clear_buffers(struct impl *this) +{ + if (this->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers", this); + this->n_buffers = 0; + spa_list_init(&this->empty); + this->started = false; + set_timer(this, false); + } + return SPA_RESULT_OK; } static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (format == NULL) { + this->have_format = false; + clear_buffers(this); + } else { + struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; + int idx; + int sizes[4] = { 2, 4, 4, 8 }; + + if (info.media_type != this->type.media_type.audio || + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (info.info.raw.format == this->type.audio_format.S16) + idx = 0; + else if (info.info.raw.format == this->type.audio_format.S32) + idx = 1; + else if (info.info.raw.format == this->type.audio_format.F32) + idx = 2; + else if (info.info.raw.format == this->type.audio_format.F64) + idx = 3; + else + return SPA_RESULT_INVALID_MEDIA_TYPE; + + this->bpf = sizes[idx] * info.info.raw.channels; + this->current_format = info; + this->have_format = true; + this->render_func = sine_funcs[idx]; + } + + if (this->have_format) { + this->info.rate = this->current_format.info.raw.rate; + } + + return SPA_RESULT_OK; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.audio, + this->type.media_subtype.raw, + PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, + this->current_format.info.raw.format), + PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, + this->current_format.info.raw.rate), + PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, + this->current_format.info.raw.channels)); + + *format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - struct impl *this; - int res; - struct spa_format *fmt; - uint8_t buffer[256]; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - uint32_t count, match; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - count = match = filter ? 0 : index; + *info = &this->info; -next: - spa_pod_builder_init (&b, buffer, sizeof (buffer)); - - switch (count++) { - case 0: - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.audio, this->type.media_subtype.raw, - PROP_U_EN (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 5, this->type.audio_format.S16, - this->type.audio_format.S16, - this->type.audio_format.S32, - this->type.audio_format.F32, - this->type.audio_format.F64), - PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), - PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); - break; - default: - return SPA_RESULT_ENUM_END; - } - fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); - - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - - if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) - goto next; - - *format = SPA_POD_BUILDER_DEREF (&b, 0, struct spa_format); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -clear_buffers (struct impl *this) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - if (this->n_buffers > 0) { - spa_log_info (this->log, IMPL_NAME " %p: clear buffers", this); - this->n_buffers = 0; - spa_list_init (&this->empty); - this->started = false; - set_timer (this, false); - } - return SPA_RESULT_OK; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer)); + + switch (index) { + case 0: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + 1024 * this->bpf), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + this->bpf), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + 32, + 2, 32), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, + 16)); + break; + + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; + + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } + + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (format == NULL) { - this->have_format = false; - clear_buffers (this); - } else { - struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; - int idx; - int sizes[4] = { 2, 4, 4, 8 }; - - if (info.media_type != this->type.media_type.audio || - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!spa_format_audio_raw_parse (format, &info.info.raw, &this->type.format_audio)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (info.info.raw.format == this->type.audio_format.S16) - idx = 0; - else if (info.info.raw.format == this->type.audio_format.S32) - idx = 1; - else if (info.info.raw.format == this->type.audio_format.F32) - idx = 2; - else if (info.info.raw.format == this->type.audio_format.F64) - idx = 3; - else - return SPA_RESULT_INVALID_MEDIA_TYPE; - - this->bpf = sizes[idx] * info.info.raw.channels; - this->current_format = info; - this->have_format = true; - this->render_func = sine_funcs[idx]; - } - - if (this->have_format) { - this->info.rate = this->current_format.info.raw.rate; - } - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + uint32_t i; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.audio, this->type.media_subtype.raw, - PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->current_format.info.raw.format), - PROP (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, this->current_format.info.raw.rate), - PROP (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, this->current_format.info.raw.channels)); + clear_buffers(this); - *format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; - return SPA_RESULT_OK; + b = &this->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = false; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + b->rb = spa_buffer_find_meta(buffers[i], this->type.meta.Ringbuffer); + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) { + spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this, + buffers[i]); + } + spa_list_insert(this->empty.prev, &b->link); + } + this->n_buffers = n_buffers; + + return SPA_RESULT_OK; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - *info = &this->info; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT_NUM(this, direction, port_id), SPA_RESULT_INVALID_PORT); - spa_pod_builder_init (&b, this->params_buffer, sizeof (this->params_buffer)); + this->io = io; - switch (index) { - case 0: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, 1024 * this->bpf), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, this->bpf), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; + return SPA_RESULT_OK; +} - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; +static inline void reuse_buffer(struct impl *this, uint32_t id) +{ + struct buffer *b = &this->buffers[id]; + spa_return_if_fail(b->outstanding); - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } + spa_log_trace(this->log, NAME " %p: reuse buffer %d", this, id); - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); + b->outstanding = false; + spa_list_insert(this->empty.prev, &b->link); - return SPA_RESULT_OK; + if (!this->props.live) + set_timer(this, true); +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(port_id == 0, SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); + spa_return_val_if_fail(buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); + + reuse_buffer(this, buffer_id); + + return SPA_RESULT_OK; } static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +static int impl_node_process_input(struct spa_node *node) { - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - clear_buffers (this); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &this->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = false; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - b->rb = spa_buffer_find_meta (buffers[i], this->type.meta.Ringbuffer); - - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data == NULL) { - spa_log_error (this->log, IMPL_NAME " %p: invalid memory on buffer %p", this, buffers[i]); - } - spa_list_insert (this->empty.prev, &b->link); - } - this->n_buffers = n_buffers; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +static int impl_node_process_output(struct spa_node *node) { - struct impl *this; + struct impl *this; + struct spa_port_io *io; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); + io = this->io; + spa_return_val_if_fail(io != NULL, SPA_RESULT_WRONG_STATE); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + if (io->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + if (io->buffer_id != SPA_ID_INVALID) { + reuse_buffer(this, this->io->buffer_id); + this->io->buffer_id = SPA_ID_INVALID; + } - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->io = io; - - return SPA_RESULT_OK; -} - -static inline void -reuse_buffer (struct impl *this, uint32_t id) -{ - struct buffer *b = &this->buffers[id]; - spa_return_if_fail (b->outstanding); - - spa_log_trace (this->log, IMPL_NAME " %p: reuse buffer %d", this, id); - - b->outstanding = false; - spa_list_insert (this->empty.prev, &b->link); - - if (!this->props.live) - set_timer (this, true); -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (port_id == 0, SPA_RESULT_INVALID_PORT); - spa_return_val_if_fail (this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); - spa_return_val_if_fail (buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); - - reuse_buffer (this, buffer_id); - - return SPA_RESULT_OK; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_input (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - struct impl *this; - struct spa_port_io *io; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - io = this->io; - spa_return_val_if_fail (io != NULL, SPA_RESULT_WRONG_STATE); - - if (io->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - if (io->buffer_id != SPA_ID_INVALID) { - reuse_buffer (this, this->io->buffer_id); - this->io->buffer_id = SPA_ID_INVALID; - } - - if (!this->callbacks.have_output && (io->status == SPA_RESULT_NEED_BUFFER)) - return make_buffer (this); - else - return SPA_RESULT_OK; + if (!this->callbacks.have_output && (io->status == SPA_RESULT_NEED_BUFFER)) + return make_buffer(this); + else + return SPA_RESULT_OK; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, }; -static int -impl_clock_get_props (struct spa_clock *clock, - struct spa_props **props) +static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_clock_set_props (struct spa_clock *clock, - const struct spa_props *props) +impl_clock_get_time(struct spa_clock *clock, + int32_t *rate, + int64_t *ticks, + int64_t *monotonic_time) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct timespec now; + uint64_t tnow; -static int -impl_clock_get_time (struct spa_clock *clock, - int32_t *rate, - int64_t *ticks, - int64_t *monotonic_time) -{ - struct timespec now; - uint64_t tnow; + spa_return_val_if_fail(clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (rate) + *rate = SPA_NSEC_PER_SEC; - if (rate) - *rate = SPA_NSEC_PER_SEC; + clock_gettime(CLOCK_MONOTONIC, &now); + tnow = SPA_TIMESPEC_TO_TIME(&now); - clock_gettime (CLOCK_MONOTONIC, &now); - tnow = SPA_TIMESPEC_TO_TIME (&now); + if (ticks) + *ticks = tnow; + if (monotonic_time) + *monotonic_time = tnow; - if (ticks) - *ticks = tnow; - if (monotonic_time) - *monotonic_time = tnow; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_clock impl_clock = { - sizeof (struct spa_clock), - NULL, - SPA_CLOCK_STATE_STOPPED, - impl_clock_get_props, - impl_clock_set_props, - impl_clock_get_time, + sizeof(struct spa_clock), + NULL, + SPA_CLOCK_STATE_STOPPED, + impl_clock_get_props, + impl_clock_set_props, + impl_clock_get_time, }; -static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = (struct impl *) handle; + this = (struct impl *) handle; - if (interface_id == this->type.node) - *interface = &this->node; - else if (interface_id == this->type.clock) - *interface = &this->clock; - else - return SPA_RESULT_UNKNOWN_INTERFACE; + if (interface_id == this->type.node) + *interface = &this->node; + else if (interface_id == this->type.clock) + *interface = &this->clock; + else + return SPA_RESULT_UNKNOWN_INTERFACE; - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (this->data_loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + close(this->timer_source.fd); + + return SPA_RESULT_OK; } static int -impl_clear (struct spa_handle *handle) +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) { - struct impl *this; + struct impl *this; + uint32_t i; - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = (struct impl *) handle; + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; - if (this->data_loop) - spa_loop_remove_source (this->data_loop, &this->timer_source); - close (this->timer_source.fd); + this = (struct impl *) handle; - return SPA_RESULT_OK; -} + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) + this->data_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; + this->node = impl_node; + this->clock = impl_clock; + reset_props(this, &this->props); - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_list_init(&this->empty); - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; + this->timer_source.func = on_output; + this->timer_source.data = this; + this->timer_source.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + this->timerspec.it_interval.tv_sec = 0; + this->timerspec.it_interval.tv_nsec = 0; - this = (struct impl *) handle; + if (this->data_loop) + spa_loop_add_source(this->data_loop, &this->timer_source); - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) - this->data_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); + this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - this->node = impl_node; - this->clock = impl_clock; - impl_reset_props (this, &this->props); + spa_log_info(this->log, NAME " %p: initialized", this); - spa_list_init (&this->empty); - - this->timer_source.func = on_output; - this->timer_source.data = this; - this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); - this->timer_source.mask = SPA_IO_IN; - this->timer_source.rmask = 0; - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - this->timerspec.it_interval.tv_sec = 0; - this->timerspec.it_interval.tv_nsec = 0; - - if (this->data_loop) - spa_loop_add_source (this->data_loop, &this->timer_source); - - this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - - spa_log_info (this->log, IMPL_NAME " %p: initialized", this); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_interface_info impl_interfaces[] = { - { SPA_TYPE__Node, }, - { SPA_TYPE__Clock, }, + {SPA_TYPE__Node,}, + {SPA_TYPE__Clock,}, }; static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } const struct spa_handle_factory spa_audiotestsrc_factory = { - IMPL_NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/audiotestsrc/plugin.c b/spa/plugins/audiotestsrc/plugin.c index 751cc10f1..c3eedba74 100644 --- a/spa/plugins/audiotestsrc/plugin.c +++ b/spa/plugins/audiotestsrc/plugin.c @@ -23,11 +23,9 @@ extern const struct spa_handle_factory spa_audiotestsrc_factory; int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) +spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); switch (index) { case 0: diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index aabb76cf9..6fdc1c241 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -32,490 +32,478 @@ #define MAX_BUFFERS 32 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct buffer *next; + struct spa_buffer *outbuf; + bool outstanding; + struct buffer *next; }; struct port { - bool have_format; - struct spa_video_info current_format; - bool have_buffers; - struct buffer buffers[MAX_BUFFERS]; - struct spa_port_info info; - struct spa_port_io *io; + bool have_format; + struct spa_video_info current_format; + bool have_buffers; + struct buffer buffers[MAX_BUFFERS]; + struct spa_port_info info; + struct spa_port_io *io; }; struct type { - uint32_t node; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_video format_video; - struct spa_type_command_node command_node; + uint32_t node; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_video format_video; + struct spa_type_command_node command_node; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_video_map (map, &type->format_video); - spa_type_command_node_map (map, &type->command_node); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_video_map(map, &type->format_video); + spa_type_command_node_map(map, &type->command_node); } struct impl { - struct spa_handle handle; - struct spa_node node; + struct spa_handle handle; + struct spa_node node; - struct type type; - struct spa_type_map *map; - struct spa_log *log; + struct type type; + struct spa_type_map *map; + struct spa_log *log; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct port in_ports[1]; - struct port out_ports[1]; + struct port in_ports[1]; + struct port out_ports[1]; - bool started; + bool started; }; -static int -spa_ffmpeg_dec_node_get_props (struct spa_node *node, - struct spa_props **props) +static int spa_ffmpeg_dec_node_get_props(struct spa_node *node, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int spa_ffmpeg_dec_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int spa_ffmpeg_dec_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + if (node == NULL || command == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + this->started = true; + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + this->started = false; + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_set_props (struct spa_node *node, - const struct spa_props *props) +spa_ffmpeg_dec_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + this->callbacks = *callbacks; + this->user_data = user_data; + + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_send_command (struct spa_node *node, - struct spa_command *command) +spa_ffmpeg_dec_node_get_n_ports(struct spa_node *node, + uint32_t * n_input_ports, + uint32_t * max_input_ports, + uint32_t * n_output_ports, + uint32_t * max_output_ports) { - struct impl *this; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (node == NULL || command == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (n_input_ports) + *n_input_ports = 1; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 1; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - this->started = true; - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - this->started = false; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +spa_ffmpeg_dec_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t * input_ids, + uint32_t n_output_ports, + uint32_t * output_ids) { - struct impl *this; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (n_input_ports > 0 && input_ids != NULL) + input_ids[0] = 0; + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); - - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_dec_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports) - *n_input_ports = 1; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_dec_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports > 0 && input_ids != NULL) - input_ids[0] = 0; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +spa_ffmpeg_dec_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +spa_ffmpeg_dec_node_remove_port(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +spa_ffmpeg_dec_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - //struct impl *this; + //struct impl *this; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - //this = SPA_CONTAINER_OF (node, struct impl, node); + //this = SPA_CONTAINER_OF (node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - switch (index) { - case 0: - break; - default: - return SPA_RESULT_ENUM_END; - } - *format = NULL; + switch (index) { + case 0: + break; + default: + return SPA_RESULT_ENUM_END; + } + *format = NULL; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +spa_ffmpeg_dec_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (format == NULL) { - port->have_format = false; - return SPA_RESULT_OK; - } else { - struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; + if (format == NULL) { + port->have_format = false; + return SPA_RESULT_OK; + } else { + struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; - if (info.media_type != this->type.media_type.video && - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; + if (info.media_type != this->type.media_type.video && + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; - if (!spa_format_video_raw_parse (format, &info.info.raw, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; + if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video)) + return SPA_RESULT_INVALID_MEDIA_TYPE; - if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - port->current_format = info; - port->have_format = true; - } - } - return SPA_RESULT_OK; + if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { + port->current_format = info; + port->have_format = true; + } + } + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +spa_ffmpeg_dec_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; - *format = NULL; + *format = NULL; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +spa_ffmpeg_dec_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - *info = &port->info; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +spa_ffmpeg_dec_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +spa_ffmpeg_dec_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +spa_ffmpeg_dec_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (node, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(node, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +spa_ffmpeg_dec_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) +spa_ffmpeg_dec_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - port->io = io; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port->io = io; - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int spa_ffmpeg_dec_node_process_input(struct spa_node *node) +{ + return SPA_RESULT_INVALID_PORT; +} + +static int spa_ffmpeg_dec_node_process_output(struct spa_node *node) +{ + struct impl *this; + struct port *port; + struct spa_port_io *output; + + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + port = &this->out_ports[0]; + + if ((output = port->io) == NULL) + return SPA_RESULT_ERROR; + + if (!port->have_format) { + output->status = SPA_RESULT_NO_FORMAT; + return SPA_RESULT_ERROR; + } + output->status = SPA_RESULT_OK; + + return SPA_RESULT_OK; } static int -spa_ffmpeg_dec_node_process_input (struct spa_node *node) +spa_ffmpeg_dec_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) { - return SPA_RESULT_INVALID_PORT; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + if (port_id != 0) + return SPA_RESULT_INVALID_PORT; + + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_dec_node_process_output (struct spa_node *node) +spa_ffmpeg_dec_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; - struct port *port; - struct spa_port_io *output; - - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - port = &this->out_ports[0]; - - if ((output = port->io) == NULL) - return SPA_RESULT_ERROR; - - if (!port->have_format) { - output->status = SPA_RESULT_NO_FORMAT; - return SPA_RESULT_ERROR; - } - output->status = SPA_RESULT_OK; - - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_dec_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (port_id != 0) - return SPA_RESULT_INVALID_PORT; - - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_ffmpeg_dec_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static const struct spa_node ffmpeg_dec_node = { - sizeof (struct spa_node), - NULL, - spa_ffmpeg_dec_node_get_props, - spa_ffmpeg_dec_node_set_props, - spa_ffmpeg_dec_node_send_command, - spa_ffmpeg_dec_node_set_callbacks, - spa_ffmpeg_dec_node_get_n_ports, - spa_ffmpeg_dec_node_get_port_ids, - spa_ffmpeg_dec_node_add_port, - spa_ffmpeg_dec_node_remove_port, - spa_ffmpeg_dec_node_port_enum_formats, - spa_ffmpeg_dec_node_port_set_format, - spa_ffmpeg_dec_node_port_get_format, - spa_ffmpeg_dec_node_port_get_info, - spa_ffmpeg_dec_node_port_enum_params, - spa_ffmpeg_dec_node_port_set_param, - spa_ffmpeg_dec_node_port_use_buffers, - spa_ffmpeg_dec_node_port_alloc_buffers, - spa_ffmpeg_dec_node_port_set_io, - spa_ffmpeg_dec_node_port_reuse_buffer, - spa_ffmpeg_dec_node_port_send_command, - spa_ffmpeg_dec_node_process_input, - spa_ffmpeg_dec_node_process_output, + sizeof(struct spa_node), + NULL, + spa_ffmpeg_dec_node_get_props, + spa_ffmpeg_dec_node_set_props, + spa_ffmpeg_dec_node_send_command, + spa_ffmpeg_dec_node_set_callbacks, + spa_ffmpeg_dec_node_get_n_ports, + spa_ffmpeg_dec_node_get_port_ids, + spa_ffmpeg_dec_node_add_port, + spa_ffmpeg_dec_node_remove_port, + spa_ffmpeg_dec_node_port_enum_formats, + spa_ffmpeg_dec_node_port_set_format, + spa_ffmpeg_dec_node_port_get_format, + spa_ffmpeg_dec_node_port_get_info, + spa_ffmpeg_dec_node_port_enum_params, + spa_ffmpeg_dec_node_port_set_param, + spa_ffmpeg_dec_node_port_use_buffers, + spa_ffmpeg_dec_node_port_alloc_buffers, + spa_ffmpeg_dec_node_port_set_io, + spa_ffmpeg_dec_node_port_reuse_buffer, + spa_ffmpeg_dec_node_port_send_command, + spa_ffmpeg_dec_node_process_input, + spa_ffmpeg_dec_node_process_output, }; static int -spa_ffmpeg_dec_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +spa_ffmpeg_dec_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) { - struct impl *this; + struct impl *this; - if (handle == NULL || interface == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (handle == NULL || interface == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = (struct impl *) handle; + this = (struct impl *) handle; - if (interface_id == this->type.node) - *interface = &this->node; - else - return SPA_RESULT_UNKNOWN_INTERFACE; + if (interface_id == this->type.node) + *interface = &this->node; + else + return SPA_RESULT_UNKNOWN_INTERFACE; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } int -spa_ffmpeg_dec_init (struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) +spa_ffmpeg_dec_init(struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) { - struct impl *this; - uint32_t i; + struct impl *this; + uint32_t i; - handle->get_interface = spa_ffmpeg_dec_get_interface; + handle->get_interface = spa_ffmpeg_dec_get_interface; - this = (struct impl *) handle; + this = (struct impl *) handle; - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); - this->node = ffmpeg_dec_node; + this->node = ffmpeg_dec_node; - this->in_ports[0].info.flags = 0; - this->out_ports[0].info.flags = 0; + this->in_ports[0].info.flags = 0; + this->out_ports[0].info.flags = 0; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index 25fd804e8..da7cbaedd 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -32,495 +32,467 @@ #define MAX_BUFFERS 32 struct buffer { - struct spa_buffer buffer; - struct spa_meta metas[1]; - struct spa_meta_header header; - struct spa_data datas[1]; - struct spa_buffer *imported; - bool outstanding; - struct buffer *next; + struct spa_buffer buffer; + struct spa_meta metas[1]; + struct spa_meta_header header; + struct spa_data datas[1]; + struct spa_buffer *imported; + bool outstanding; + struct buffer *next; }; struct port { - bool have_format; - struct spa_video_info current_format; - bool have_buffers; - struct buffer buffers[MAX_BUFFERS]; - struct spa_port_info info; - struct spa_port_io *io; + bool have_format; + struct spa_video_info current_format; + bool have_buffers; + struct buffer buffers[MAX_BUFFERS]; + struct spa_port_info info; + struct spa_port_io *io; }; struct type { - uint32_t node; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_video format_video; - struct spa_type_command_node command_node; + uint32_t node; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_video format_video; + struct spa_type_command_node command_node; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_video_map (map, &type->format_video); - spa_type_command_node_map (map, &type->command_node); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_video_map(map, &type->format_video); + spa_type_command_node_map(map, &type->command_node); } struct impl { - struct spa_handle handle; - struct spa_node node; + struct spa_handle handle; + struct spa_node node; - struct type type; - struct spa_type_map *map; - struct spa_log *log; + struct type type; + struct spa_type_map *map; + struct spa_log *log; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct port in_ports[1]; - struct port out_ports[1]; + struct port in_ports[1]; + struct port out_ports[1]; - bool started; + bool started; }; -static int -spa_ffmpeg_enc_node_get_props (struct spa_node *node, - struct spa_props **props) +static int spa_ffmpeg_enc_node_get_props(struct spa_node *node, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int spa_ffmpeg_enc_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int spa_ffmpeg_enc_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + if (node == NULL || command == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + this->started = true; + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + this->started = false; + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_set_props (struct spa_node *node, - const struct spa_props *props) +spa_ffmpeg_enc_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, void *user_data) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + this->callbacks = *callbacks; + this->user_data = user_data; + + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_send_command (struct spa_node *node, - struct spa_command *command) +spa_ffmpeg_enc_node_get_n_ports(struct spa_node *node, + uint32_t * n_input_ports, + uint32_t * max_input_ports, + uint32_t * n_output_ports, uint32_t * max_output_ports) { - struct impl *this; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (node == NULL || command == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (n_input_ports) + *n_input_ports = 1; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 1; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - this->started = true; - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - this->started = false; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +spa_ffmpeg_enc_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t * input_ids, + uint32_t n_output_ports, uint32_t * output_ids) { - struct impl *this; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (n_input_ports > 0 && input_ids != NULL) + input_ids[0] = 0; + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); - - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_enc_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports) - *n_input_ports = 1; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_enc_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports > 0 && input_ids != NULL) - input_ids[0] = 0; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +spa_ffmpeg_enc_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +spa_ffmpeg_enc_node_remove_port(struct spa_node *node, + enum spa_direction direction, uint32_t port_id) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +spa_ffmpeg_enc_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, uint32_t index) { - //struct impl *this; - //struct port *port; + //struct impl *this; + //struct port *port; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - //this = SPA_CONTAINER_OF (node, struct impl, node); + //this = SPA_CONTAINER_OF (node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - //port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + //port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - switch (index) { - case 0: - break; - default: - return SPA_RESULT_ENUM_END; - } - *format = NULL; + switch (index) { + case 0: + break; + default: + return SPA_RESULT_ENUM_END; + } + *format = NULL; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +spa_ffmpeg_enc_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, const struct spa_format *format) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (format == NULL) { - port->have_format = false; - return SPA_RESULT_OK; - } else { - struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; + if (format == NULL) { + port->have_format = false; + return SPA_RESULT_OK; + } else { + struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; - if (info.media_type != this->type.media_type.video && - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; + if (info.media_type != this->type.media_type.video && + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; - if (!spa_format_video_raw_parse (format, &info.info.raw, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; + if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video)) + return SPA_RESULT_INVALID_MEDIA_TYPE; - if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - port->current_format = info; - port->have_format = true; - } - } - return SPA_RESULT_OK; + if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { + port->current_format = info; + port->have_format = true; + } + } + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +spa_ffmpeg_enc_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, const struct spa_format **format) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; - *format = NULL; + *format = NULL; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +spa_ffmpeg_enc_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, const struct spa_port_info **info) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - *info = &port->info; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +spa_ffmpeg_enc_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, uint32_t index, struct spa_param **param) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +spa_ffmpeg_enc_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, const struct spa_param *param) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +spa_ffmpeg_enc_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, uint32_t n_buffers) { - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (!IS_VALID_PORT (node, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(node, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +spa_ffmpeg_enc_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, uint32_t * n_buffers) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) +spa_ffmpeg_enc_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, struct spa_port_io *io) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (!IS_VALID_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - port->io = io; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port->io = io; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -spa_ffmpeg_enc_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) +spa_ffmpeg_enc_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) { - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (port_id != 0) - return SPA_RESULT_INVALID_PORT; + if (port_id != 0) + return SPA_RESULT_INVALID_PORT; - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -spa_ffmpeg_enc_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) +spa_ffmpeg_enc_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, struct spa_command *command) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -spa_ffmpeg_enc_node_process_input (struct spa_node *node) +static int spa_ffmpeg_enc_node_process_input(struct spa_node *node) { - return SPA_RESULT_INVALID_PORT; + return SPA_RESULT_INVALID_PORT; } -static int -spa_ffmpeg_enc_node_process_output (struct spa_node *node) +static int spa_ffmpeg_enc_node_process_output(struct spa_node *node) { - struct impl *this; - struct port *port; - struct spa_port_io *output; + struct impl *this; + struct port *port; + struct spa_port_io *output; - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (node == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if ((output = this->out_ports[0].io) == NULL) - return SPA_RESULT_OK; + if ((output = this->out_ports[0].io) == NULL) + return SPA_RESULT_OK; - port = &this->out_ports[0]; + port = &this->out_ports[0]; - if (!port->have_format) { - output->status = SPA_RESULT_NO_FORMAT; - return SPA_RESULT_ERROR; - } - output->status = SPA_RESULT_OK; + if (!port->have_format) { + output->status = SPA_RESULT_NO_FORMAT; + return SPA_RESULT_ERROR; + } + output->status = SPA_RESULT_OK; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_node ffmpeg_enc_node = { - sizeof (struct spa_node), - NULL, - spa_ffmpeg_enc_node_get_props, - spa_ffmpeg_enc_node_set_props, - spa_ffmpeg_enc_node_send_command, - spa_ffmpeg_enc_node_set_callbacks, - spa_ffmpeg_enc_node_get_n_ports, - spa_ffmpeg_enc_node_get_port_ids, - spa_ffmpeg_enc_node_add_port, - spa_ffmpeg_enc_node_remove_port, - spa_ffmpeg_enc_node_port_enum_formats, - spa_ffmpeg_enc_node_port_set_format, - spa_ffmpeg_enc_node_port_get_format, - spa_ffmpeg_enc_node_port_get_info, - spa_ffmpeg_enc_node_port_enum_params, - spa_ffmpeg_enc_node_port_set_param, - spa_ffmpeg_enc_node_port_use_buffers, - spa_ffmpeg_enc_node_port_alloc_buffers, - spa_ffmpeg_enc_node_port_set_io, - spa_ffmpeg_enc_node_port_reuse_buffer, - spa_ffmpeg_enc_node_port_send_command, - spa_ffmpeg_enc_node_process_input, - spa_ffmpeg_enc_node_process_output, + sizeof(struct spa_node), + NULL, + spa_ffmpeg_enc_node_get_props, + spa_ffmpeg_enc_node_set_props, + spa_ffmpeg_enc_node_send_command, + spa_ffmpeg_enc_node_set_callbacks, + spa_ffmpeg_enc_node_get_n_ports, + spa_ffmpeg_enc_node_get_port_ids, + spa_ffmpeg_enc_node_add_port, + spa_ffmpeg_enc_node_remove_port, + spa_ffmpeg_enc_node_port_enum_formats, + spa_ffmpeg_enc_node_port_set_format, + spa_ffmpeg_enc_node_port_get_format, + spa_ffmpeg_enc_node_port_get_info, + spa_ffmpeg_enc_node_port_enum_params, + spa_ffmpeg_enc_node_port_set_param, + spa_ffmpeg_enc_node_port_use_buffers, + spa_ffmpeg_enc_node_port_alloc_buffers, + spa_ffmpeg_enc_node_port_set_io, + spa_ffmpeg_enc_node_port_reuse_buffer, + spa_ffmpeg_enc_node_port_send_command, + spa_ffmpeg_enc_node_process_input, + spa_ffmpeg_enc_node_process_output, }; static int -spa_ffmpeg_enc_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +spa_ffmpeg_enc_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) { - struct impl *this; + struct impl *this; - if (handle == NULL || interface == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (handle == NULL || interface == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - this = (struct impl *) handle; + this = (struct impl *) handle; - if (interface_id == this->type.node) - *interface = &this->node; - else - return SPA_RESULT_UNKNOWN_INTERFACE; + if (interface_id == this->type.node) + *interface = &this->node; + else + return SPA_RESULT_UNKNOWN_INTERFACE; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } int -spa_ffmpeg_enc_init (struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) +spa_ffmpeg_enc_init(struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, uint32_t n_support) { - struct impl *this; - uint32_t i; + struct impl *this; + uint32_t i; - handle->get_interface = spa_ffmpeg_enc_get_interface; + handle->get_interface = spa_ffmpeg_enc_get_interface; - this = (struct impl *) handle; + this = (struct impl *) handle; - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } - this->node = ffmpeg_enc_node; + this->node = ffmpeg_enc_node; - this->in_ports[0].info.flags = 0; - this->out_ports[0].info.flags = 0; + this->in_ports[0].info.flags = 0; + this->out_ports[0].info.flags = 0; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg.c b/spa/plugins/ffmpeg/ffmpeg.c index 67dd30419..b330d5a67 100644 --- a/spa/plugins/ffmpeg/ffmpeg.c +++ b/spa/plugins/ffmpeg/ffmpeg.c @@ -25,92 +25,89 @@ #include #include -int spa_ffmpeg_dec_init (struct spa_handle *handle, const struct spa_dict *info, const struct spa_support *support, uint32_t n_support); -int spa_ffmpeg_enc_init (struct spa_handle *handle, const struct spa_dict *info, const struct spa_support *support, uint32_t n_support); +int spa_ffmpeg_dec_init(struct spa_handle *handle, const struct spa_dict *info, + const struct spa_support *support, uint32_t n_support); +int spa_ffmpeg_enc_init(struct spa_handle *handle, const struct spa_dict *info, + const struct spa_support *support, uint32_t n_support); static int -ffmpeg_dec_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) +ffmpeg_dec_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) { - if (factory == NULL || handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (factory == NULL || handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - return spa_ffmpeg_dec_init (handle, info, support, n_support); + return spa_ffmpeg_dec_init(handle, info, support, n_support); } static int -ffmpeg_enc_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) +ffmpeg_enc_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) { - if (factory == NULL || handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (factory == NULL || handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - return spa_ffmpeg_enc_init (handle, info, support, n_support); + return spa_ffmpeg_enc_init(handle, info, support, n_support); } -static const struct spa_interface_info ffmpeg_interfaces[] = -{ - { SPA_TYPE__Node, - }, +static const struct spa_interface_info ffmpeg_interfaces[] = { + {SPA_TYPE__Node, }, }; static int -ffmpeg_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) +ffmpeg_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - if (factory == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; + if (factory == NULL || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; - if (index >= 1) - return SPA_RESULT_ENUM_END; + if (index >= 1) + return SPA_RESULT_ENUM_END; - *info = &ffmpeg_interfaces[index]; + *info = &ffmpeg_interfaces[index]; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -int -spa_handle_factory_enum (const struct spa_handle_factory **factory, - uint32_t index) +int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - static const AVCodec *c = NULL; - static int ci = 0; - static struct spa_handle_factory f; - static char name[128]; + static const AVCodec *c = NULL; + static int ci = 0; + static struct spa_handle_factory f; + static char name[128]; - av_register_all(); + av_register_all(); - if (index == 0) { - c = av_codec_next (NULL); - ci = 0; - } - while (index > ci && c) { - c = av_codec_next (c); - ci++; - } - if (c == NULL) - return SPA_RESULT_ENUM_END; + if (index == 0) { + c = av_codec_next(NULL); + ci = 0; + } + while (index > ci && c) { + c = av_codec_next(c); + ci++; + } + if (c == NULL) + return SPA_RESULT_ENUM_END; - if (av_codec_is_encoder (c)) { - snprintf (name, 128, "ffenc_%s", c->name); - f.init = ffmpeg_enc_init; - } - else { - snprintf (name, 128, "ffdec_%s", c->name); - f.init = ffmpeg_dec_init; - } - f.name = name; - f.info = NULL; - f.enum_interface_info = ffmpeg_enum_interface_info; + if (av_codec_is_encoder(c)) { + snprintf(name, 128, "ffenc_%s", c->name); + f.init = ffmpeg_enc_init; + } else { + snprintf(name, 128, "ffdec_%s", c->name); + f.init = ffmpeg_dec_init; + } + f.name = name; + f.info = NULL; + f.enum_interface_info = ffmpeg_enum_interface_info; - *factory = &f; + *factory = &f; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } diff --git a/spa/plugins/libva/libva-dec.c b/spa/plugins/libva/libva-dec.c deleted file mode 100644 index b3a9e2266..000000000 --- a/spa/plugins/libva/libva-dec.c +++ /dev/null @@ -1,528 +0,0 @@ -/* Spa Libva Decoder - * Copyright (C) 2016 Wim Taymans - * - * 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. - */ - -#include -#include -#include -#include - -#include -#include - -typedef struct _SpaLibvaDec SpaLibvaDec; - -typedef struct { - SpaProps props; -} SpaLibvaDecProps; - -static void -reset_libva_dec_props (SpaLibvaDecProps *props) -{ -} - -#define INPUT_PORT_ID 0 -#define OUTPUT_PORT_ID 1 -#define IS_VALID_PORT(id) ((id) < 2) -#define MAX_BUFFERS 32 - -typedef struct _LibvaBuffer LibvaBuffer; - -struct _LibvaBuffer { - SpaBuffer buffer; - SpaMeta metas[1]; - SpaMetaHeader header; - SpaData datas[1]; - SpaLibvaDec *dec; - SpaBuffer *imported; - bool outstanding; - LibvaBuffer *next; -}; - -typedef struct { - SpaVideoRawFormat raw_format[2]; - SpaFormat *current_format; - bool have_buffers; - LibvaBuffer buffers[MAX_BUFFERS]; - SpaPortInfo info; - SpaPortStatus status; -} SpaLibvaState; - -struct _SpaLibvaDec { - SpaHandle handle; - - SpaLibvaDecProps props[2]; - - SpaNodeEventCallback event_cb; - void *user_data; - - SpaLibvaState state[2]; -}; - -enum { - PROP_ID_LAST, -}; - -static const SpaPropInfo prop_info[] = -{ - { 0, }, -}; - -static int -spa_libva_dec_node_get_props (SpaHandle *handle, - SpaProps **props) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - - if (handle == NULL || props == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); - *props = &this->props[0].props; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_set_props (SpaHandle *handle, - const SpaProps *props) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - SpaLibvaDecProps *p = &this->props[1]; - int res; - - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (props == NULL) { - reset_libva_dec_props (p); - return SPA_RESULT_OK; - } - - res = spa_props_copy_values (props, &p->props); - - return res; -} - -static int -spa_libva_dec_node_send_command (SpaHandle *handle, - SpaCommand *command) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - - if (handle == NULL || command == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - switch (command->type) { - case SPA_COMMAND_INVALID: - return SPA_RESULT_INVALID_COMMAND; - - case SPA_COMMAND_START: - if (this->event_cb) { - SpaNodeEvent event; - - event.refcount = 1; - event.notify = NULL; - event.type = SPA_NODE_EVENT_TYPE_STARTED; - event.port_id = -1; - event.data = NULL; - event.size = 0; - - this->event_cb (handle, &event, this->user_data); - } - break; - case SPA_COMMAND_STOP: - if (this->event_cb) { - SpaNodeEvent event; - - event.refcount = 1; - event.notify = NULL; - event.type = SPA_NODE_EVENT_TYPE_STOPPED; - event.port_id = -1; - event.data = NULL; - event.size = 0; - - this->event_cb (handle, &event, this->user_data); - } - break; - - case SPA_COMMAND_FLUSH: - case SPA_COMMAND_DRAIN: - case SPA_COMMAND_MARKER: - return SPA_RESULT_NOT_IMPLEMENTED; - } - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_set_event_callback (SpaHandle *handle, - SpaNodeEventCallback event, - void *user_data) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this->event_cb = event; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_get_n_ports (SpaHandle *handle, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports) - *n_input_ports = 1; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_get_port_ids (SpaHandle *handle, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports > 0 && input_ids != NULL) - input_ids[0] = 0; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 1; - - return SPA_RESULT_OK; -} - - -static int -spa_libva_dec_node_add_port (SpaHandle *handle, - SpaDirection direction, - uint32_t *port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_dec_node_remove_port (SpaHandle *handle, - uint32_t port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_dec_node_port_enum_formats (SpaHandle *handle, - uint32_t port_id, - uint32_t index, - SpaFormat **format) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - SpaLibvaState *state; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - switch (index) { - case 0: - spa_video_raw_format_init (&state->raw_format[0]); - break; - default: - return SPA_RESULT_ENUM_END; - } - *format = &state->raw_format[0].format; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_set_format (SpaHandle *handle, - uint32_t port_id, - bool test_only, - const SpaFormat *format) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - SpaLibvaState *state; - int res; - SpaFormat *f, *tf; - size_t fs; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - if (format == NULL) { - state->current_format = NULL; - return SPA_RESULT_OK; - } - - if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { - if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - if ((res = spa_video_raw_format_parse (format, &state->raw_format[0]) < 0)) - return res; - - f = &state->raw_format[0].format; - tf = &state->raw_format[1].format; - fs = sizeof (SpaVideoRawFormat); - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!test_only) { - memcpy (tf, f, fs); - state->current_format = tf; - } - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_get_format (SpaHandle *handle, - uint32_t port_id, - const SpaFormat **format) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - SpaLibvaState *state; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - if (state->current_format == NULL) - return SPA_RESULT_NO_FORMAT; - - *format = state->current_format; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_get_info (SpaHandle *handle, - uint32_t port_id, - const SpaPortInfo **info) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - - if (handle == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - *info = &this->state[port_id].info; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_get_props (SpaHandle *handle, - uint32_t port_id, - SpaProps **props) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_dec_node_port_set_props (SpaHandle *handle, - uint32_t port_id, - const SpaProps *props) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_dec_node_port_get_status (SpaHandle *handle, - uint32_t port_id, - const SpaPortStatus **status) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - - if (handle == NULL || status == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - *status = &this->state[port_id].status; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_use_buffers (SpaHandle *handle, - uint32_t port_id, - SpaBuffer **buffers, - uint32_t n_buffers) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - return SPA_RESULT_OK; -} - -static int -spa_libva_dec_node_port_alloc_buffers (SpaHandle *handle, - uint32_t port_id, - SpaParam **params, - uint32_t n_params, - SpaBuffer **buffers, - uint32_t *n_buffers) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - - -static int -spa_libva_dec_node_port_push_input (SpaHandle *handle, - uint32_t n_info, - SpaInputInfo *info) -{ - return SPA_RESULT_INVALID_PORT; -} - -static int -spa_libva_dec_node_port_pull_output (SpaHandle *handle, - uint32_t n_info, - SpaOutputInfo *info) -{ - SpaLibvaDec *this = (SpaLibvaDec *) handle; - SpaLibvaState *state; - uint32_t i; - bool have_error = false; - - if (handle == NULL || n_info == 0 || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - - for (i = 0; i < n_info; i++) { - if (info[i].port_id != OUTPUT_PORT_ID) { - info[i].status = SPA_RESULT_INVALID_PORT; - have_error = true; - continue; - } - state = &this->state[info[i].port_id]; - - if (state->current_format == NULL) { - info[i].status = SPA_RESULT_NO_FORMAT; - have_error = true; - continue; - } - info[i].status = SPA_RESULT_OK; - } - if (have_error) - return SPA_RESULT_ERROR; - - return SPA_RESULT_OK; -} - -static const SpaNode libva_dec_node = { - sizeof (SpaNode), - spa_libva_dec_node_get_props, - spa_libva_dec_node_set_props, - spa_libva_dec_node_send_command, - spa_libva_dec_node_set_event_callback, - spa_libva_dec_node_get_n_ports, - spa_libva_dec_node_get_port_ids, - spa_libva_dec_node_add_port, - spa_libva_dec_node_remove_port, - spa_libva_dec_node_port_enum_formats, - spa_libva_dec_node_port_set_format, - spa_libva_dec_node_port_get_format, - spa_libva_dec_node_port_get_info, - spa_libva_dec_node_port_get_props, - spa_libva_dec_node_port_set_props, - spa_libva_dec_node_port_use_buffers, - spa_libva_dec_node_port_alloc_buffers, - spa_libva_dec_node_port_get_status, - spa_libva_dec_node_port_push_input, - spa_libva_dec_node_port_pull_output, -}; - -static int -spa_libva_dec_get_interface (SpaHandle *handle, - uint32_t interface_id, - const void **interface) -{ - if (handle == NULL || interface == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - switch (interface_id) { - case SPA_INTERFACE_ID_NODE: - *interface = &libva_dec_node; - break; - default: - return SPA_RESULT_UNKNOWN_INTERFACE; - } - return SPA_RESULT_OK; -} - -SpaHandle * -spa_libva_dec_new (void) -{ - SpaHandle *handle; - SpaLibvaDec *this; - - handle = calloc (1, sizeof (SpaLibvaDec)); - handle->get_interface = spa_libva_dec_get_interface; - - this = (SpaLibvaDec *) handle; - this->props[1].props.n_prop_info = PROP_ID_LAST; - this->props[1].props.prop_info = prop_info; - this->props[1].props.set_prop = spa_props_generic_set_prop; - this->props[1].props.get_prop = spa_props_generic_get_prop; - reset_libva_dec_props (&this->props[1]); - - this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; - - this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; - return handle; -} diff --git a/spa/plugins/libva/libva-enc.c b/spa/plugins/libva/libva-enc.c deleted file mode 100644 index 3fba31ff7..000000000 --- a/spa/plugins/libva/libva-enc.c +++ /dev/null @@ -1,530 +0,0 @@ -/* Spa Libva Encoder - * Copyright (C) 2016 Wim Taymans - * - * 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. - */ - -#include -#include -#include -#include - -#include -#include - -typedef struct _SpaLibvaEnc SpaLibvaEnc; - -typedef struct { - SpaProps props; -} SpaLibvaEncProps; - -static void -reset_libva_enc_props (SpaLibvaEncProps *props) -{ -} - -#define INPUT_PORT_ID 0 -#define OUTPUT_PORT_ID 1 -#define IS_VALID_PORT(id) ((id) < 2) -#define MAX_BUFFERS 32 - -typedef struct _LibvaBuffer LibvaBuffer; - -struct _LibvaBuffer { - SpaBuffer buffer; - SpaMeta metas[1]; - SpaMetaHeader header; - SpaData datas[1]; - SpaLibvaEnc *enc; - SpaBuffer *imported; - bool outstanding; - LibvaBuffer *next; -}; - -typedef struct { - SpaVideoRawFormat raw_format[2]; - SpaFormat *current_format; - bool have_buffers; - LibvaBuffer buffers[MAX_BUFFERS]; - SpaPortInfo info; - SpaAllocParam *params[1]; - SpaAllocParamBuffers param_buffers; - SpaPortStatus status; -} SpaLibvaState; - -struct _SpaLibvaEnc { - SpaHandle handle; - - SpaLibvaEncProps props[2]; - - SpaEventCallback event_cb; - void *user_data; - - SpaLibvaState state[2]; -}; - -enum { - PROP_ID_LAST, -}; - -static const SpaPropInfo prop_info[] = -{ - { 0, }, -}; - -static int -spa_libva_enc_node_get_props (SpaHandle *handle, - SpaProps **props) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - - if (handle == NULL || props == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); - *props = &this->props[0].props; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_set_props (SpaHandle *handle, - const SpaProps *props) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - SpaLibvaEncProps *p = &this->props[1]; - int res; - - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (props == NULL) { - reset_libva_enc_props (p); - return SPA_RESULT_OK; - } - - res = spa_props_copy_values (props, &p->props); - - return res; -} - -static int -spa_libva_enc_node_send_command (SpaHandle *handle, - SpaCommand *command) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - - if (handle == NULL || command == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - switch (command->type) { - case SPA_COMMAND_INVALID: - return SPA_RESULT_INVALID_COMMAND; - - case SPA_COMMAND_START: - if (this->event_cb) { - SpaEvent event; - - event.refcount = 1; - event.notify = NULL; - event.type = SPA_EVENT_TYPE_STARTED; - event.port_id = -1; - event.data = NULL; - event.size = 0; - - this->event_cb (handle, &event, this->user_data); - } - break; - case SPA_COMMAND_STOP: - if (this->event_cb) { - SpaEvent event; - - event.refcount = 1; - event.notify = NULL; - event.type = SPA_EVENT_TYPE_STOPPED; - event.port_id = -1; - event.data = NULL; - event.size = 0; - - this->event_cb (handle, &event, this->user_data); - } - break; - - case SPA_COMMAND_FLUSH: - case SPA_COMMAND_DRAIN: - case SPA_COMMAND_MARKER: - return SPA_RESULT_NOT_IMPLEMENTED; - } - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_set_event_callback (SpaHandle *handle, - SpaEventCallback event, - void *user_data) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this->event_cb = event; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_get_n_ports (SpaHandle *handle, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports) - *n_input_ports = 1; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_get_port_ids (SpaHandle *handle, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports > 0 && input_ids != NULL) - input_ids[0] = 0; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 1; - - return SPA_RESULT_OK; -} - - -static int -spa_libva_enc_node_add_port (SpaHandle *handle, - SpaDirection direction, - uint32_t *port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_enc_node_remove_port (SpaHandle *handle, - uint32_t port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_enc_node_port_enum_formats (SpaHandle *handle, - uint32_t port_id, - uint32_t index, - SpaFormat **format) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - SpaLibvaState *state; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - switch (index) { - case 0: - spa_video_raw_format_init (&state->raw_format[0]); - break; - default: - return SPA_RESULT_ENUM_END; - } - *format = &state->raw_format[0].format; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_set_format (SpaHandle *handle, - uint32_t port_id, - bool test_only, - const SpaFormat *format) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - SpaLibvaState *state; - int res; - SpaFormat *f, *tf; - size_t fs; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - if (format == NULL) { - state->current_format = NULL; - return SPA_RESULT_OK; - } - - if (format->media_type == SPA_MEDIA_TYPE_VIDEO) { - if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) { - if ((res = spa_video_raw_format_parse (format, &state->raw_format[0]) < 0)) - return res; - - f = &state->raw_format[0].format; - tf = &state->raw_format[1].format; - fs = sizeof (SpaVideoRawFormat); - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - } else - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!test_only) { - memcpy (tf, f, fs); - state->current_format = tf; - } - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_get_format (SpaHandle *handle, - uint32_t port_id, - const SpaFormat **format) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - SpaLibvaState *state; - - if (handle == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - state = &this->state[port_id]; - - if (state->current_format == NULL) - return SPA_RESULT_NO_FORMAT; - - *format = state->current_format; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_get_info (SpaHandle *handle, - uint32_t port_id, - const SpaPortInfo **info) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - - if (handle == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - *info = &this->state[port_id].info; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_get_props (SpaHandle *handle, - uint32_t port_id, - SpaProps **props) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_enc_node_port_set_props (SpaHandle *handle, - uint32_t port_id, - const SpaProps *props) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_libva_enc_node_port_get_status (SpaHandle *handle, - uint32_t port_id, - const SpaPortStatus **status) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - - if (handle == NULL || status == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - *status = &this->state[port_id].status; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_use_buffers (SpaHandle *handle, - uint32_t port_id, - SpaBuffer **buffers, - uint32_t n_buffers) -{ - if (handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (!IS_VALID_PORT (port_id)) - return SPA_RESULT_INVALID_PORT; - - return SPA_RESULT_OK; -} - -static int -spa_libva_enc_node_port_alloc_buffers (SpaHandle *handle, - uint32_t port_id, - SpaAllocParam **params, - uint32_t n_params, - SpaBuffer **buffers, - uint32_t *n_buffers) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - - -static int -spa_libva_enc_node_port_push_input (SpaHandle *handle, - uint32_t n_info, - SpaInputInfo *info) -{ - return SPA_RESULT_INVALID_PORT; -} - -static int -spa_libva_enc_node_port_pull_output (SpaHandle *handle, - uint32_t n_info, - SpaOutputInfo *info) -{ - SpaLibvaEnc *this = (SpaLibvaEnc *) handle; - SpaLibvaState *state; - uint32_t i; - bool have_error = false; - - if (handle == NULL || n_info == 0 || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - - for (i = 0; i < n_info; i++) { - if (info[i].port_id != OUTPUT_PORT_ID) { - info[i].status = SPA_RESULT_INVALID_PORT; - have_error = true; - continue; - } - state = &this->state[info[i].port_id]; - - if (state->current_format == NULL) { - info[i].status = SPA_RESULT_NO_FORMAT; - have_error = true; - continue; - } - info[i].status = SPA_RESULT_OK; - } - if (have_error) - return SPA_RESULT_ERROR; - - return SPA_RESULT_OK; -} - -static const SpaNode libva_enc_node = { - sizeof (SpaNode), - spa_libva_enc_node_get_props, - spa_libva_enc_node_set_props, - spa_libva_enc_node_send_command, - spa_libva_enc_node_set_event_callback, - spa_libva_enc_node_get_n_ports, - spa_libva_enc_node_get_port_ids, - spa_libva_enc_node_add_port, - spa_libva_enc_node_remove_port, - spa_libva_enc_node_port_enum_formats, - spa_libva_enc_node_port_set_format, - spa_libva_enc_node_port_get_format, - spa_libva_enc_node_port_get_info, - spa_libva_enc_node_port_get_props, - spa_libva_enc_node_port_set_props, - spa_libva_enc_node_port_use_buffers, - spa_libva_enc_node_port_alloc_buffers, - spa_libva_enc_node_port_get_status, - spa_libva_enc_node_port_push_input, - spa_libva_enc_node_port_pull_output, -}; - -static int -spa_libva_enc_get_interface (SpaHandle *handle, - uint32_t interface_id, - const void **interface) -{ - if (handle == NULL || interface == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - switch (interface_id) { - case SPA_INTERFACE_ID_NODE: - *interface = &libva_enc_node; - break; - default: - return SPA_RESULT_UNKNOWN_INTERFACE; - } - return SPA_RESULT_OK; -} - -SpaHandle * -spa_libva_enc_new (void) -{ - SpaHandle *handle; - SpaLibvaEnc *this; - - handle = calloc (1, sizeof (SpaLibvaEnc)); - handle->get_interface = spa_libva_enc_get_interface; - - this = (SpaLibvaEnc *) handle; - this->props[1].props.n_prop_info = PROP_ID_LAST; - this->props[1].props.prop_info = prop_info; - this->props[1].props.set_prop = spa_props_generic_set_prop; - this->props[1].props.get_prop = spa_props_generic_get_prop; - reset_libva_enc_props (&this->props[1]); - - this->state[INPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[INPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; - - this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE; - this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE; - return handle; -} diff --git a/spa/plugins/libva/libva.c b/spa/plugins/libva/libva.c deleted file mode 100644 index 87c78c3eb..000000000 --- a/spa/plugins/libva/libva.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Spa V4l2 support - * Copyright (C) 2016 Wim Taymans - * - * 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. - */ - -#include -#include - -SpaHandle * spa_libva_dec_new (void); -SpaHandle * spa_libva_enc_new (void); - -static int -libva_dec_instantiate (const struct spa_handle_factory *factory, - SpaHandle **handle) -{ - if (factory == NULL || handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - *handle = spa_libva_dec_new (); - - return SPA_RESULT_OK; -} - -static int -libva_enc_instantiate (const struct spa_handle_factory *factory, - SpaHandle **handle) -{ - if (factory == NULL || handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - *handle = spa_libva_enc_new (); - - return SPA_RESULT_OK; -} - - -static const struct spa_interface_info libva_interfaces[] = -{ - { SPA_INTERFACE_ID_NODE, - SPA_INTERFACE_ID_NODE_NAME, - SPA_INTERFACE_ID_NODE_DESCRIPTION, - }, -}; - -static int -libva_enum_interface_info (const struct spa_handle_factory *factory, - uint32_t index, - const struct spa_interface_info **info) -{ - if (index >= 1) - return SPA_RESULT_ENUM_END; - - *info = &libva_interfaces[index]; - - return SPA_RESULT_OK; -} - -static const struct spa_handle_factory factories[] = -{ - { "libva-dec", - NULL, - libva_dec_instantiate, - libva_enum_interface_info, - }, - { "libva-enc", - NULL, - libva_enc_instantiate, - libva_enum_interface_info, - } -}; - -int -spa_handle_factory_enum (uint32_t index, - const struct spa_handle_factory **factory) -{ - if (index >= 2) - return SPA_RESULT_ENUM_END; - - *factory = &factories[index]; - - return SPA_RESULT_OK; -} diff --git a/spa/plugins/libva/meson.build b/spa/plugins/libva/meson.build deleted file mode 100644 index ced52b4dc..000000000 --- a/spa/plugins/libva/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -libva_sources = ['libva.c', - 'libva-dec.c', - 'libva-enc.c'] - -libvalib = shared_library('spa-libva', - libva_sources, - include_directories : inc, - dependencies : libva_dep, - link_with : spalib, - install : true, - install_dir : '@0@/spa'.format(get_option('libdir'))) diff --git a/spa/plugins/libva/vaapi-recorder.c b/spa/plugins/libva/vaapi-recorder.c deleted file mode 100644 index 1228f7d1e..000000000 --- a/spa/plugins/libva/vaapi-recorder.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* - * Copyright (c) 2012 Intel Corporation. All Rights Reserved. - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "compositor.h" -#include "vaapi-recorder.h" - -#define NAL_REF_IDC_NONE 0 -#define NAL_REF_IDC_LOW 1 -#define NAL_REF_IDC_MEDIUM 2 -#define NAL_REF_IDC_HIGH 3 - -#define NAL_NON_IDR 1 -#define NAL_IDR 5 -#define NAL_SPS 7 -#define NAL_PPS 8 -#define NAL_SEI 6 - -#define SLICE_TYPE_P 0 -#define SLICE_TYPE_B 1 -#define SLICE_TYPE_I 2 - -#define ENTROPY_MODE_CAVLC 0 -#define ENTROPY_MODE_CABAC 1 - -#define PROFILE_IDC_BASELINE 66 -#define PROFILE_IDC_MAIN 77 -#define PROFILE_IDC_HIGH 100 - -struct vaapi_recorder { - int drm_fd, output_fd; - int width, height; - int frame_count; - - int error; - int destroying; - pthread_t worker_thread; - pthread_mutex_t mutex; - pthread_cond_t input_cond; - - struct { - int valid; - int prime_fd, stride; - } input; - - VADisplay va_dpy; - - /* video post processing is used for colorspace conversion */ - struct { - VAConfigID cfg; - VAContextID ctx; - VABufferID pipeline_buf; - VASurfaceID output; - } vpp; - - struct { - VAConfigID cfg; - VAContextID ctx; - VASurfaceID reference_picture[3]; - - int intra_period; - int output_size; - int constraint_set_flag; - - struct { - VAEncSequenceParameterBufferH264 seq; - VAEncPictureParameterBufferH264 pic; - VAEncSliceParameterBufferH264 slice; - } param; - } encoder; -}; - -static void * -worker_thread_function(void *); - -/* bistream code used for writing the packed headers */ - -#define BITSTREAM_ALLOCATE_STEPPING 4096 - -struct bitstream { - unsigned int *buffer; - int bit_offset; - int max_size_in_dword; -}; - -static unsigned int -va_swap32(unsigned int val) -{ - unsigned char *pval = (unsigned char *)&val; - - return ((pval[0] << 24) | - (pval[1] << 16) | - (pval[2] << 8) | - (pval[3] << 0)); -} - -static void -bitstream_start(struct bitstream *bs) -{ - bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING; - bs->buffer = calloc(bs->max_size_in_dword * sizeof(unsigned int), 1); - bs->bit_offset = 0; -} - -static void -bitstream_end(struct bitstream *bs) -{ - int pos = (bs->bit_offset >> 5); - int bit_offset = (bs->bit_offset & 0x1f); - int bit_left = 32 - bit_offset; - - if (bit_offset) { - bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left)); - } -} - -static void -bitstream_put_ui(struct bitstream *bs, unsigned int val, int size_in_bits) -{ - int pos = (bs->bit_offset >> 5); - int bit_offset = (bs->bit_offset & 0x1f); - int bit_left = 32 - bit_offset; - - if (!size_in_bits) - return; - - bs->bit_offset += size_in_bits; - - if (bit_left > size_in_bits) { - bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val); - return; - } - - size_in_bits -= bit_left; - bs->buffer[pos] = - (bs->buffer[pos] << bit_left) | (val >> size_in_bits); - bs->buffer[pos] = va_swap32(bs->buffer[pos]); - - if (pos + 1 == bs->max_size_in_dword) { - bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING; - bs->buffer = - realloc(bs->buffer, - bs->max_size_in_dword * sizeof(unsigned int)); - } - - bs->buffer[pos + 1] = val; -} - -static void -bitstream_put_ue(struct bitstream *bs, unsigned int val) -{ - int size_in_bits = 0; - int tmp_val = ++val; - - while (tmp_val) { - tmp_val >>= 1; - size_in_bits++; - } - - bitstream_put_ui(bs, 0, size_in_bits - 1); /* leading zero */ - bitstream_put_ui(bs, val, size_in_bits); -} - -static void -bitstream_put_se(struct bitstream *bs, int val) -{ - unsigned int new_val; - - if (val <= 0) - new_val = -2 * val; - else - new_val = 2 * val - 1; - - bitstream_put_ue(bs, new_val); -} - -static void -bitstream_byte_aligning(struct bitstream *bs, int bit) -{ - int bit_offset = (bs->bit_offset & 0x7); - int bit_left = 8 - bit_offset; - int new_val; - - if (!bit_offset) - return; - - if (bit) - new_val = (1 << bit_left) - 1; - else - new_val = 0; - - bitstream_put_ui(bs, new_val, bit_left); -} - -static VAStatus -encoder_create_config(struct vaapi_recorder *r) -{ - VAConfigAttrib attrib[2]; - VAStatus status; - - /* FIXME: should check if VAEntrypointEncSlice is supported */ - - /* FIXME: should check if specified attributes are supported */ - - attrib[0].type = VAConfigAttribRTFormat; - attrib[0].value = VA_RT_FORMAT_YUV420; - - attrib[1].type = VAConfigAttribRateControl; - attrib[1].value = VA_RC_CQP; - - status = vaCreateConfig(r->va_dpy, VAProfileH264Main, - VAEntrypointEncSlice, attrib, 2, - &r->encoder.cfg); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaCreateContext(r->va_dpy, r->encoder.cfg, - r->width, r->height, VA_PROGRESSIVE, 0, 0, - &r->encoder.ctx); - if (status != VA_STATUS_SUCCESS) { - vaDestroyConfig(r->va_dpy, r->encoder.cfg); - return status; - } - - return VA_STATUS_SUCCESS; -} - -static void -encoder_destroy_config(struct vaapi_recorder *r) -{ - vaDestroyContext(r->va_dpy, r->encoder.ctx); - vaDestroyConfig(r->va_dpy, r->encoder.cfg); -} - -static void -encoder_init_seq_parameters(struct vaapi_recorder *r) -{ - int width_in_mbs, height_in_mbs; - int frame_cropping_flag = 0; - int frame_crop_bottom_offset = 0; - - width_in_mbs = (r->width + 15) / 16; - height_in_mbs = (r->height + 15) / 16; - - r->encoder.param.seq.level_idc = 41; - r->encoder.param.seq.intra_period = r->encoder.intra_period; - r->encoder.param.seq.max_num_ref_frames = 4; - r->encoder.param.seq.picture_width_in_mbs = width_in_mbs; - r->encoder.param.seq.picture_height_in_mbs = height_in_mbs; - r->encoder.param.seq.seq_fields.bits.frame_mbs_only_flag = 1; - - /* Tc = num_units_in_tick / time_scale */ - r->encoder.param.seq.time_scale = 1800; - r->encoder.param.seq.num_units_in_tick = 15; - - if (height_in_mbs * 16 - r->height > 0) { - frame_cropping_flag = 1; - frame_crop_bottom_offset = (height_in_mbs * 16 - r->height) / 2; - } - - r->encoder.param.seq.frame_cropping_flag = frame_cropping_flag; - r->encoder.param.seq.frame_crop_bottom_offset = frame_crop_bottom_offset; - - r->encoder.param.seq.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2; -} - -static VABufferID -encoder_update_seq_parameters(struct vaapi_recorder *r) -{ - VABufferID seq_buf; - VAStatus status; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncSequenceParameterBufferType, - sizeof(r->encoder.param.seq), - 1, &r->encoder.param.seq, - &seq_buf); - - if (status == VA_STATUS_SUCCESS) - return seq_buf; - else - return VA_INVALID_ID; -} - -static void -encoder_init_pic_parameters(struct vaapi_recorder *r) -{ - VAEncPictureParameterBufferH264 *pic = &r->encoder.param.pic; - - pic->pic_init_qp = 0; - - /* ENTROPY_MODE_CABAC */ - pic->pic_fields.bits.entropy_coding_mode_flag = 1; - - pic->pic_fields.bits.deblocking_filter_control_present_flag = 1; -} - -static VABufferID -encoder_update_pic_parameters(struct vaapi_recorder *r, - VABufferID output_buf) -{ - VAEncPictureParameterBufferH264 *pic = &r->encoder.param.pic; - VAStatus status; - VABufferID pic_param_buf; - VASurfaceID curr_pic, pic0; - - curr_pic = r->encoder.reference_picture[r->frame_count % 2]; - pic0 = r->encoder.reference_picture[(r->frame_count + 1) % 2]; - - pic->CurrPic.picture_id = curr_pic; - pic->CurrPic.TopFieldOrderCnt = r->frame_count * 2; - pic->ReferenceFrames[0].picture_id = pic0; - pic->ReferenceFrames[1].picture_id = r->encoder.reference_picture[2]; - pic->ReferenceFrames[2].picture_id = VA_INVALID_ID; - - pic->coded_buf = output_buf; - pic->frame_num = r->frame_count; - - pic->pic_fields.bits.idr_pic_flag = (r->frame_count == 0); - pic->pic_fields.bits.reference_pic_flag = 1; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncPictureParameterBufferType, - sizeof(VAEncPictureParameterBufferH264), 1, - pic, &pic_param_buf); - - if (status == VA_STATUS_SUCCESS) - return pic_param_buf; - else - return VA_INVALID_ID; -} - -static VABufferID -encoder_update_slice_parameter(struct vaapi_recorder *r, int slice_type) -{ - VABufferID slice_param_buf; - VAStatus status; - - int width_in_mbs = (r->width + 15) / 16; - int height_in_mbs = (r->height + 15) / 16; - - memset(&r->encoder.param.slice, 0, sizeof r->encoder.param.slice); - - r->encoder.param.slice.num_macroblocks = width_in_mbs * height_in_mbs; - r->encoder.param.slice.slice_type = slice_type; - - r->encoder.param.slice.slice_alpha_c0_offset_div2 = 2; - r->encoder.param.slice.slice_beta_offset_div2 = 2; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncSliceParameterBufferType, - sizeof(r->encoder.param.slice), 1, - &r->encoder.param.slice, - &slice_param_buf); - - if (status == VA_STATUS_SUCCESS) - return slice_param_buf; - else - return VA_INVALID_ID; -} - -static VABufferID -encoder_update_misc_hdr_parameter(struct vaapi_recorder *r) -{ - VAEncMiscParameterBuffer *misc_param; - VAEncMiscParameterHRD *hrd; - VABufferID buffer; - VAStatus status; - - int total_size = - sizeof(VAEncMiscParameterBuffer) + - sizeof(VAEncMiscParameterRateControl); - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncMiscParameterBufferType, total_size, - 1, NULL, &buffer); - if (status != VA_STATUS_SUCCESS) - return VA_INVALID_ID; - - status = vaMapBuffer(r->va_dpy, buffer, (void **) &misc_param); - if (status != VA_STATUS_SUCCESS) { - vaDestroyBuffer(r->va_dpy, buffer); - return VA_INVALID_ID; - } - - misc_param->type = VAEncMiscParameterTypeHRD; - hrd = (VAEncMiscParameterHRD *) misc_param->data; - - hrd->initial_buffer_fullness = 0; - hrd->buffer_size = 0; - - vaUnmapBuffer(r->va_dpy, buffer); - - return buffer; -} - -static int -setup_encoder(struct vaapi_recorder *r) -{ - VAStatus status; - - status = encoder_create_config(r); - if (status != VA_STATUS_SUCCESS) { - return -1; - } - - status = vaCreateSurfaces(r->va_dpy, VA_RT_FORMAT_YUV420, - r->width, r->height, - r->encoder.reference_picture, 3, - NULL, 0); - if (status != VA_STATUS_SUCCESS) { - encoder_destroy_config(r); - return -1; - } - - /* VAProfileH264Main */ - r->encoder.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */ - - r->encoder.output_size = r->width * r->height; - - r->encoder.intra_period = 30; - - encoder_init_seq_parameters(r); - encoder_init_pic_parameters(r); - - return 0; -} - -static void -encoder_destroy(struct vaapi_recorder *r) -{ - vaDestroySurfaces(r->va_dpy, r->encoder.reference_picture, 3); - - encoder_destroy_config(r); -} - -static void -nal_start_code_prefix(struct bitstream *bs) -{ - bitstream_put_ui(bs, 0x00000001, 32); -} - -static void -nal_header(struct bitstream *bs, int nal_ref_idc, int nal_unit_type) -{ - /* forbidden_zero_bit: 0 */ - bitstream_put_ui(bs, 0, 1); - - bitstream_put_ui(bs, nal_ref_idc, 2); - bitstream_put_ui(bs, nal_unit_type, 5); -} - -static void -rbsp_trailing_bits(struct bitstream *bs) -{ - bitstream_put_ui(bs, 1, 1); - bitstream_byte_aligning(bs, 0); -} - -static void sps_rbsp(struct bitstream *bs, - VAEncSequenceParameterBufferH264 *seq, - int constraint_set_flag) -{ - int i; - - bitstream_put_ui(bs, PROFILE_IDC_MAIN, 8); - - /* constraint_set[0-3] flag */ - for (i = 0; i < 4; i++) { - int set = (constraint_set_flag & (1 << i)) ? 1 : 0; - bitstream_put_ui(bs, set, 1); - } - - /* reserved_zero_4bits */ - bitstream_put_ui(bs, 0, 4); - bitstream_put_ui(bs, seq->level_idc, 8); - bitstream_put_ue(bs, seq->seq_parameter_set_id); - - bitstream_put_ue(bs, seq->seq_fields.bits.log2_max_frame_num_minus4); - bitstream_put_ue(bs, seq->seq_fields.bits.pic_order_cnt_type); - bitstream_put_ue(bs, - seq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4); - - bitstream_put_ue(bs, seq->max_num_ref_frames); - - /* gaps_in_frame_num_value_allowed_flag */ - bitstream_put_ui(bs, 0, 1); - - /* pic_width_in_mbs_minus1, pic_height_in_map_units_minus1 */ - bitstream_put_ue(bs, seq->picture_width_in_mbs - 1); - bitstream_put_ue(bs, seq->picture_height_in_mbs - 1); - - bitstream_put_ui(bs, seq->seq_fields.bits.frame_mbs_only_flag, 1); - bitstream_put_ui(bs, seq->seq_fields.bits.direct_8x8_inference_flag, 1); - - bitstream_put_ui(bs, seq->frame_cropping_flag, 1); - - if (seq->frame_cropping_flag) { - bitstream_put_ue(bs, seq->frame_crop_left_offset); - bitstream_put_ue(bs, seq->frame_crop_right_offset); - bitstream_put_ue(bs, seq->frame_crop_top_offset); - bitstream_put_ue(bs, seq->frame_crop_bottom_offset); - } - - /* vui_parameters_present_flag */ - bitstream_put_ui(bs, 1, 1); - - /* aspect_ratio_info_present_flag */ - bitstream_put_ui(bs, 0, 1); - /* overscan_info_present_flag */ - bitstream_put_ui(bs, 0, 1); - - /* video_signal_type_present_flag */ - bitstream_put_ui(bs, 0, 1); - /* chroma_loc_info_present_flag */ - bitstream_put_ui(bs, 0, 1); - - /* timing_info_present_flag */ - bitstream_put_ui(bs, 1, 1); - bitstream_put_ui(bs, seq->num_units_in_tick, 32); - bitstream_put_ui(bs, seq->time_scale, 32); - /* fixed_frame_rate_flag */ - bitstream_put_ui(bs, 1, 1); - - /* nal_hrd_parameters_present_flag */ - bitstream_put_ui(bs, 0, 1); - - /* vcl_hrd_parameters_present_flag */ - bitstream_put_ui(bs, 0, 1); - - /* low_delay_hrd_flag */ - bitstream_put_ui(bs, 0, 1); - - /* pic_struct_present_flag */ - bitstream_put_ui(bs, 0, 1); - /* bitstream_restriction_flag */ - bitstream_put_ui(bs, 0, 1); - - rbsp_trailing_bits(bs); -} - -static void pps_rbsp(struct bitstream *bs, - VAEncPictureParameterBufferH264 *pic) -{ - /* pic_parameter_set_id, seq_parameter_set_id */ - bitstream_put_ue(bs, pic->pic_parameter_set_id); - bitstream_put_ue(bs, pic->seq_parameter_set_id); - - bitstream_put_ui(bs, pic->pic_fields.bits.entropy_coding_mode_flag, 1); - - /* pic_order_present_flag: 0 */ - bitstream_put_ui(bs, 0, 1); - - /* num_slice_groups_minus1 */ - bitstream_put_ue(bs, 0); - - bitstream_put_ue(bs, pic->num_ref_idx_l0_active_minus1); - bitstream_put_ue(bs, pic->num_ref_idx_l1_active_minus1); - - bitstream_put_ui(bs, pic->pic_fields.bits.weighted_pred_flag, 1); - bitstream_put_ui(bs, pic->pic_fields.bits.weighted_bipred_idc, 2); - - /* pic_init_qp_minus26, pic_init_qs_minus26, chroma_qp_index_offset */ - bitstream_put_se(bs, pic->pic_init_qp - 26); - bitstream_put_se(bs, 0); - bitstream_put_se(bs, 0); - - bitstream_put_ui(bs, pic->pic_fields.bits.deblocking_filter_control_present_flag, 1); - - /* constrained_intra_pred_flag, redundant_pic_cnt_present_flag */ - bitstream_put_ui(bs, 0, 1); - bitstream_put_ui(bs, 0, 1); - - bitstream_put_ui(bs, pic->pic_fields.bits.transform_8x8_mode_flag, 1); - - /* pic_scaling_matrix_present_flag */ - bitstream_put_ui(bs, 0, 1); - bitstream_put_se(bs, pic->second_chroma_qp_index_offset ); - - rbsp_trailing_bits(bs); -} - -static int -build_packed_pic_buffer(struct vaapi_recorder *r, - void **header_buffer) -{ - struct bitstream bs; - - bitstream_start(&bs); - nal_start_code_prefix(&bs); - nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS); - pps_rbsp(&bs, &r->encoder.param.pic); - bitstream_end(&bs); - - *header_buffer = bs.buffer; - return bs.bit_offset; -} - -static int -build_packed_seq_buffer(struct vaapi_recorder *r, - void **header_buffer) -{ - struct bitstream bs; - - bitstream_start(&bs); - nal_start_code_prefix(&bs); - nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS); - sps_rbsp(&bs, &r->encoder.param.seq, r->encoder.constraint_set_flag); - bitstream_end(&bs); - - *header_buffer = bs.buffer; - return bs.bit_offset; -} - -static int -create_packed_header_buffers(struct vaapi_recorder *r, VABufferID *buffers, - VAEncPackedHeaderType type, - void *data, int bit_length) -{ - VAEncPackedHeaderParameterBuffer packed_header; - VAStatus status; - - packed_header.type = type; - packed_header.bit_length = bit_length; - packed_header.has_emulation_bytes = 0; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncPackedHeaderParameterBufferType, - sizeof packed_header, 1, &packed_header, - &buffers[0]); - if (status != VA_STATUS_SUCCESS) - return 0; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncPackedHeaderDataBufferType, - (bit_length + 7) / 8, 1, data, &buffers[1]); - if (status != VA_STATUS_SUCCESS) { - vaDestroyBuffer(r->va_dpy, buffers[0]); - return 0; - } - - return 2; -} - -static int -encoder_prepare_headers(struct vaapi_recorder *r, VABufferID *buffers) -{ - VABufferID *p; - - int bit_length; - void *data; - - p = buffers; - - bit_length = build_packed_seq_buffer(r, &data); - p += create_packed_header_buffers(r, p, VAEncPackedHeaderSequence, - data, bit_length); - free(data); - - bit_length = build_packed_pic_buffer(r, &data); - p += create_packed_header_buffers(r, p, VAEncPackedHeaderPicture, - data, bit_length); - free(data); - - return p - buffers; -} - -static VAStatus -encoder_render_picture(struct vaapi_recorder *r, VASurfaceID input, - VABufferID *buffers, int count) -{ - VAStatus status; - - status = vaBeginPicture(r->va_dpy, r->encoder.ctx, input); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaRenderPicture(r->va_dpy, r->encoder.ctx, buffers, count); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaEndPicture(r->va_dpy, r->encoder.ctx); - if (status != VA_STATUS_SUCCESS) - return status; - - return vaSyncSurface(r->va_dpy, input); -} - -static VABufferID -encoder_create_output_buffer(struct vaapi_recorder *r) -{ - VABufferID output_buf; - VAStatus status; - - status = vaCreateBuffer(r->va_dpy, r->encoder.ctx, - VAEncCodedBufferType, r->encoder.output_size, - 1, NULL, &output_buf); - if (status == VA_STATUS_SUCCESS) - return output_buf; - else - return VA_INVALID_ID; -} - -enum output_write_status { - OUTPUT_WRITE_SUCCESS, - OUTPUT_WRITE_OVERFLOW, - OUTPUT_WRITE_FATAL -}; - -static enum output_write_status -encoder_write_output(struct vaapi_recorder *r, VABufferID output_buf) -{ - VACodedBufferSegment *segment; - VAStatus status; - int count; - - status = vaMapBuffer(r->va_dpy, output_buf, (void **) &segment); - if (status != VA_STATUS_SUCCESS) - return OUTPUT_WRITE_FATAL; - - if (segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) { - r->encoder.output_size *= 2; - vaUnmapBuffer(r->va_dpy, output_buf); - return OUTPUT_WRITE_OVERFLOW; - } - - count = write(r->output_fd, segment->buf, segment->size); - - vaUnmapBuffer(r->va_dpy, output_buf); - - if (count < 0) - return OUTPUT_WRITE_FATAL; - - return OUTPUT_WRITE_SUCCESS; -} - -static void -encoder_encode(struct vaapi_recorder *r, VASurfaceID input) -{ - VABufferID output_buf = VA_INVALID_ID; - - VABufferID buffers[8]; - int count = 0; - int i, slice_type; - enum output_write_status ret; - - if ((r->frame_count % r->encoder.intra_period) == 0) - slice_type = SLICE_TYPE_I; - else - slice_type = SLICE_TYPE_P; - - buffers[count++] = encoder_update_seq_parameters(r); - buffers[count++] = encoder_update_misc_hdr_parameter(r); - buffers[count++] = encoder_update_slice_parameter(r, slice_type); - - for (i = 0; i < count; i++) - if (buffers[i] == VA_INVALID_ID) - goto bail; - - if (r->frame_count == 0) - count += encoder_prepare_headers(r, buffers + count); - - do { - output_buf = encoder_create_output_buffer(r); - if (output_buf == VA_INVALID_ID) - goto bail; - - buffers[count++] = - encoder_update_pic_parameters(r, output_buf); - if (buffers[count - 1] == VA_INVALID_ID) - goto bail; - - encoder_render_picture(r, input, buffers, count); - ret = encoder_write_output(r, output_buf); - - vaDestroyBuffer(r->va_dpy, output_buf); - output_buf = VA_INVALID_ID; - - vaDestroyBuffer(r->va_dpy, buffers[--count]); - } while (ret == OUTPUT_WRITE_OVERFLOW); - - if (ret == OUTPUT_WRITE_FATAL) - r->error = errno; - - for (i = 0; i < count; i++) - vaDestroyBuffer(r->va_dpy, buffers[i]); - - r->frame_count++; - return; - -bail: - for (i = 0; i < count; i++) - vaDestroyBuffer(r->va_dpy, buffers[i]); - if (output_buf != VA_INVALID_ID) - vaDestroyBuffer(r->va_dpy, output_buf); -} - - -static int -setup_vpp(struct vaapi_recorder *r) -{ - VAStatus status; - - status = vaCreateConfig(r->va_dpy, VAProfileNone, - VAEntrypointVideoProc, NULL, 0, - &r->vpp.cfg); - if (status != VA_STATUS_SUCCESS) { - weston_log("vaapi: failed to create VPP config\n"); - return -1; - } - - status = vaCreateContext(r->va_dpy, r->vpp.cfg, r->width, r->height, - 0, NULL, 0, &r->vpp.ctx); - if (status != VA_STATUS_SUCCESS) { - weston_log("vaapi: failed to create VPP context\n"); - goto err_cfg; - } - - status = vaCreateBuffer(r->va_dpy, r->vpp.ctx, - VAProcPipelineParameterBufferType, - sizeof(VAProcPipelineParameterBuffer), - 1, NULL, &r->vpp.pipeline_buf); - if (status != VA_STATUS_SUCCESS) { - weston_log("vaapi: failed to create VPP pipeline buffer\n"); - goto err_ctx; - } - - status = vaCreateSurfaces(r->va_dpy, VA_RT_FORMAT_YUV420, - r->width, r->height, &r->vpp.output, 1, - NULL, 0); - if (status != VA_STATUS_SUCCESS) { - weston_log("vaapi: failed to create YUV surface\n"); - goto err_buf; - } - - return 0; - -err_buf: - vaDestroyBuffer(r->va_dpy, r->vpp.pipeline_buf); -err_ctx: - vaDestroyConfig(r->va_dpy, r->vpp.ctx); -err_cfg: - vaDestroyConfig(r->va_dpy, r->vpp.cfg); - - return -1; -} - -static void -vpp_destroy(struct vaapi_recorder *r) -{ - vaDestroySurfaces(r->va_dpy, &r->vpp.output, 1); - vaDestroyBuffer(r->va_dpy, r->vpp.pipeline_buf); - vaDestroyConfig(r->va_dpy, r->vpp.ctx); - vaDestroyConfig(r->va_dpy, r->vpp.cfg); -} - -static int -setup_worker_thread(struct vaapi_recorder *r) -{ - pthread_mutex_init(&r->mutex, NULL); - pthread_cond_init(&r->input_cond, NULL); - pthread_create(&r->worker_thread, NULL, worker_thread_function, r); - - return 1; -} - -static void -destroy_worker_thread(struct vaapi_recorder *r) -{ - pthread_mutex_lock(&r->mutex); - - /* Make sure the worker thread finishes */ - r->destroying = 1; - pthread_cond_signal(&r->input_cond); - - pthread_mutex_unlock(&r->mutex); - - pthread_join(r->worker_thread, NULL); - - pthread_mutex_destroy(&r->mutex); - pthread_cond_destroy(&r->input_cond); -} - -struct vaapi_recorder * -vaapi_recorder_create(int drm_fd, int width, int height, const char *filename) -{ - struct vaapi_recorder *r; - VAStatus status; - int major, minor; - int flags; - - r = zalloc(sizeof *r); - if (r == NULL) - return NULL; - - r->width = width; - r->height = height; - r->drm_fd = drm_fd; - - if (setup_worker_thread(r) < 0) - goto err_free; - - flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; - r->output_fd = open(filename, flags, 0644); - if (r->output_fd < 0) - goto err_thread; - - r->va_dpy = vaGetDisplayDRM(drm_fd); - if (!r->va_dpy) { - weston_log("failed to create VA display\n"); - goto err_fd; - } - - status = vaInitialize(r->va_dpy, &major, &minor); - if (status != VA_STATUS_SUCCESS) { - weston_log("vaapi: failed to initialize display\n"); - goto err_fd; - } - - if (setup_vpp(r) < 0) { - weston_log("vaapi: failed to initialize VPP pipeline\n"); - goto err_va_dpy; - } - - if (setup_encoder(r) < 0) { - goto err_vpp; - } - - return r; - -err_vpp: - vpp_destroy(r); -err_va_dpy: - vaTerminate(r->va_dpy); -err_fd: - close(r->output_fd); -err_thread: - destroy_worker_thread(r); -err_free: - free(r); - - return NULL; -} - -void -vaapi_recorder_destroy(struct vaapi_recorder *r) -{ - destroy_worker_thread(r); - - encoder_destroy(r); - vpp_destroy(r); - - vaTerminate(r->va_dpy); - - close(r->output_fd); - close(r->drm_fd); - - free(r); -} - -static VAStatus -create_surface_from_fd(struct vaapi_recorder *r, int prime_fd, - int stride, VASurfaceID *surface) -{ - VASurfaceAttrib va_attribs[2]; - VASurfaceAttribExternalBuffers va_attrib_extbuf; - VAStatus status; - - unsigned long buffer_fd = prime_fd; - - va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX; - va_attrib_extbuf.width = r->width; - va_attrib_extbuf.height = r->height; - va_attrib_extbuf.data_size = r->height * stride; - va_attrib_extbuf.num_planes = 1; - va_attrib_extbuf.pitches[0] = stride; - va_attrib_extbuf.offsets[0] = 0; - va_attrib_extbuf.buffers = &buffer_fd; - va_attrib_extbuf.num_buffers = 1; - va_attrib_extbuf.flags = 0; - va_attrib_extbuf.private_data = NULL; - - va_attribs[0].type = VASurfaceAttribMemoryType; - va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; - va_attribs[0].value.type = VAGenericValueTypeInteger; - va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; - - va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; - va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; - va_attribs[1].value.type = VAGenericValueTypePointer; - va_attribs[1].value.value.p = &va_attrib_extbuf; - - status = vaCreateSurfaces(r->va_dpy, VA_RT_FORMAT_RGB32, - r->width, r->height, surface, 1, - va_attribs, 2); - - return status; -} - -static VAStatus -convert_rgb_to_yuv(struct vaapi_recorder *r, VASurfaceID rgb_surface) -{ - VAProcPipelineParameterBuffer *pipeline_param; - VAStatus status; - - status = vaMapBuffer(r->va_dpy, r->vpp.pipeline_buf, - (void **) &pipeline_param); - if (status != VA_STATUS_SUCCESS) - return status; - - memset(pipeline_param, 0, sizeof *pipeline_param); - - pipeline_param->surface = rgb_surface; - pipeline_param->surface_color_standard = VAProcColorStandardNone; - - pipeline_param->output_background_color = 0xff000000; - pipeline_param->output_color_standard = VAProcColorStandardNone; - - status = vaUnmapBuffer(r->va_dpy, r->vpp.pipeline_buf); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaBeginPicture(r->va_dpy, r->vpp.ctx, r->vpp.output); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaRenderPicture(r->va_dpy, r->vpp.ctx, - &r->vpp.pipeline_buf, 1); - if (status != VA_STATUS_SUCCESS) - return status; - - status = vaEndPicture(r->va_dpy, r->vpp.ctx); - if (status != VA_STATUS_SUCCESS) - return status; - - return status; -} - -static void -recorder_frame(struct vaapi_recorder *r) -{ - VASurfaceID rgb_surface; - VAStatus status; - - status = create_surface_from_fd(r, r->input.prime_fd, - r->input.stride, &rgb_surface); - if (status != VA_STATUS_SUCCESS) { - weston_log("[libva recorder] " - "failed to create surface from bo\n"); - return; - } - - close(r->input.prime_fd); - - status = convert_rgb_to_yuv(r, rgb_surface); - if (status != VA_STATUS_SUCCESS) { - weston_log("[libva recorder] " - "color space conversion failed\n"); - return; - } - - encoder_encode(r, r->vpp.output); - - vaDestroySurfaces(r->va_dpy, &rgb_surface, 1); -} - -static void * -worker_thread_function(void *data) -{ - struct vaapi_recorder *r = data; - - pthread_mutex_lock(&r->mutex); - - while (!r->destroying) { - if (!r->input.valid) - pthread_cond_wait(&r->input_cond, &r->mutex); - - /* If the thread is awaken by destroy_worker_thread(), - * there might not be valid input */ - if (!r->input.valid) - continue; - - recorder_frame(r); - r->input.valid = 0; - } - - pthread_mutex_unlock(&r->mutex); - - return NULL; -} - -int -vaapi_recorder_frame(struct vaapi_recorder *r, int prime_fd, int stride) -{ - int ret = 0; - - pthread_mutex_lock(&r->mutex); - - if (r->error) { - errno = r->error; - ret = -1; - goto unlock; - } - - /* The mutex is never released while encoding, so this point should - * never be reached if input.valid is true. */ - assert(!r->input.valid); - - r->input.prime_fd = prime_fd; - r->input.stride = stride; - r->input.valid = 1; - pthread_cond_signal(&r->input_cond); - -unlock: - pthread_mutex_unlock(&r->mutex); - - return ret; -} diff --git a/spa/plugins/libva/vaapi-recorder.h b/spa/plugins/libva/vaapi-recorder.h deleted file mode 100644 index 6b194aa81..000000000 --- a/spa/plugins/libva/vaapi-recorder.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _VAAPI_RECORDER_H_ -#define _VAAPI_RECORDER_H_ - -struct vaapi_recorder; - -struct vaapi_recorder * -vaapi_recorder_create(int drm_fd, int width, int height, const char *filename); -void -vaapi_recorder_destroy(struct vaapi_recorder *r); -int -vaapi_recorder_frame(struct vaapi_recorder *r, int fd, int stride); - -#endif /* _VAAPI_RECORDER_H_ */ diff --git a/spa/plugins/meson.build b/spa/plugins/meson.build index 4e5ced214..455659593 100644 --- a/spa/plugins/meson.build +++ b/spa/plugins/meson.build @@ -3,8 +3,6 @@ subdir('audiomixer') subdir('audiotestsrc') subdir('ffmpeg') subdir('test') -#subdir('libva') subdir('videotestsrc') subdir('volume') subdir('v4l2') -subdir('xv') diff --git a/spa/plugins/test/fakesink.c b/spa/plugins/test/fakesink.c index ed685f34b..e8c049d58 100644 --- a/spa/plugins/test/fakesink.c +++ b/spa/plugins/test/fakesink.c @@ -36,84 +36,83 @@ #define NAME "fakesink" struct type { - uint32_t node; - uint32_t clock; - uint32_t format; - uint32_t props; - uint32_t prop_live; - struct spa_type_meta meta; - struct spa_type_data data; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + uint32_t node; + uint32_t clock; + uint32_t format; + uint32_t props; + uint32_t prop_live; + struct spa_type_meta meta; + struct spa_type_data data; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->clock = spa_type_map_get_id (map, SPA_TYPE__Clock); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_live = spa_type_map_get_id (map, SPA_TYPE_PROPS__live); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->clock = spa_type_map_get_id(map, SPA_TYPE__Clock); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); } struct props { - bool live; + bool live; }; #define MAX_BUFFERS 16 #define MAX_PORTS 1 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + struct spa_list link; }; struct impl { - struct spa_handle handle; - struct spa_node node; - struct spa_clock clock; + struct spa_handle handle; + struct spa_node node; + struct spa_clock clock; - struct type type; - struct spa_type_map *map; - struct spa_log *log; - struct spa_loop *data_loop; + struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct spa_loop *data_loop; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct spa_source timer_source; - struct itimerspec timerspec; + struct spa_source timer_source; + struct itimerspec timerspec; - struct spa_port_info info; - uint8_t params_buffer[1024]; - struct spa_port_io *io; + struct spa_port_info info; + uint8_t params_buffer[1024]; + struct spa_port_io *io; - bool have_format; - uint8_t format_buffer[1024]; + bool have_format; + uint8_t format_buffer[1024]; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - bool started; - uint64_t start_time; - uint64_t elapsed_time; + bool started; + uint64_t start_time; + uint64_t elapsed_time; - uint64_t buffer_count; - struct spa_list ready; + uint64_t buffer_count; + struct spa_list ready; }; #define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS) @@ -121,10 +120,9 @@ struct impl { #define DEFAULT_LIVE false -static void -reset_props (struct impl *this, struct props *props) +static void reset_props(struct impl *this, struct props *props) { - props->live = DEFAULT_LIVE; + props->live = DEFAULT_LIVE; } #define PROP(f,key,type,...) \ @@ -140,773 +138,745 @@ reset_props (struct impl *this, struct props *props) SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, this->props.live)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, + this->props.live)); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (props == NULL) { + reset_props(this, &this->props); + } else { + spa_props_query(props, + this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, 0); + } + + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + else + this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; + + return SPA_RESULT_OK; +} + +static void set_timer(struct impl *this, bool enabled) +{ + if (this->callbacks.need_input || this->props.live) { + if (enabled) { + if (this->props.live) { + uint64_t next_time = this->start_time + this->elapsed_time; + this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; + this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 1; + } + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + } + timerfd_settime(this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); + } +} + +static inline void read_timer(struct impl *this) +{ + uint64_t expirations; + + if (this->callbacks.need_input || this->props.live) { + if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) < sizeof(uint64_t)) + perror("read timerfd"); + } +} + +static void render_buffer(struct impl *this, struct buffer *b) +{ +} + +static int consume_buffer(struct impl *this) +{ + struct buffer *b; + struct spa_port_io *io = this->io; + int n_bytes; + + read_timer(this); + + if (spa_list_is_empty(&this->ready)) { + io->status = SPA_RESULT_NEED_BUFFER; + if (this->callbacks.need_input) + this->callbacks.need_input(&this->node, this->user_data); + } + if (spa_list_is_empty(&this->ready)) { + spa_log_error(this->log, NAME " %p: no buffers", this); + return SPA_RESULT_NEED_BUFFER; + } + + b = spa_list_first(&this->ready, struct buffer, link); + spa_list_remove(&b->link); + + n_bytes = b->outbuf->datas[0].maxsize; + + spa_log_trace(this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); + + render_buffer(this, b); + + b->outbuf->datas[0].chunk->offset = 0; + b->outbuf->datas[0].chunk->size = n_bytes; + b->outbuf->datas[0].chunk->stride = n_bytes; + + if (b->h) { + b->h->seq = this->buffer_count; + b->h->pts = this->start_time + this->elapsed_time; + b->h->dts_offset = 0; + } + + this->buffer_count++; + this->elapsed_time = this->buffer_count; + set_timer(this, true); + + io->buffer_id = b->outbuf->id; + io->status = SPA_RESULT_NEED_BUFFER; + b->outstanding = true; + + return SPA_RESULT_NEED_BUFFER; +} + +static void on_input(struct spa_source *source) +{ + struct impl *this = source->data; + + consume_buffer(this); +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + struct timespec now; + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (this->started) + return SPA_RESULT_OK; + + clock_gettime(CLOCK_MONOTONIC, &now); + if (this->props.live) + this->start_time = SPA_TIMESPEC_TO_TIME(&now); + else + this->start_time = 0; + this->buffer_count = 0; + this->elapsed_time = 0; + + this->started = true; + set_timer(this, true); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (!this->started) + return SPA_RESULT_OK; + + this->started = false; + set_timer(this, false); + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (props == NULL) { - reset_props (this, &this->props); - } else { - spa_props_query (props, - this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, - 0); - } + if (this->data_loop == NULL && callbacks->need_input != NULL) { + spa_log_error(this->log, "a data_loop is needed for async operation"); + return SPA_RESULT_ERROR; + } + this->callbacks = *callbacks; + this->user_data = user_data; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - else - this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; - - return SPA_RESULT_OK; -} - -static void -set_timer (struct impl *this, bool enabled) -{ - if (this->callbacks.need_input || this->props.live) { - if (enabled) { - if (this->props.live) { - uint64_t next_time = this->start_time + this->elapsed_time; - this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; - this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 1; - } - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - } - timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); - } -} - -static inline void -read_timer (struct impl *this) -{ - uint64_t expirations; - - if (this->callbacks.need_input || this->props.live) { - if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t)) - perror ("read timerfd"); - } -} - -static void -render_buffer (struct impl *this, struct buffer *b) -{ + return SPA_RESULT_OK; } static int -consume_buffer (struct impl *this) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct buffer *b; - struct spa_port_io *io = this->io; - int n_bytes; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - read_timer (this); + if (n_input_ports) + *n_input_ports = 0; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 0; + if (max_output_ports) + *max_output_ports = 1; - if (spa_list_is_empty (&this->ready)) { - io->status = SPA_RESULT_NEED_BUFFER; - if (this->callbacks.need_input) - this->callbacks.need_input (&this->node, this->user_data); - } - if (spa_list_is_empty (&this->ready)) { - spa_log_error (this->log, NAME " %p: no buffers", this); - return SPA_RESULT_NEED_BUFFER; - } - - b = spa_list_first (&this->ready, struct buffer, link); - spa_list_remove (&b->link); - - n_bytes = b->outbuf->datas[0].maxsize; - - spa_log_trace (this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); - - render_buffer (this, b); - - b->outbuf->datas[0].chunk->offset = 0; - b->outbuf->datas[0].chunk->size = n_bytes; - b->outbuf->datas[0].chunk->stride = n_bytes; - - if (b->h) { - b->h->seq = this->buffer_count; - b->h->pts = this->start_time + this->elapsed_time; - b->h->dts_offset = 0; - } - - this->buffer_count++; - this->elapsed_time = this->buffer_count; - set_timer (this, true); - - io->buffer_id = b->outbuf->id; - io->status = SPA_RESULT_NEED_BUFFER; - b->outstanding = true; - - return SPA_RESULT_NEED_BUFFER; -} - -static void -on_input (struct spa_source *source) -{ - struct impl *this = source->data; - - consume_buffer (this); + return SPA_RESULT_OK; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); + return SPA_RESULT_OK; +} - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - struct timespec now; - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (this->started) - return SPA_RESULT_OK; - - clock_gettime (CLOCK_MONOTONIC, &now); - if (this->props.live) - this->start_time = SPA_TIMESPEC_TO_TIME (&now); - else - this->start_time = 0; - this->buffer_count = 0; - this->elapsed_time = 0; - - this->started = true; - set_timer (this, true); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (!this->started) - return SPA_RESULT_OK; - - this->started = false; - set_timer (this, false); - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (this->data_loop == NULL && callbacks->need_input != NULL) { - spa_log_error (this->log, "a data_loop is needed for async operation"); - return SPA_RESULT_ERROR; - } - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, uint32_t index) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; - if (n_input_ports) - *n_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 0; - if (max_output_ports) - *max_output_ports = 1; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + return SPA_RESULT_ENUM_END; +} + +static int clear_buffers(struct impl *this) +{ + if (this->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers", this); + this->n_buffers = 0; + spa_list_init(&this->ready); + this->started = false; + set_timer(this, false); + } + return SPA_RESULT_OK; } static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (format == NULL) { + this->have_format = false; + clear_buffers(this); + } else { + if (SPA_POD_SIZE(format) > sizeof(this->format_buffer)) + return SPA_RESULT_ERROR; + memcpy(this->format_buffer, format, SPA_POD_SIZE(format)); + this->have_format = true; + } + return SPA_RESULT_OK; } static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + *format = (const struct spa_format *) this->format_buffer; + + return SPA_RESULT_OK; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + *info = &this->info; + + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - struct impl *this; + struct impl *this; + struct spa_pod_builder b = { NULL }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - return SPA_RESULT_ENUM_END; + spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer)); + + switch (index) { + case 0: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + 128), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + 1), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + 32, + 2, 32), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, + 16)); + break; + + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; + + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; } static int -clear_buffers (struct impl *this) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - if (this->n_buffers > 0) { - spa_log_info (this->log, NAME " %p: clear buffers", this); - this->n_buffers = 0; - spa_list_init (&this->ready); - this->started = false; - set_timer (this, false); - } - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - struct impl *this; + struct impl *this; + uint32_t i; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (format == NULL) { - this->have_format = false; - clear_buffers (this); - } else { - if (SPA_POD_SIZE (format) > sizeof (this->format_buffer)) - return SPA_RESULT_ERROR; - memcpy (this->format_buffer, format, SPA_POD_SIZE (format)); - this->have_format = true; - } - return SPA_RESULT_OK; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + clear_buffers(this); + + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; + + b = &this->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = true; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) { + spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this, + buffers[i]); + } + } + this->n_buffers = n_buffers; + + return SPA_RESULT_OK; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t *n_buffers) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - *format = (const struct spa_format *) this->format_buffer; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT_NUM(this, direction, port_id), SPA_RESULT_INVALID_PORT); - *info = &this->info; + this->io = io; - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; - struct spa_pod_builder b = { NULL }; - struct spa_pod_frame f[2]; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - spa_pod_builder_init (&b, this->params_buffer, sizeof (this->params_buffer)); - - switch (index) { - case 0: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, 128), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 1), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; - - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; - - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +static int impl_node_process_input(struct spa_node *node) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct spa_port_io *input; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + input = this->io; + spa_return_val_if_fail(input != NULL, SPA_RESULT_WRONG_STATE); + + if (input->status == SPA_RESULT_HAVE_BUFFER && input->buffer_id != SPA_ID_INVALID) { + struct buffer *b = &this->buffers[input->buffer_id]; + + if (!b->outstanding) { + spa_log_warn(this->log, NAME " %p: buffer %u in use", this, + input->buffer_id); + input->status = SPA_RESULT_INVALID_BUFFER_ID; + return SPA_RESULT_ERROR; + } + + spa_log_trace(this->log, NAME " %p: queue buffer %u", this, input->buffer_id); + + spa_list_insert(this->ready.prev, &b->link); + b->outstanding = false; + + input->buffer_id = SPA_ID_INVALID; + input->status = SPA_RESULT_OK; + } + if (this->callbacks.need_input == NULL) + return consume_buffer(this); + else + return SPA_RESULT_OK; } -static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +static int impl_node_process_output(struct spa_node *node) { - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - clear_buffers (this); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &this->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = true; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data == NULL) { - spa_log_error (this->log, NAME " %p: invalid memory on buffer %p", this, buffers[i]); - } - } - this->n_buffers = n_buffers; - - return SPA_RESULT_OK; -} - -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->io = io; - - return SPA_RESULT_OK; -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_input (struct spa_node *node) -{ - struct impl *this; - struct spa_port_io *input; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - input = this->io; - spa_return_val_if_fail (input != NULL, SPA_RESULT_WRONG_STATE); - - if (input->status == SPA_RESULT_HAVE_BUFFER && - input->buffer_id != SPA_ID_INVALID) { - struct buffer *b = &this->buffers[input->buffer_id]; - - if (!b->outstanding) { - spa_log_warn (this->log, NAME " %p: buffer %u in use", this, input->buffer_id); - input->status = SPA_RESULT_INVALID_BUFFER_ID; - return SPA_RESULT_ERROR; - } - - spa_log_trace (this->log, NAME " %p: queue buffer %u", this, input->buffer_id); - - spa_list_insert (this->ready.prev, &b->link); - b->outstanding = false; - - input->buffer_id = SPA_ID_INVALID; - input->status = SPA_RESULT_OK; - } - if (this->callbacks.need_input == NULL) - return consume_buffer (this); - else - return SPA_RESULT_OK; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, }; -static int -impl_clock_get_props (struct spa_clock *clock, - struct spa_props **props) +static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_clock_set_props (struct spa_clock *clock, - const struct spa_props *props) +impl_clock_get_time(struct spa_clock *clock, + int32_t *rate, + int64_t *ticks, + int64_t *monotonic_time) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct timespec now; + uint64_t tnow; -static int -impl_clock_get_time (struct spa_clock *clock, - int32_t *rate, - int64_t *ticks, - int64_t *monotonic_time) -{ - struct timespec now; - uint64_t tnow; + spa_return_val_if_fail(clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (rate) + *rate = SPA_NSEC_PER_SEC; - if (rate) - *rate = SPA_NSEC_PER_SEC; + clock_gettime(CLOCK_MONOTONIC, &now); + tnow = SPA_TIMESPEC_TO_TIME(&now); - clock_gettime (CLOCK_MONOTONIC, &now); - tnow = SPA_TIMESPEC_TO_TIME (&now); + if (ticks) + *ticks = tnow; + if (monotonic_time) + *monotonic_time = tnow; - if (ticks) - *ticks = tnow; - if (monotonic_time) - *monotonic_time = tnow; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_clock impl_clock = { - sizeof (struct spa_clock), - NULL, - SPA_CLOCK_STATE_STOPPED, - impl_clock_get_props, - impl_clock_set_props, - impl_clock_get_time, + sizeof(struct spa_clock), + NULL, + SPA_CLOCK_STATE_STOPPED, + impl_clock_get_props, + impl_clock_set_props, + impl_clock_get_time, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.node) + *interface = &this->node; + else if (interface_id == this->type.clock) + *interface = &this->clock; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (this->data_loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + close(this->timer_source.fd); + + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) + this->data_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + this->clock = impl_clock; + reset_props(this, &this->props); + + spa_list_init(&this->ready); + + this->timer_source.func = on_input; + this->timer_source.data = this; + this->timer_source.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + this->timerspec.it_interval.tv_sec = 0; + this->timerspec.it_interval.tv_nsec = 0; + + if (this->data_loop) + spa_loop_add_source(this->data_loop, &this->timer_source); + + this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + + spa_log_info(this->log, NAME " %p: initialized", this); + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, + {SPA_TYPE__Clock,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else if (interface_id == this->type.clock) - *interface = &this->clock; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - struct impl *this; - - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (this->data_loop) - spa_loop_remove_source (this->data_loop, &this->timer_source); - close (this->timer_source.fd); - - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) - this->data_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - this->clock = impl_clock; - reset_props (this, &this->props); - - spa_list_init (&this->ready); - - this->timer_source.func = on_input; - this->timer_source.data = this; - this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); - this->timer_source.mask = SPA_IO_IN; - this->timer_source.rmask = 0; - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - this->timerspec.it_interval.tv_sec = 0; - this->timerspec.it_interval.tv_nsec = 0; - - if (this->data_loop) - spa_loop_add_source (this->data_loop, &this->timer_source); - - this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - - spa_log_info (this->log, NAME " %p: initialized", this); - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, - { SPA_TYPE__Clock, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_fakesink_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_fakesink_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/test/fakesrc.c b/spa/plugins/test/fakesrc.c index f505aa04d..27933049c 100644 --- a/spa/plugins/test/fakesrc.c +++ b/spa/plugins/test/fakesrc.c @@ -36,88 +36,87 @@ #define NAME "fakesrc" struct type { - uint32_t node; - uint32_t clock; - uint32_t format; - uint32_t props; - uint32_t prop_live; - uint32_t prop_pattern; - struct spa_type_meta meta; - struct spa_type_data data; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + uint32_t node; + uint32_t clock; + uint32_t format; + uint32_t props; + uint32_t prop_live; + uint32_t prop_pattern; + struct spa_type_meta meta; + struct spa_type_data data; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->clock = spa_type_map_get_id (map, SPA_TYPE__Clock); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_live = spa_type_map_get_id (map, SPA_TYPE_PROPS__live); - type->prop_pattern = spa_type_map_get_id (map, SPA_TYPE_PROPS__patternType); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->clock = spa_type_map_get_id(map, SPA_TYPE__Clock); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live); + type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); } struct props { - bool live; - uint32_t pattern; + bool live; + uint32_t pattern; }; #define MAX_BUFFERS 16 #define MAX_PORTS 1 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + struct spa_list link; }; struct impl { - struct spa_handle handle; - struct spa_node node; - struct spa_clock clock; + struct spa_handle handle; + struct spa_node node; + struct spa_clock clock; - struct type type; - struct spa_type_map *map; - struct spa_log *log; - struct spa_loop *data_loop; + struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct spa_loop *data_loop; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct spa_source timer_source; - struct itimerspec timerspec; + struct spa_source timer_source; + struct itimerspec timerspec; - struct spa_port_info info; - uint8_t params_buffer[1024]; - struct spa_port_io *io; + struct spa_port_info info; + uint8_t params_buffer[1024]; + struct spa_port_io *io; - bool have_format; - uint8_t format_buffer[1024]; + bool have_format; + uint8_t format_buffer[1024]; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - bool started; - uint64_t start_time; - uint64_t elapsed_time; + bool started; + uint64_t start_time; + uint64_t elapsed_time; - uint64_t buffer_count; - struct spa_list empty; - bool underrun; + uint64_t buffer_count; + struct spa_list empty; + bool underrun; }; #define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS) @@ -126,11 +125,10 @@ struct impl { #define DEFAULT_LIVE false #define DEFAULT_PATTERN 0 -static void -reset_props (struct impl *this, struct props *props) +static void reset_props(struct impl *this, struct props *props) { - props->live = DEFAULT_LIVE; - props->pattern = DEFAULT_PATTERN; + props->live = DEFAULT_LIVE; + props->pattern = DEFAULT_PATTERN; } #define PROP(f,key,type,...) \ @@ -146,804 +144,776 @@ reset_props (struct impl *this, struct props *props) SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, this->props.live), - PROP_EN (&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 1, - this->props.pattern, - this->props.pattern)); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, + this->props.live), + PROP_EN(&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 1, + this->props.pattern, + this->props.pattern)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (props == NULL) { + reset_props(this, &this->props); + } else { + spa_props_query(props, + this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, + this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern, 0); + } + + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + else + this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; + + return SPA_RESULT_OK; +} + +static int fill_buffer(struct impl *this, struct buffer *b) +{ + return SPA_RESULT_OK; +} + +static void set_timer(struct impl *this, bool enabled) +{ + if (this->callbacks.have_output || this->props.live) { + if (enabled) { + if (this->props.live) { + uint64_t next_time = this->start_time + this->elapsed_time; + this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; + this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 1; + } + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + } + timerfd_settime(this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); + } +} + +static inline void read_timer(struct impl *this) +{ + uint64_t expirations; + + if (this->callbacks.have_output || this->props.live) { + if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) < sizeof(uint64_t)) + perror("read timerfd"); + } +} + +static int make_buffer(struct impl *this) +{ + struct buffer *b; + struct spa_port_io *io = this->io; + int n_bytes; + + read_timer(this); + + if (spa_list_is_empty(&this->empty)) { + set_timer(this, false); + this->underrun = true; + spa_log_error(this->log, NAME " %p: out of buffers", this); + return SPA_RESULT_OUT_OF_BUFFERS; + } + b = spa_list_first(&this->empty, struct buffer, link); + spa_list_remove(&b->link); + b->outstanding = true; + + n_bytes = b->outbuf->datas[0].maxsize; + + spa_log_trace(this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); + + fill_buffer(this, b); + + b->outbuf->datas[0].chunk->offset = 0; + b->outbuf->datas[0].chunk->size = n_bytes; + b->outbuf->datas[0].chunk->stride = n_bytes; + + if (b->h) { + b->h->seq = this->buffer_count; + b->h->pts = this->start_time + this->elapsed_time; + b->h->dts_offset = 0; + } + + this->buffer_count++; + this->elapsed_time = this->buffer_count; + set_timer(this, true); + + io->buffer_id = b->outbuf->id; + io->status = SPA_RESULT_HAVE_BUFFER; + + return SPA_RESULT_HAVE_BUFFER; +} + +static void on_output(struct spa_source *source) +{ + struct impl *this = source->data; + int res; + + res = make_buffer(this); + + if (res == SPA_RESULT_HAVE_BUFFER && this->callbacks.have_output) + this->callbacks.have_output(&this->node, this->user_data); +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + struct timespec now; + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (this->started) + return SPA_RESULT_OK; + + clock_gettime(CLOCK_MONOTONIC, &now); + if (this->props.live) + this->start_time = SPA_TIMESPEC_TO_TIME(&now); + else + this->start_time = 0; + this->buffer_count = 0; + this->elapsed_time = 0; + + this->started = true; + set_timer(this, true); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (!this->started) + return SPA_RESULT_OK; + + this->started = false; + set_timer(this, false); + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (props == NULL) { - reset_props (this, &this->props); - } else { - spa_props_query (props, - this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, - this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern, - 0); - } + if (this->data_loop == NULL && callbacks->have_output != NULL) { + spa_log_error(this->log, "a data_loop is needed for async operation"); + return SPA_RESULT_ERROR; + } + this->callbacks = *callbacks; + this->user_data = user_data; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - else - this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -fill_buffer (struct impl *this, struct buffer *b) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - return SPA_RESULT_OK; -} + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); -static void -set_timer (struct impl *this, bool enabled) -{ - if (this->callbacks.have_output || this->props.live) { - if (enabled) { - if (this->props.live) { - uint64_t next_time = this->start_time + this->elapsed_time; - this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; - this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 1; - } - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - } - timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); - } -} + if (n_input_ports) + *n_input_ports = 0; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 0; + if (max_output_ports) + *max_output_ports = 1; -static inline void -read_timer (struct impl *this) -{ - uint64_t expirations; - - if (this->callbacks.have_output || this->props.live) { - if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t)) - perror ("read timerfd"); - } + return SPA_RESULT_OK; } static int -make_buffer (struct impl *this) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct buffer *b; - struct spa_port_io *io = this->io; - int n_bytes; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - read_timer (this); + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - if (spa_list_is_empty (&this->empty)) { - set_timer (this, false); - this->underrun = true; - spa_log_error (this->log, NAME " %p: out of buffers", this); - return SPA_RESULT_OUT_OF_BUFFERS; - } - b = spa_list_first (&this->empty, struct buffer, link); - spa_list_remove (&b->link); - b->outstanding = true; - - n_bytes = b->outbuf->datas[0].maxsize; - - spa_log_trace (this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); - - fill_buffer (this, b); - - b->outbuf->datas[0].chunk->offset = 0; - b->outbuf->datas[0].chunk->size = n_bytes; - b->outbuf->datas[0].chunk->stride = n_bytes; - - if (b->h) { - b->h->seq = this->buffer_count; - b->h->pts = this->start_time + this->elapsed_time; - b->h->dts_offset = 0; - } - - this->buffer_count++; - this->elapsed_time = this->buffer_count; - set_timer (this, true); - - io->buffer_id = b->outbuf->id; - io->status = SPA_RESULT_HAVE_BUFFER; - - return SPA_RESULT_HAVE_BUFFER; + return SPA_RESULT_OK; } -static void -on_output (struct spa_source *source) +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - struct impl *this = source->data; - int res; - - res = make_buffer (this); - - if (res == SPA_RESULT_HAVE_BUFFER && this->callbacks.have_output) - this->callbacks.have_output (&this->node, this->user_data); + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - struct timespec now; - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (this->started) - return SPA_RESULT_OK; - - clock_gettime (CLOCK_MONOTONIC, &now); - if (this->props.live) - this->start_time = SPA_TIMESPEC_TO_TIME (&now); - else - this->start_time = 0; - this->buffer_count = 0; - this->elapsed_time = 0; - - this->started = true; - set_timer (this, true); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (!this->started) - return SPA_RESULT_OK; - - this->started = false; - set_timer (this, false); - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (this->data_loop == NULL && callbacks->have_output != NULL) { - spa_log_error (this->log, "a data_loop is needed for async operation"); - return SPA_RESULT_ERROR; - } - this->callbacks = *callbacks; - this->user_data = user_data; + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - return SPA_RESULT_OK; + return SPA_RESULT_ENUM_END; +} + +static int clear_buffers(struct impl *this) +{ + if (this->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers", this); + this->n_buffers = 0; + spa_list_init(&this->empty); + this->started = false; + set_timer(this, false); + } + return SPA_RESULT_OK; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; - if (n_input_ports) - *n_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 0; - if (max_output_ports) - *max_output_ports = 1; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (format == NULL) { + this->have_format = false; + clear_buffers(this); + } else { + if (SPA_POD_SIZE(format) > sizeof(this->format_buffer)) + return SPA_RESULT_ERROR; + memcpy(this->format_buffer, format, SPA_POD_SIZE(format)); + this->have_format = true; + } + + if (this->have_format) { + } + + return SPA_RESULT_OK; } static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + *format = (const struct spa_format *) this->format_buffer; + + return SPA_RESULT_OK; } static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + *info = &this->info; + + return SPA_RESULT_OK; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct spa_pod_builder b = { NULL }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer)); + + switch (index) { + case 0: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + 128), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + 1), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + 32, + 2, 32), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, + 16)); + break; + + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; + + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - return SPA_RESULT_ENUM_END; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -clear_buffers (struct impl *this) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - if (this->n_buffers > 0) { - spa_log_info (this->log, NAME " %p: clear buffers", this); - this->n_buffers = 0; - spa_list_init (&this->empty); - this->started = false; - set_timer (this, false); - } - return SPA_RESULT_OK; + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + clear_buffers(this); + + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; + + b = &this->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = false; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) { + spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this, + buffers[i]); + } + spa_list_insert(this->empty.prev, &b->link); + } + this->n_buffers = n_buffers; + this->underrun = false; + + return SPA_RESULT_OK; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (format == NULL) { - this->have_format = false; - clear_buffers (this); - } else { - if (SPA_POD_SIZE (format) > sizeof (this->format_buffer)) - return SPA_RESULT_ERROR; - memcpy (this->format_buffer, format, SPA_POD_SIZE (format)); - this->have_format = true; - } + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - if (this->have_format) { - } - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT_NUM(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + this->io = io; - *format = (const struct spa_format *) this->format_buffer; + return SPA_RESULT_OK; +} - return SPA_RESULT_OK; +static inline void reuse_buffer(struct impl *this, uint32_t id) +{ + struct buffer *b = &this->buffers[id]; + spa_return_if_fail(b->outstanding); + + spa_log_trace(this->log, NAME " %p: reuse buffer %d", this, id); + + b->outstanding = false; + spa_list_insert(this->empty.prev, &b->link); + + if (this->underrun) { + set_timer(this, true); + this->underrun = false; + } +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(port_id == 0, SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); + spa_return_val_if_fail(buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); + + reuse_buffer(this, buffer_id); + + return SPA_RESULT_OK; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - *info = &this->info; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +static int impl_node_process_input(struct spa_node *node) { - struct impl *this; - struct spa_pod_builder b = { NULL }; - struct spa_pod_frame f[2]; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - spa_pod_builder_init (&b, this->params_buffer, sizeof (this->params_buffer)); - - switch (index) { - case 0: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, 128), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 1), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; - - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; - - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +static int impl_node_process_output(struct spa_node *node) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct impl *this; + struct spa_port_io *io; -static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) -{ - struct impl *this; - uint32_t i; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + this = SPA_CONTAINER_OF(node, struct impl, node); + io = this->io; + spa_return_val_if_fail(io != NULL, SPA_RESULT_WRONG_STATE); - this = SPA_CONTAINER_OF (node, struct impl, node); + if (io->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + if (io->buffer_id != SPA_ID_INVALID) { + reuse_buffer(this, this->io->buffer_id); + this->io->buffer_id = SPA_ID_INVALID; + } - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - clear_buffers (this); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &this->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = false; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data == NULL) { - spa_log_error (this->log, NAME " %p: invalid memory on buffer %p", this, buffers[i]); - } - spa_list_insert (this->empty.prev, &b->link); - } - this->n_buffers = n_buffers; - this->underrun = false; - - return SPA_RESULT_OK; -} - -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->io = io; - - return SPA_RESULT_OK; -} - -static inline void -reuse_buffer (struct impl *this, uint32_t id) -{ - struct buffer *b = &this->buffers[id]; - spa_return_if_fail (b->outstanding); - - spa_log_trace (this->log, NAME " %p: reuse buffer %d", this, id); - - b->outstanding = false; - spa_list_insert (this->empty.prev, &b->link); - - if (this->underrun) { - set_timer (this, true); - this->underrun = false; - } -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (port_id == 0, SPA_RESULT_INVALID_PORT); - spa_return_val_if_fail (this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); - spa_return_val_if_fail (buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); - - reuse_buffer (this, buffer_id); - - return SPA_RESULT_OK; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_input (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - struct impl *this; - struct spa_port_io *io; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - io = this->io; - spa_return_val_if_fail (io != NULL, SPA_RESULT_WRONG_STATE); - - if (io->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - if (io->buffer_id != SPA_ID_INVALID) { - reuse_buffer (this, this->io->buffer_id); - this->io->buffer_id = SPA_ID_INVALID; - } - - if (this->callbacks.have_output == NULL && (io->status == SPA_RESULT_NEED_BUFFER)) - return make_buffer (this); - else - return SPA_RESULT_OK; + if (this->callbacks.have_output == NULL && (io->status == SPA_RESULT_NEED_BUFFER)) + return make_buffer(this); + else + return SPA_RESULT_OK; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, }; -static int -impl_clock_get_props (struct spa_clock *clock, - struct spa_props **props) +static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_clock_set_props (struct spa_clock *clock, - const struct spa_props *props) +impl_clock_get_time(struct spa_clock *clock, + int32_t *rate, + int64_t *ticks, + int64_t *monotonic_time) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct timespec now; + uint64_t tnow; -static int -impl_clock_get_time (struct spa_clock *clock, - int32_t *rate, - int64_t *ticks, - int64_t *monotonic_time) -{ - struct timespec now; - uint64_t tnow; + spa_return_val_if_fail(clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (rate) + *rate = SPA_NSEC_PER_SEC; - if (rate) - *rate = SPA_NSEC_PER_SEC; + clock_gettime(CLOCK_MONOTONIC, &now); + tnow = SPA_TIMESPEC_TO_TIME(&now); - clock_gettime (CLOCK_MONOTONIC, &now); - tnow = SPA_TIMESPEC_TO_TIME (&now); + if (ticks) + *ticks = tnow; + if (monotonic_time) + *monotonic_time = tnow; - if (ticks) - *ticks = tnow; - if (monotonic_time) - *monotonic_time = tnow; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_clock impl_clock = { - sizeof (struct spa_clock), - NULL, - SPA_CLOCK_STATE_STOPPED, - impl_clock_get_props, - impl_clock_set_props, - impl_clock_get_time, + sizeof(struct spa_clock), + NULL, + SPA_CLOCK_STATE_STOPPED, + impl_clock_get_props, + impl_clock_set_props, + impl_clock_get_time, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.node) + *interface = &this->node; + else if (interface_id == this->type.clock) + *interface = &this->clock; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (this->data_loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + close(this->timer_source.fd); + + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) + this->data_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + this->clock = impl_clock; + reset_props(this, &this->props); + + spa_list_init(&this->empty); + + this->timer_source.func = on_output; + this->timer_source.data = this; + this->timer_source.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + this->timerspec.it_interval.tv_sec = 0; + this->timerspec.it_interval.tv_nsec = 0; + + if (this->data_loop) + spa_loop_add_source(this->data_loop, &this->timer_source); + + this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + + spa_log_info(this->log, NAME " %p: initialized", this); + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, + {SPA_TYPE__Clock,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else if (interface_id == this->type.clock) - *interface = &this->clock; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - struct impl *this; - - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (this->data_loop) - spa_loop_remove_source (this->data_loop, &this->timer_source); - close (this->timer_source.fd); - - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) - this->data_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - this->clock = impl_clock; - reset_props (this, &this->props); - - spa_list_init (&this->empty); - - this->timer_source.func = on_output; - this->timer_source.data = this; - this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); - this->timer_source.mask = SPA_IO_IN; - this->timer_source.rmask = 0; - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - this->timerspec.it_interval.tv_sec = 0; - this->timerspec.it_interval.tv_nsec = 0; - - if (this->data_loop) - spa_loop_add_source (this->data_loop, &this->timer_source); - - this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - - spa_log_info (this->log, NAME " %p: initialized", this); - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, - { SPA_TYPE__Clock, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_fakesrc_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_fakesrc_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/test/plugin.c b/spa/plugins/test/plugin.c index 4106b78fb..d993d4cfa 100644 --- a/spa/plugins/test/plugin.c +++ b/spa/plugins/test/plugin.c @@ -24,11 +24,9 @@ extern const struct spa_handle_factory spa_fakesrc_factory; extern const struct spa_handle_factory spa_fakesink_factory; int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) +spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); switch (index) { case 0: diff --git a/spa/plugins/v4l2/v4l2-monitor.c b/spa/plugins/v4l2/v4l2-monitor.c index 8cbbfda68..08d102b68 100644 --- a/spa/plugins/v4l2/v4l2-monitor.c +++ b/spa/plugins/v4l2/v4l2-monitor.c @@ -36,390 +36,386 @@ extern const struct spa_handle_factory spa_v4l2_source_factory; struct item { - struct spa_monitor_item *item; - struct udev_device *udevice; + struct spa_monitor_item *item; + struct udev_device *udevice; }; struct type { - uint32_t handle_factory; - struct spa_type_monitor monitor; + uint32_t handle_factory; + struct spa_type_monitor monitor; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->handle_factory = spa_type_map_get_id (map, SPA_TYPE__HandleFactory); - spa_type_monitor_map (map, &type->monitor); + type->handle_factory = spa_type_map_get_id(map, SPA_TYPE__HandleFactory); + spa_type_monitor_map(map, &type->monitor); } struct impl { - struct spa_handle handle; - struct spa_monitor monitor; + struct spa_handle handle; + struct spa_monitor monitor; - struct type type; - struct spa_type_map *map; - struct spa_log *log; - struct spa_loop *main_loop; + struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct spa_loop *main_loop; - struct spa_monitor_callbacks callbacks; - void *user_data; + struct spa_monitor_callbacks callbacks; + void *user_data; - struct udev* udev; - struct udev_monitor *umonitor; - struct udev_enumerate *enumerate; - uint32_t index; - struct udev_list_entry *devices; - uint8_t item_buffer[4096]; + struct udev *udev; + struct udev_monitor *umonitor; + struct udev_enumerate *enumerate; + uint32_t index; + struct udev_list_entry *devices; + uint8_t item_buffer[4096]; - struct item uitem; + struct item uitem; - struct spa_source source; + struct spa_source source; }; -static int -impl_udev_open (struct impl *this) +static int impl_udev_open(struct impl *this) { - if (this->udev != NULL) - return SPA_RESULT_OK; + if (this->udev != NULL) + return SPA_RESULT_OK; - this->udev = udev_new (); + this->udev = udev_new(); - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static void -fill_item (struct impl *this, struct item *item, struct udev_device *udevice) +static void fill_item(struct impl *this, struct item *item, struct udev_device *udevice) { - const char *str, *name; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[3]; + const char *str, *name; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[3]; - if (item->udevice) - udev_device_unref (item->udevice); - item->udevice = udevice; - if (udevice == NULL) - return; + if (item->udevice) + udev_device_unref(item->udevice); + item->udevice = udevice; + if (udevice == NULL) + return; - name = udev_device_get_property_value (item->udevice, "ID_V4L_PRODUCT"); - if (!(name && *name)) { - name = udev_device_get_property_value (item->udevice, "ID_MODEL_FROM_DATABASE"); - if (!(name && *name)) { - name = udev_device_get_property_value (item->udevice, "ID_MODEL_ENC"); - if (!(name && *name)) { - name = udev_device_get_property_value (item->udevice, "ID_MODEL"); - } - } - } - if (!(name && *name)) - name = "Unknown"; + name = udev_device_get_property_value(item->udevice, "ID_V4L_PRODUCT"); + if (!(name && *name)) { + name = udev_device_get_property_value(item->udevice, "ID_MODEL_FROM_DATABASE"); + if (!(name && *name)) { + name = udev_device_get_property_value(item->udevice, "ID_MODEL_ENC"); + if (!(name && *name)) { + name = udev_device_get_property_value(item->udevice, "ID_MODEL"); + } + } + } + if (!(name && *name)) + name = "Unknown"; - spa_pod_builder_init (&b, this->item_buffer, sizeof (this->item_buffer)); + spa_pod_builder_init(&b, this->item_buffer, sizeof(this->item_buffer)); - spa_pod_builder_push_object (&b, &f[0], 0, this->type.monitor.MonitorItem); + spa_pod_builder_push_object(&b, &f[0], 0, this->type.monitor.MonitorItem); - spa_pod_builder_add (&b, - SPA_POD_PROP (&f[1], this->type.monitor.id, 0, SPA_POD_TYPE_STRING, 1, udev_device_get_syspath (item->udevice)), - SPA_POD_PROP (&f[1], this->type.monitor.flags, 0, SPA_POD_TYPE_INT, 1, 0), - SPA_POD_PROP (&f[1], this->type.monitor.state, 0, SPA_POD_TYPE_INT, 1, SPA_MONITOR_ITEM_STATE_AVAILABLE), - SPA_POD_PROP (&f[1], this->type.monitor.name, 0, SPA_POD_TYPE_STRING, 1, name), - SPA_POD_PROP (&f[1], this->type.monitor.klass, 0, SPA_POD_TYPE_STRING, 1, "Video/Source"), - SPA_POD_PROP (&f[1], this->type.monitor.factory, 0, SPA_POD_TYPE_POINTER, 1, this->type.handle_factory, - &spa_v4l2_source_factory), - 0); - - spa_pod_builder_add (&b, - SPA_POD_TYPE_PROP, &f[1], this->type.monitor.info, 0, - SPA_POD_TYPE_STRUCT, 1, &f[2], 0); + spa_pod_builder_add(&b, + SPA_POD_PROP(&f[1], this->type.monitor.id, 0, SPA_POD_TYPE_STRING, 1, + udev_device_get_syspath(item->udevice)), + SPA_POD_PROP(&f[1], this->type.monitor.flags, 0, SPA_POD_TYPE_INT, 1, + 0), + SPA_POD_PROP(&f[1], this->type.monitor.state, 0, SPA_POD_TYPE_INT, 1, + SPA_MONITOR_ITEM_STATE_AVAILABLE), + SPA_POD_PROP(&f[1], this->type.monitor.name, 0, SPA_POD_TYPE_STRING, 1, + name), + SPA_POD_PROP(&f[1], this->type.monitor.klass, 0, SPA_POD_TYPE_STRING, 1, + "Video/Source"), + SPA_POD_PROP(&f[1], this->type.monitor.factory, 0, SPA_POD_TYPE_POINTER, 1, + this->type.handle_factory, &spa_v4l2_source_factory), + 0); + spa_pod_builder_add(&b, + SPA_POD_TYPE_PROP, &f[1], this->type.monitor.info, 0, + SPA_POD_TYPE_STRUCT, 1, &f[2], 0); - spa_pod_builder_add (&b, - SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1", - SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "v4l2", - SPA_POD_TYPE_STRING, "device.path", SPA_POD_TYPE_STRING, udev_device_get_devnode (item->udevice), - 0); + spa_pod_builder_add(&b, + SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1", + SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "v4l2", + SPA_POD_TYPE_STRING, "device.path", SPA_POD_TYPE_STRING, + udev_device_get_devnode(item->udevice), 0); - str = udev_device_get_property_value (item->udevice, "ID_PATH"); - if (!(str && *str)) - str = udev_device_get_syspath (item->udevice); - if (str && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_syspath (item->udevice)) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "ID_ID")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "ID_BUS")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "SUBSYSTEM")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.subsystem", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "ID_VENDOR_ID")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.id", SPA_POD_TYPE_STRING, str, 0); - } - str = udev_device_get_property_value (item->udevice, "ID_VENDOR_FROM_DATABASE"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_VENDOR_ENC"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_VENDOR"); - } - } - if (str && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.name", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "ID_MODEL_ID")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.id", SPA_POD_TYPE_STRING, str, 0); - } - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING, name, 0); - if ((str = udev_device_get_property_value (item->udevice, "ID_SERIAL")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING, str, 0); - } - if ((str = udev_device_get_property_value (item->udevice, "ID_V4L_CAPABILITIES")) && *str) { - spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.capabilities", SPA_POD_TYPE_STRING, str, 0); - } + str = udev_device_get_property_value(item->udevice, "ID_PATH"); + if (!(str && *str)) + str = udev_device_get_syspath(item->udevice); + if (str && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING, + str, 0); + } + if ((str = udev_device_get_syspath(item->udevice)) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING, + str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "ID_ID")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING, + str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "ID_BUS")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING, + str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "SUBSYSTEM")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.subsystem", + SPA_POD_TYPE_STRING, str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "ID_VENDOR_ID")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.id", + SPA_POD_TYPE_STRING, str, 0); + } + str = udev_device_get_property_value(item->udevice, "ID_VENDOR_FROM_DATABASE"); + if (!(str && *str)) { + str = udev_device_get_property_value(item->udevice, "ID_VENDOR_ENC"); + if (!(str && *str)) { + str = udev_device_get_property_value(item->udevice, "ID_VENDOR"); + } + } + if (str && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.name", + SPA_POD_TYPE_STRING, str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "ID_MODEL_ID")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.id", + SPA_POD_TYPE_STRING, str, 0); + } + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING, + name, 0); + if ((str = udev_device_get_property_value(item->udevice, "ID_SERIAL")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING, + str, 0); + } + if ((str = udev_device_get_property_value(item->udevice, "ID_V4L_CAPABILITIES")) && *str) { + spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.capabilities", + SPA_POD_TYPE_STRING, str, 0); + } - spa_pod_builder_add (&b, - -SPA_POD_TYPE_STRUCT, &f[2], - -SPA_POD_TYPE_PROP, &f[1], - 0); + spa_pod_builder_add(&b, -SPA_POD_TYPE_STRUCT, &f[2], -SPA_POD_TYPE_PROP, &f[1], 0); - spa_pod_builder_pop (&b, &f[0]); + spa_pod_builder_pop(&b, &f[0]); - item->item = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_monitor_item); + item->item = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_monitor_item); } -static void -impl_on_fd_events (struct spa_source *source) +static void impl_on_fd_events(struct spa_source *source) { - struct impl *this = source->data; - struct udev_device *dev; - struct spa_event *event; - const char *action; - uint32_t type; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[1]; - uint8_t buffer[4096]; + struct impl *this = source->data; + struct udev_device *dev; + struct spa_event *event; + const char *action; + uint32_t type; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[1]; + uint8_t buffer[4096]; - dev = udev_monitor_receive_device (this->umonitor); - fill_item (this, &this->uitem, dev); - if (dev == NULL) - return; + dev = udev_monitor_receive_device(this->umonitor); + fill_item(this, &this->uitem, dev); + if (dev == NULL) + return; - if ((action = udev_device_get_action (dev)) == NULL) - action = "change"; + if ((action = udev_device_get_action(dev)) == NULL) + action = "change"; - if (strcmp (action, "add") == 0) { - type = this->type.monitor.Added; - } else if (strcmp (action, "change") == 0) { - type = this->type.monitor.Changed; - } else if (strcmp (action, "remove") == 0) { - type = this->type.monitor.Removed; - } else - return; + if (strcmp(action, "add") == 0) { + type = this->type.monitor.Added; + } else if (strcmp(action, "change") == 0) { + type = this->type.monitor.Changed; + } else if (strcmp(action, "remove") == 0) { + type = this->type.monitor.Removed; + } else + return; - spa_pod_builder_init (&b, buffer, sizeof (buffer)); - spa_pod_builder_object (&b, &f[0], 0, type, - SPA_POD_TYPE_POD, this->uitem.item); + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_object(&b, &f[0], 0, type, SPA_POD_TYPE_POD, this->uitem.item); - event = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_event); - this->callbacks.event (&this->monitor, event, this->user_data); + event = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_event); + this->callbacks.event(&this->monitor, event, this->user_data); } static int -impl_monitor_set_callbacks (struct spa_monitor *monitor, - const struct spa_monitor_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_monitor_set_callbacks(struct spa_monitor *monitor, + const struct spa_monitor_callbacks *callbacks, + size_t callbacks_size, void *user_data) { - int res; - struct impl *this; + int res; + struct impl *this; - spa_return_val_if_fail (monitor != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(monitor != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (monitor, struct impl, monitor); + this = SPA_CONTAINER_OF(monitor, struct impl, monitor); - if (callbacks) { - this->callbacks = *callbacks; - this->user_data = user_data; + if (callbacks) { + this->callbacks = *callbacks; + this->user_data = user_data; - if ((res = impl_udev_open (this)) < 0) - return res; + if ((res = impl_udev_open(this)) < 0) + return res; - this->umonitor = udev_monitor_new_from_netlink (this->udev, "udev"); - if (!this->umonitor) - return SPA_RESULT_ERROR; + this->umonitor = udev_monitor_new_from_netlink(this->udev, "udev"); + if (!this->umonitor) + return SPA_RESULT_ERROR; - udev_monitor_filter_add_match_subsystem_devtype (this->umonitor, - "video4linux", - NULL); + udev_monitor_filter_add_match_subsystem_devtype(this->umonitor, + "video4linux", NULL); - udev_monitor_enable_receiving (this->umonitor); - this->source.func = impl_on_fd_events; - this->source.data = this; - this->source.fd = udev_monitor_get_fd (this->umonitor);; - this->source.mask = SPA_IO_IN | SPA_IO_ERR; + udev_monitor_enable_receiving(this->umonitor); + this->source.func = impl_on_fd_events; + this->source.data = this; + this->source.fd = udev_monitor_get_fd(this->umonitor);; + this->source.mask = SPA_IO_IN | SPA_IO_ERR; - spa_loop_add_source (this->main_loop, &this->source); - } else { - spa_zero (this->callbacks); - spa_loop_remove_source (this->main_loop, &this->source); - } + spa_loop_add_source(this->main_loop, &this->source); + } else { + spa_zero(this->callbacks); + spa_loop_remove_source(this->main_loop, &this->source); + } - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_monitor_enum_items (struct spa_monitor *monitor, - struct spa_monitor_item **item, - uint32_t index) +impl_monitor_enum_items(struct spa_monitor *monitor, struct spa_monitor_item **item, uint32_t index) { - int res; - struct impl *this; - struct udev_device *dev; + int res; + struct impl *this; + struct udev_device *dev; - spa_return_val_if_fail (monitor != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (item != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(monitor != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(item != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (monitor, struct impl, monitor); + this = SPA_CONTAINER_OF(monitor, struct impl, monitor); - if ((res = impl_udev_open (this)) < 0) - return res; + if ((res = impl_udev_open(this)) < 0) + return res; - if (index == 0) { - if (this->enumerate) - udev_enumerate_unref (this->enumerate); - this->enumerate = udev_enumerate_new (this->udev); + if (index == 0) { + if (this->enumerate) + udev_enumerate_unref(this->enumerate); + this->enumerate = udev_enumerate_new(this->udev); - udev_enumerate_add_match_subsystem (this->enumerate, "video4linux"); - udev_enumerate_scan_devices (this->enumerate); + udev_enumerate_add_match_subsystem(this->enumerate, "video4linux"); + udev_enumerate_scan_devices(this->enumerate); - this->devices = udev_enumerate_get_list_entry (this->enumerate); - this->index = 0; - } - while (index > this->index && this->devices) { - this->devices = udev_list_entry_get_next (this->devices); - this->index++; - } - if (this->devices == NULL) { - fill_item (this, &this->uitem, NULL); - return SPA_RESULT_ENUM_END; - } + this->devices = udev_enumerate_get_list_entry(this->enumerate); + this->index = 0; + } + while (index > this->index && this->devices) { + this->devices = udev_list_entry_get_next(this->devices); + this->index++; + } + if (this->devices == NULL) { + fill_item(this, &this->uitem, NULL); + return SPA_RESULT_ENUM_END; + } - dev = udev_device_new_from_syspath (this->udev, - udev_list_entry_get_name (this->devices)); + dev = udev_device_new_from_syspath(this->udev, udev_list_entry_get_name(this->devices)); - fill_item (this, &this->uitem, dev); - if (dev == NULL) - return SPA_RESULT_ENUM_END; + fill_item(this, &this->uitem, dev); + if (dev == NULL) + return SPA_RESULT_ENUM_END; - *item = this->uitem.item; + *item = this->uitem.item; - this->devices = udev_list_entry_get_next (this->devices); - this->index++; + this->devices = udev_list_entry_get_next(this->devices); + this->index++; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_monitor impl_monitor = { - NULL, - sizeof (struct spa_monitor), - impl_monitor_set_callbacks, - impl_monitor_enum_items, + NULL, + sizeof(struct spa_monitor), + impl_monitor_set_callbacks, + impl_monitor_enum_items, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.monitor.Monitor) + *interface = &this->monitor; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear, this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__MainLoop) == 0) + this->main_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + if (this->main_loop == NULL) { + spa_log_error(this->log, "a main-loop is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->monitor = impl_monitor; + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Monitor,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (index < 0 || index >= SPA_N_ELEMENTS(impl_interfaces)) + return SPA_RESULT_ENUM_END; - this = (struct impl *) handle; + *info = &impl_interfaces[index]; - if (interface_id == this->type.monitor.Monitor) - *interface = &this->monitor; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear, - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__MainLoop) == 0) - this->main_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - if (this->main_loop == NULL) { - spa_log_error (this->log, "a main-loop is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->monitor = impl_monitor; - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Monitor, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (index < 0 || index >= SPA_N_ELEMENTS (impl_interfaces)) - return SPA_RESULT_ENUM_END; - - *info = &impl_interfaces[index]; - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_v4l2_monitor_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_v4l2_monitor_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 825c49c01..1cedc897c 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -41,128 +41,126 @@ static const char default_device[] = "/dev/video0"; struct props { - char device[64]; - char device_name[128]; - int device_fd; + char device[64]; + char device_name[128]; + int device_fd; }; -static void -reset_props (struct props *props) +static void reset_props(struct props *props) { - strncpy (props->device, default_device, 64); + strncpy(props->device, default_device, 64); } #define MAX_BUFFERS 64 struct buffer { - struct spa_buffer *outbuf; - struct spa_meta_header *h; - bool outstanding; - bool allocated; - struct v4l2_buffer v4l2_buffer; + struct spa_buffer *outbuf; + struct spa_meta_header *h; + bool outstanding; + bool allocated; + struct v4l2_buffer v4l2_buffer; }; struct type { - uint32_t node; - uint32_t clock; - uint32_t format; - uint32_t props; - uint32_t prop_device; - uint32_t prop_device_name; - uint32_t prop_device_fd; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_media_subtype_video media_subtype_video; - struct spa_type_format_video format_video; - struct spa_type_video_format video_format; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; - struct spa_type_meta meta; - struct spa_type_data data; + uint32_t node; + uint32_t clock; + uint32_t format; + uint32_t props; + uint32_t prop_device; + uint32_t prop_device_name; + uint32_t prop_device_fd; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_media_subtype_video media_subtype_video; + struct spa_type_format_video format_video; + struct spa_type_video_format video_format; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + struct spa_type_meta meta; + struct spa_type_data data; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->clock = spa_type_map_get_id (map, SPA_TYPE__Clock); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_device = spa_type_map_get_id (map, SPA_TYPE_PROPS__device); - type->prop_device_name = spa_type_map_get_id (map, SPA_TYPE_PROPS__deviceName); - type->prop_device_fd = spa_type_map_get_id (map, SPA_TYPE_PROPS__deviceFd); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_media_subtype_video_map (map, &type->media_subtype_video); - spa_type_format_video_map (map, &type->format_video); - spa_type_video_format_map (map, &type->video_format); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->clock = spa_type_map_get_id(map, SPA_TYPE__Clock); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_device = spa_type_map_get_id(map, SPA_TYPE_PROPS__device); + type->prop_device_name = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceName); + type->prop_device_fd = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceFd); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_media_subtype_video_map(map, &type->media_subtype_video); + spa_type_format_video_map(map, &type->format_video); + spa_type_video_format_map(map, &type->video_format); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); } struct port { - struct spa_log *log; - struct spa_loop *main_loop; - struct spa_loop *data_loop; + struct spa_log *log; + struct spa_loop *main_loop; + struct spa_loop *data_loop; - bool export_buf; - bool started; + bool export_buf; + bool started; - bool next_fmtdesc; - struct v4l2_fmtdesc fmtdesc; - bool next_frmsize; - struct v4l2_frmsizeenum frmsize; - struct v4l2_frmivalenum frmival; + bool next_fmtdesc; + struct v4l2_fmtdesc fmtdesc; + bool next_frmsize; + struct v4l2_frmsizeenum frmsize; + struct v4l2_frmivalenum frmival; - bool have_format; - struct spa_video_info current_format; - uint8_t format_buffer[1024]; + bool have_format; + struct spa_video_info current_format; + uint8_t format_buffer[1024]; - int fd; - bool opened; - struct v4l2_capability cap; - struct v4l2_format fmt; - enum v4l2_buf_type type; - enum v4l2_memory memtype; + int fd; + bool opened; + struct v4l2_capability cap; + struct v4l2_format fmt; + enum v4l2_buf_type type; + enum v4l2_memory memtype; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - bool source_enabled; - struct spa_source source; + bool source_enabled; + struct spa_source source; - struct spa_port_info info; - uint8_t params_buffer[1024]; - struct spa_port_io *io; + struct spa_port_info info; + uint8_t params_buffer[1024]; + struct spa_port_io *io; - int64_t last_ticks; - int64_t last_monotonic; + int64_t last_ticks; + int64_t last_monotonic; }; struct impl { - struct spa_handle handle; - struct spa_node node; - struct spa_clock clock; + struct spa_handle handle; + struct spa_node node; + struct spa_clock clock; - struct spa_type_map *map; - struct spa_log *log; - struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct type type; - uint32_t seq; + uint32_t seq; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct port out_ports[1]; + struct port out_ports[1]; }; #define CHECK_PORT(this,direction,port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0) @@ -184,861 +182,820 @@ struct impl { SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) #include "v4l2-utils.c" -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device)), - PROP_R (&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING, this->props.device_name, sizeof (this->props.device_name)), - PROP_R (&f[1], this->type.prop_device_fd, SPA_POD_TYPE_INT, this->props.device_fd)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP(&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING, + this->props.device, sizeof(this->props.device)), + PROP_R(&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING, + this->props.device_name, sizeof(this->props.device_name)), + PROP_R(&f[1], this->type.prop_device_fd, SPA_POD_TYPE_INT, + this->props.device_fd)); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (props == NULL) { + reset_props(&this->props); + return SPA_RESULT_OK; + } else { + spa_props_query(props, this->type.prop_device, -SPA_POD_TYPE_STRING, + this->props.device, sizeof(this->props.device), 0); + } + return SPA_RESULT_OK; +} + +static int do_pause_done(struct spa_loop *loop, + bool async, + uint32_t seq, + size_t size, + void *data, + void *user_data) +{ + struct impl *this = user_data; + struct spa_event_node_async_complete *ac = data; + + if (SPA_RESULT_IS_OK(ac->body.res.value)) + ac->body.res.value = spa_v4l2_stream_off(this); + + this->callbacks.event(&this->node, (struct spa_event *) ac, this->user_data); + + return SPA_RESULT_OK; +} + +static int do_pause(struct spa_loop *loop, + bool async, + uint32_t seq, + size_t size, + void *data, + void *user_data) +{ + struct impl *this = user_data; + int res; + struct spa_command *cmd = data; + + res = spa_node_port_send_command(&this->node, SPA_DIRECTION_OUTPUT, 0, cmd); + + if (async) { + spa_loop_invoke(this->out_ports[0].main_loop, + do_pause_done, + seq, + sizeof(struct spa_event_node_async_complete), + &SPA_EVENT_NODE_ASYNC_COMPLETE_INIT(this->type.event_node.AsyncComplete, + seq, res), + this); + } + return res; +} + +static int do_start_done(struct spa_loop *loop, + bool async, + uint32_t seq, + size_t size, + void *data, + void *user_data) +{ + struct impl *this = user_data; + struct spa_event_node_async_complete *ac = data; + + this->callbacks.event(&this->node, (struct spa_event *) ac, this->user_data); + + return SPA_RESULT_OK; +} + +static int do_start(struct spa_loop *loop, + bool async, + uint32_t seq, + size_t size, + void *data, + void *user_data) +{ + struct impl *this = user_data; + int res; + struct spa_command *cmd = data; + + res = spa_node_port_send_command(&this->node, SPA_DIRECTION_OUTPUT, 0, cmd); + + if (async) { + spa_loop_invoke(this->out_ports[0].main_loop, + do_start_done, + seq, + sizeof(struct spa_event_node_async_complete), + &SPA_EVENT_NODE_ASYNC_COMPLETE_INIT(this->type.event_node.AsyncComplete, + seq, res), + this); + } + return SPA_RESULT_OK; +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + struct port *state = &this->out_ports[0]; + int res; + + if (!state->have_format) + return SPA_RESULT_NO_FORMAT; + + if (state->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if ((res = spa_v4l2_stream_on(this)) < 0) + return res; + + return spa_loop_invoke(this->out_ports[0].data_loop, + do_start, + ++this->seq, + SPA_POD_SIZE(command), + command, + this); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + struct port *state = &this->out_ports[0]; + + if (!state->have_format) + return SPA_RESULT_NO_FORMAT; + + if (state->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + return spa_loop_invoke(this->out_ports[0].data_loop, + do_pause, + ++this->seq, + SPA_POD_SIZE(command), + command, + this); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.ClockUpdate) { + return SPA_RESULT_OK; + } else + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + this->callbacks = *callbacks; + this->user_data = user_data; + + return SPA_RESULT_OK; } static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports) + *n_input_ports = 0; + if (max_input_ports) + *max_input_ports = 0; + if (n_output_ports) + *n_output_ports = 1; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (props == NULL) { - reset_props (&this->props); - return SPA_RESULT_OK; - } else { - spa_props_query (props, - this->type.prop_device, -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device), - 0); - } - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -do_pause_done (struct spa_loop *loop, - bool async, - uint32_t seq, - size_t size, - void *data, - void *user_data) +static int impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this = user_data; - struct spa_event_node_async_complete *ac = data; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - if (SPA_RESULT_IS_OK (ac->body.res.value)) - ac->body.res.value = spa_v4l2_stream_off (this); + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this->callbacks.event (&this->node, (struct spa_event *)ac, this->user_data); - - return SPA_RESULT_OK; -} - -static int -do_pause (struct spa_loop *loop, - bool async, - uint32_t seq, - size_t size, - void *data, - void *user_data) -{ - struct impl *this = user_data; - int res; - struct spa_command *cmd = data; - - res = spa_node_port_send_command (&this->node, - SPA_DIRECTION_OUTPUT, - 0, - cmd); - - if (async) { - spa_loop_invoke (this->out_ports[0].main_loop, - do_pause_done, - seq, - sizeof (struct spa_event_node_async_complete), - &SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete, - seq, res), - this); - } - return res; -} - -static int -do_start_done (struct spa_loop *loop, - bool async, - uint32_t seq, - size_t size, - void *data, - void *user_data) -{ - struct impl *this = user_data; - struct spa_event_node_async_complete *ac = data; - - this->callbacks.event (&this->node, (struct spa_event *)ac, this->user_data); - - return SPA_RESULT_OK; -} - -static int -do_start (struct spa_loop *loop, - bool async, - uint32_t seq, - size_t size, - void *data, - void *user_data) -{ - struct impl *this = user_data; - int res; - struct spa_command *cmd = data; - - res = spa_node_port_send_command (&this->node, - SPA_DIRECTION_OUTPUT, - 0, - cmd); - - if (async) { - spa_loop_invoke (this->out_ports[0].main_loop, - do_start_done, - seq, - sizeof (struct spa_event_node_async_complete), - &SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete, - seq, res), - this); - } - - return SPA_RESULT_OK; -} - -static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - struct port *state = &this->out_ports[0]; - int res; - - if (!state->have_format) - return SPA_RESULT_NO_FORMAT; - - if (state->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if ((res = spa_v4l2_stream_on (this)) < 0) - return res; - - return spa_loop_invoke (this->out_ports[0].data_loop, - do_start, - ++this->seq, - SPA_POD_SIZE (command), - command, - this); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - struct port *state = &this->out_ports[0]; - - if (!state->have_format) - return SPA_RESULT_NO_FORMAT; - - if (state->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - return spa_loop_invoke (this->out_ports[0].data_loop, - do_pause, - ++this->seq, - SPA_POD_SIZE (command), - command, - this); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.ClockUpdate) { - return SPA_RESULT_OK; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (n_input_ports) - *n_input_ports = 0; - if (max_input_ports) - *max_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +static int impl_node_add_port(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_node_remove_port(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + int res; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + res = spa_v4l2_enum_format(this, format, filter, index); + + return res; +} + +static int impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) +{ + struct impl *this; + struct port *state; + struct spa_video_info info; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + state = &this->out_ports[port_id]; + + if (format == NULL) { + spa_v4l2_stream_off(this); + spa_v4l2_clear_buffers(this); + spa_v4l2_close(this); + state->have_format = false; + return SPA_RESULT_OK; + } else { + info.media_type = SPA_FORMAT_MEDIA_TYPE(format); + info.media_subtype = SPA_FORMAT_MEDIA_SUBTYPE(format); + + if (info.media_type != this->type.media_type.video) { + spa_log_error(this->log, "media type must be video"); + return SPA_RESULT_INVALID_MEDIA_TYPE; + } + + if (info.media_subtype == this->type.media_subtype.raw) { + if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video)) { + spa_log_error(this->log, "can't parse video raw"); + return SPA_RESULT_INVALID_MEDIA_TYPE; + } + + if (state->have_format && info.media_type == state->current_format.media_type && + info.media_subtype == state->current_format.media_subtype && + info.info.raw.format == state->current_format.info.raw.format && + info.info.raw.size.width == state->current_format.info.raw.size.width && + info.info.raw.size.height == state->current_format.info.raw.size.height) + return SPA_RESULT_OK; + } else if (info.media_subtype == this->type.media_subtype_video.mjpg) { + if (!spa_format_video_mjpg_parse(format, &info.info.mjpg, &this->type.format_video)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (state->have_format && info.media_type == state->current_format.media_type && + info.media_subtype == state->current_format.media_subtype && + info.info.mjpg.size.width == state->current_format.info.mjpg.size.width && + info.info.mjpg.size.height == state->current_format.info.mjpg.size.height) + return SPA_RESULT_OK; + } else if (info.media_subtype == this->type.media_subtype_video.h264) { + if (!spa_format_video_h264_parse(format, &info.info.h264, &this->type.format_video)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (state->have_format && info.media_type == state->current_format.media_type && + info.media_subtype == state->current_format.media_subtype && + info.info.h264.size.width == state->current_format.info.h264.size.width && + info.info.h264.size.height == state->current_format.info.h264.size.height) + return SPA_RESULT_OK; + } + } + + if (state->have_format && !(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { + spa_v4l2_use_buffers(this, NULL, 0); + state->have_format = false; + } + + if (spa_v4l2_set_format(this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { + state->current_format = info; + state->have_format = true; + } + + return SPA_RESULT_OK; +} + +static int impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) +{ + struct impl *this; + struct port *state; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + state = &this->out_ports[port_id]; + + if (!state->have_format) + return SPA_RESULT_NO_FORMAT; + + b.data = state->format_buffer; + b.size = sizeof(state->format_buffer); + + spa_pod_builder_push_format(&b, &f[0], this->type.format, + state->current_format.media_type, + state->current_format.media_subtype); + + if (state->current_format.media_subtype == this->type.media_subtype.raw) { + spa_pod_builder_add(&b, + PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, + state->current_format.info.raw.format), + PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, + &state->current_format.info.raw.size), + PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, + &state->current_format.info.raw.framerate), 0); + } else if (state->current_format.media_subtype == this->type.media_subtype_video.mjpg || + state->current_format.media_subtype == this->type.media_subtype_video.jpeg) { + spa_pod_builder_add(&b, + PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, + &state->current_format.info.mjpg.size), + PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, + &state->current_format.info.mjpg.framerate), 0); + } else if (state->current_format.media_subtype == this->type.media_subtype_video.h264) { + spa_pod_builder_add(&b, + PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, + &state->current_format.info.h264.size), + PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, + &state->current_format.info.h264.framerate), 0); + } else + return SPA_RESULT_NO_FORMAT; + + spa_pod_builder_pop(&b, &f[0]); + + *format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + + return SPA_RESULT_OK; +} + +static int impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + *info = &this->out_ports[port_id].info; + + return SPA_RESULT_OK; +} + +static int impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) +{ + + struct impl *this; + struct port *state; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + state = &this->out_ports[port_id]; + + spa_pod_builder_init(&b, state->params_buffer, sizeof(state->params_buffer)); + + switch (index) { + case 0: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + state->fmt.fmt.pix.sizeimage), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + state->fmt.fmt.pix.bytesperline), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + MAX_BUFFERS, 2, MAX_BUFFERS), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); + break; + + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; + + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } + + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; +} + +static int impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) +{ + struct impl *this; + struct port *state; + int res; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + state = &this->out_ports[port_id]; + + if (!state->have_format) + return SPA_RESULT_NO_FORMAT; + + if (state->n_buffers) { + spa_v4l2_stream_off(this); + if ((res = spa_v4l2_clear_buffers(this)) < 0) + return res; + } + if (buffers != NULL) { + if ((res = spa_v4l2_use_buffers(this, buffers, n_buffers)) < 0) + return res; + } + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t *n_buffers) { - struct impl *this; - int res; + struct impl *this; + struct port *state; + int res; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(buffers != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - res = spa_v4l2_enum_format (this, format, filter, index); + state = &this->out_ports[port_id]; - return res; + if (!state->have_format) + return SPA_RESULT_NO_FORMAT; + + res = spa_v4l2_alloc_buffers(this, params, n_params, buffers, n_buffers); + + return res; } -static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +static int impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; - struct port *state; - struct spa_video_info info; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - state = &this->out_ports[port_id]; + this->out_ports[port_id].io = io; - if (format == NULL) { - spa_v4l2_stream_off (this); - spa_v4l2_clear_buffers (this); - spa_v4l2_close (this); - state->have_format = false; - return SPA_RESULT_OK; - } else { - info.media_type = SPA_FORMAT_MEDIA_TYPE (format); - info.media_subtype = SPA_FORMAT_MEDIA_SUBTYPE (format); - - if (info.media_type != this->type.media_type.video) { - spa_log_error (this->log, "media type must be video"); - return SPA_RESULT_INVALID_MEDIA_TYPE; - } - - if (info.media_subtype == this->type.media_subtype.raw) { - if (!spa_format_video_raw_parse (format, &info.info.raw, &this->type.format_video)) { - spa_log_error (this->log, "can't parse video raw"); - return SPA_RESULT_INVALID_MEDIA_TYPE; - } - - if (state->have_format && info.media_type == state->current_format.media_type && - info.media_subtype == state->current_format.media_subtype && - info.info.raw.format == state->current_format.info.raw.format && - info.info.raw.size.width == state->current_format.info.raw.size.width && - info.info.raw.size.height == state->current_format.info.raw.size.height) - return SPA_RESULT_OK; - } - else if (info.media_subtype == this->type.media_subtype_video.mjpg) { - if (!spa_format_video_mjpg_parse (format, &info.info.mjpg, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (state->have_format && info.media_type == state->current_format.media_type && - info.media_subtype == state->current_format.media_subtype && - info.info.mjpg.size.width == state->current_format.info.mjpg.size.width && - info.info.mjpg.size.height == state->current_format.info.mjpg.size.height) - return SPA_RESULT_OK; - } - else if (info.media_subtype == this->type.media_subtype_video.h264) { - if (!spa_format_video_h264_parse (format, &info.info.h264, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (state->have_format && info.media_type == state->current_format.media_type && - info.media_subtype == state->current_format.media_subtype && - info.info.h264.size.width == state->current_format.info.h264.size.width && - info.info.h264.size.height == state->current_format.info.h264.size.height) - return SPA_RESULT_OK; - } - } - - if (state->have_format && !(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - spa_v4l2_use_buffers (this, NULL, 0); - state->have_format = false; - } - - if (spa_v4l2_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - state->current_format = info; - state->have_format = true; - } - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +static int impl_node_port_reuse_buffer(struct spa_node *node, + uint32_t port_id, + uint32_t buffer_id) { - struct impl *this; - struct port *state; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct port *state; + int res; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(port_id == 0, SPA_RESULT_INVALID_PORT); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); + state = &this->out_ports[port_id]; - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(state->n_buffers > 0, SPA_RESULT_NO_BUFFERS); + spa_return_val_if_fail(buffer_id < state->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); - state = &this->out_ports[port_id]; + res = spa_v4l2_buffer_recycle(this, buffer_id); - if (!state->have_format) - return SPA_RESULT_NO_FORMAT; - - b.data = state->format_buffer; - b.size = sizeof (state->format_buffer); - - spa_pod_builder_push_format (&b, &f[0], this->type.format, - state->current_format.media_type, - state->current_format.media_subtype); - - if (state->current_format.media_subtype == this->type.media_subtype.raw) { - spa_pod_builder_add (&b, - PROP (&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, state->current_format.info.raw.format), - PROP (&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, &state->current_format.info.raw.size), - PROP (&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, &state->current_format.info.raw.framerate), - 0); - } - else if (state->current_format.media_subtype == this->type.media_subtype_video.mjpg || - state->current_format.media_subtype == this->type.media_subtype_video.jpeg) { - spa_pod_builder_add (&b, - PROP (&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, &state->current_format.info.mjpg.size), - PROP (&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, &state->current_format.info.mjpg.framerate), - 0); - } - else if (state->current_format.media_subtype == this->type.media_subtype_video.h264) { - spa_pod_builder_add (&b, - PROP (&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, &state->current_format.info.h264.size), - PROP (&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, &state->current_format.info.h264.framerate), - 0); - } else - return SPA_RESULT_NO_FORMAT; - - spa_pod_builder_pop (&b, &f[0]); - - *format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); - - return SPA_RESULT_OK; + return res; } -static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +static int impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; + struct impl *this; + int res; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - *info = &this->out_ports[port_id].info; + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + res = spa_v4l2_port_set_enabled(this, false); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + res = spa_v4l2_port_set_enabled(this, true); + } else + res = SPA_RESULT_NOT_IMPLEMENTED; - return SPA_RESULT_OK; + return res; } -static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +static int impl_node_process_input(struct spa_node *node) { - - struct impl *this; - struct port *state; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - state = &this->out_ports[port_id]; - - spa_pod_builder_init (&b, state->params_buffer, sizeof (state->params_buffer)); - - switch (index) { - case 0: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, state->fmt.fmt.pix.sizeimage), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, state->fmt.fmt.pix.bytesperline), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, MAX_BUFFERS, 2, MAX_BUFFERS), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; - - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; - - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } - - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +static int impl_node_process_output(struct spa_node *node) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct impl *this; + int res = SPA_RESULT_OK; + struct spa_port_io *io; -static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) -{ - struct impl *this; - struct port *state; - int res; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + this = SPA_CONTAINER_OF(node, struct impl, node); - this = SPA_CONTAINER_OF (node, struct impl, node); + io = this->out_ports[0].io; + spa_return_val_if_fail(io != NULL, SPA_RESULT_WRONG_STATE); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + if (io->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - state = &this->out_ports[port_id]; - - if (!state->have_format) - return SPA_RESULT_NO_FORMAT; - - if (state->n_buffers) { - spa_v4l2_stream_off (this); - if ((res = spa_v4l2_clear_buffers (this)) < 0) - return res; - } - if (buffers != NULL) { - if ((res = spa_v4l2_use_buffers (this, buffers, n_buffers)) < 0) - return res; - } - return SPA_RESULT_OK; -} - -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - struct impl *this; - struct port *state; - int res; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (buffers != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - state = &this->out_ports[port_id]; - - if (!state->have_format) - return SPA_RESULT_NO_FORMAT; - - res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers); - - return res; -} - -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->out_ports[port_id].io = io; - - return SPA_RESULT_OK; -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - struct impl *this; - struct port *state; - int res; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (port_id == 0, SPA_RESULT_INVALID_PORT); - - this = SPA_CONTAINER_OF (node, struct impl, node); - state = &this->out_ports[port_id]; - - spa_return_val_if_fail (state->n_buffers > 0, SPA_RESULT_NO_BUFFERS); - spa_return_val_if_fail (buffer_id < state->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); - - res = spa_v4l2_buffer_recycle (this, buffer_id); - - return res; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - struct impl *this; - int res; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - res = spa_v4l2_port_set_enabled (this, false); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - res = spa_v4l2_port_set_enabled (this, true); - } - else - res = SPA_RESULT_NOT_IMPLEMENTED; - - return res; -} - -static int -impl_node_process_input (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - struct impl *this; - int res = SPA_RESULT_OK; - struct spa_port_io *io; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - io = this->out_ports[0].io; - spa_return_val_if_fail (io != NULL, SPA_RESULT_WRONG_STATE); - - if (io->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - if (io->buffer_id != SPA_ID_INVALID) { - res = spa_v4l2_buffer_recycle (this, io->buffer_id); - io->buffer_id = SPA_ID_INVALID; - } - return res; + if (io->buffer_id != SPA_ID_INVALID) { + res = spa_v4l2_buffer_recycle(this, io->buffer_id); + io->buffer_id = SPA_ID_INVALID; + } + return res; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, }; -static int -impl_clock_get_props (struct spa_clock *clock, - struct spa_props **props) +static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_clock_set_props (struct spa_clock *clock, - const struct spa_props *props) +static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_clock_get_time (struct spa_clock *clock, - int32_t *rate, - int64_t *ticks, - int64_t *monotonic_time) +static int impl_clock_get_time(struct spa_clock *clock, + int32_t *rate, + int64_t *ticks, + int64_t *monotonic_time) { - struct impl *this; - struct port *state; + struct impl *this; + struct port *state; - spa_return_val_if_fail (clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (clock, struct impl, clock); - state = &this->out_ports[0]; + this = SPA_CONTAINER_OF(clock, struct impl, clock); + state = &this->out_ports[0]; - if (rate) - *rate = SPA_USEC_PER_SEC; - if (ticks) - *ticks = state->last_ticks; - if (monotonic_time) - *monotonic_time = state->last_monotonic; + if (rate) + *rate = SPA_USEC_PER_SEC; + if (ticks) + *ticks = state->last_ticks; + if (monotonic_time) + *monotonic_time = state->last_monotonic; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_clock impl_clock = { - sizeof (struct spa_clock), - NULL, - SPA_CLOCK_STATE_STOPPED, - impl_clock_get_props, - impl_clock_set_props, - impl_clock_get_time, + sizeof(struct spa_clock), + NULL, + SPA_CLOCK_STATE_STOPPED, + impl_clock_get_props, + impl_clock_set_props, + impl_clock_get_time, }; -static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = (struct impl *) handle; + this = (struct impl *) handle; - if (interface_id == this->type.node) - *interface = &this->node; - else if (interface_id == this->type.clock) - *interface = &this->clock; - else - return SPA_RESULT_UNKNOWN_INTERFACE; + if (interface_id == this->type.node) + *interface = &this->node; + else if (interface_id == this->type.clock) + *interface = &this->clock; + else + return SPA_RESULT_UNKNOWN_INTERFACE; - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + return SPA_RESULT_OK; } static int -impl_clear (struct spa_handle *handle) +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) { - return SPA_RESULT_OK; + struct impl *this; + uint32_t i; + const char *str; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear, this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__MainLoop) == 0) + this->out_ports[0].main_loop = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) + this->out_ports[0].data_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + if (this->out_ports[0].main_loop == NULL) { + spa_log_error(this->log, "a main_loop is needed"); + return SPA_RESULT_ERROR; + } + if (this->out_ports[0].data_loop == NULL) { + spa_log_error(this->log, "a data_loop is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + this->clock = impl_clock; + + reset_props(&this->props); + + this->out_ports[0].log = this->log; + this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_LIVE; + + this->out_ports[0].export_buf = true; + + if (info && (str = spa_dict_lookup(info, "device.path"))) { + strncpy(this->props.device, str, 63); + } + + return SPA_RESULT_OK; } -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - const char *str; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear, - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__MainLoop) == 0) - this->out_ports[0].main_loop = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) - this->out_ports[0].data_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - if (this->out_ports[0].main_loop == NULL) { - spa_log_error (this->log, "a main_loop is needed"); - return SPA_RESULT_ERROR; - } - if (this->out_ports[0].data_loop == NULL) { - spa_log_error (this->log, "a data_loop is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - this->clock = impl_clock; - - reset_props (&this->props); - - this->out_ports[0].log = this->log; - this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_LIVE; - - this->out_ports[0].export_buf = true; - - if (info && (str = spa_dict_lookup (info, "device.path"))) { - strncpy (this->props.device, str, 63); - } - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, - { SPA_TYPE__Clock, }, +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, + {SPA_TYPE__Clock,}, }; -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) +static int impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - if (index < 0 || index >= SPA_N_ELEMENTS (impl_interfaces)) - return SPA_RESULT_ENUM_END; + if (index < 0 || index >= SPA_N_ELEMENTS(impl_interfaces)) + return SPA_RESULT_ENUM_END; - *info = &impl_interfaces[index]; - return SPA_RESULT_OK; + *info = &impl_interfaces[index]; + + return SPA_RESULT_OK; } -const struct spa_handle_factory spa_v4l2_source_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_v4l2_source_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index cd1d79dfa..d4c2ee990 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -1,3 +1,21 @@ +/* Spa + * Copyright (C) 2017 Wim Taymans + * + * 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. + */ #include #include #include @@ -7,181 +25,173 @@ #include #include -#define CLEAR(x) memset(&(x), 0, sizeof(x)) +static void v4l2_on_fd_events(struct spa_source *source); -static void v4l2_on_fd_events (struct spa_source *source); - -static int -xioctl (int fd, int request, void *arg) +static int xioctl(int fd, int request, void *arg) { - int err; + int err; - do { - err = ioctl (fd, request, arg); - } while (err == -1 && errno == EINTR); + do { + err = ioctl(fd, request, arg); + } while (err == -1 && errno == EINTR); - return err; + return err; } -static int -spa_v4l2_open (struct impl *this) +static int spa_v4l2_open(struct impl *this) { - struct port *state = &this->out_ports[0]; - struct stat st; - struct props *props = &this->props; + struct port *state = &this->out_ports[0]; + struct stat st; + struct props *props = &this->props; - if (state->opened) - return 0; + if (state->opened) + return 0; - if (props->device[0] == '\0') { - spa_log_error (state->log, "v4l2: Device property not set"); - return -1; - } + if (props->device[0] == '\0') { + spa_log_error(state->log, "v4l2: Device property not set"); + return -1; + } - spa_log_info (state->log, "v4l2: Playback device is '%s'", props->device); + spa_log_info(state->log, "v4l2: Playback device is '%s'", props->device); - if (stat (props->device, &st) < 0) { - spa_log_error (state->log, "v4l2: Cannot identify '%s': %d, %s", - props->device, errno, strerror (errno)); - return -1; - } + if (stat(props->device, &st) < 0) { + spa_log_error(state->log, "v4l2: Cannot identify '%s': %d, %s", + props->device, errno, strerror(errno)); + return -1; + } - if (!S_ISCHR (st.st_mode)) { - spa_log_error (state->log, "v4l2: %s is no device", props->device); - return -1; - } + if (!S_ISCHR(st.st_mode)) { + spa_log_error(state->log, "v4l2: %s is no device", props->device); + return -1; + } - state->fd = open (props->device, O_RDWR | O_NONBLOCK, 0); + state->fd = open(props->device, O_RDWR | O_NONBLOCK, 0); - if (state->fd == -1) { - spa_log_error (state->log, "v4l2: Cannot open '%s': %d, %s", - props->device, errno, strerror (errno)); - return -1; - } + if (state->fd == -1) { + spa_log_error(state->log, "v4l2: Cannot open '%s': %d, %s", + props->device, errno, strerror(errno)); + return -1; + } - if (xioctl (state->fd, VIDIOC_QUERYCAP, &state->cap) < 0) { - perror ("QUERYCAP"); - return -1; - } + if (xioctl(state->fd, VIDIOC_QUERYCAP, &state->cap) < 0) { + perror("QUERYCAP"); + return -1; + } - if ((state->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { - spa_log_error (state->log, "v4l2: %s is no video capture device", props->device); - return -1; - } + if ((state->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { + spa_log_error(state->log, "v4l2: %s is no video capture device", props->device); + return -1; + } - state->source.func = v4l2_on_fd_events; - state->source.data = this; - state->source.fd = state->fd; - state->source.mask = SPA_IO_IN | SPA_IO_ERR; - state->source.rmask = 0; + state->source.func = v4l2_on_fd_events; + state->source.data = this; + state->source.fd = state->fd; + state->source.mask = SPA_IO_IN | SPA_IO_ERR; + state->source.rmask = 0; - state->opened = true; + state->opened = true; - return 0; + return 0; } -static int -spa_v4l2_buffer_recycle (struct impl *this, uint32_t buffer_id) +static int spa_v4l2_buffer_recycle(struct impl *this, uint32_t buffer_id) { - struct port *state = &this->out_ports[0]; - struct buffer *b = &state->buffers[buffer_id]; + struct port *state = &this->out_ports[0]; + struct buffer *b = &state->buffers[buffer_id]; - if (!b->outstanding) - return SPA_RESULT_OK; + if (!b->outstanding) + return SPA_RESULT_OK; - b->outstanding = false; - spa_log_trace (state->log, "v4l2 %p: recycle buffer %d", this, buffer_id); + b->outstanding = false; + spa_log_trace(state->log, "v4l2 %p: recycle buffer %d", this, buffer_id); - if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) { - perror ("VIDIOC_QBUF"); - } - return SPA_RESULT_OK; + if (xioctl(state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) { + perror("VIDIOC_QBUF"); + } + return SPA_RESULT_OK; } -static int -spa_v4l2_clear_buffers (struct impl *this) +static int spa_v4l2_clear_buffers(struct impl *this) { - struct port *state = &this->out_ports[0]; - struct v4l2_requestbuffers reqbuf; - int i; + struct port *state = &this->out_ports[0]; + struct v4l2_requestbuffers reqbuf; + int i; - if (state->n_buffers == 0) - return SPA_RESULT_OK; + if (state->n_buffers == 0) + return SPA_RESULT_OK; - for (i = 0; i < state->n_buffers; i++) { - struct buffer *b; + for (i = 0; i < state->n_buffers; i++) { + struct buffer *b; - b = &state->buffers[i]; - if (b->outstanding) { - spa_log_info (state->log, "v4l2: queueing outstanding buffer %p", b); - spa_v4l2_buffer_recycle (this, i); - } - if (b->allocated) { - if (b->outbuf->datas[0].data) - munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].maxsize); - if (b->outbuf->datas[0].fd != -1) - close (b->outbuf->datas[0].fd); - b->outbuf->datas[0].type = SPA_ID_INVALID; - } - } + b = &state->buffers[i]; + if (b->outstanding) { + spa_log_info(state->log, "v4l2: queueing outstanding buffer %p", b); + spa_v4l2_buffer_recycle(this, i); + } + if (b->allocated) { + if (b->outbuf->datas[0].data) + munmap(b->outbuf->datas[0].data, b->outbuf->datas[0].maxsize); + if (b->outbuf->datas[0].fd != -1) + close(b->outbuf->datas[0].fd); + b->outbuf->datas[0].type = SPA_ID_INVALID; + } + } - CLEAR(reqbuf); - reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = state->memtype; - reqbuf.count = 0; + spa_zero(reqbuf); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = state->memtype; + reqbuf.count = 0; - if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - perror ("VIDIOC_REQBUFS"); - } - state->n_buffers = 0; + if (xioctl(state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + perror("VIDIOC_REQBUFS"); + } + state->n_buffers = 0; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -spa_v4l2_port_set_enabled (struct impl *this, bool enabled) +static int spa_v4l2_port_set_enabled(struct impl *this, bool enabled) { - struct port *state = &this->out_ports[0]; - if (state->source_enabled != enabled) { - spa_log_info (state->log, "v4l2: enabled %d", enabled); - state->source_enabled = enabled; - if (enabled) - spa_loop_add_source (state->data_loop, &state->source); - else - spa_loop_remove_source (state->data_loop, &state->source); - } - return SPA_RESULT_OK; + struct port *state = &this->out_ports[0]; + if (state->source_enabled != enabled) { + spa_log_info(state->log, "v4l2: enabled %d", enabled); + state->source_enabled = enabled; + if (enabled) + spa_loop_add_source(state->data_loop, &state->source); + else + spa_loop_remove_source(state->data_loop, &state->source); + } + return SPA_RESULT_OK; } -static int -spa_v4l2_close (struct impl *this) +static int spa_v4l2_close(struct impl *this) { - struct port *state = &this->out_ports[0]; + struct port *state = &this->out_ports[0]; - if (!state->opened) - return 0; + if (!state->opened) + return 0; - if (state->n_buffers > 0) - return 0; + if (state->n_buffers > 0) + return 0; - spa_v4l2_port_set_enabled (this, false); + spa_v4l2_port_set_enabled(this, false); - spa_log_info (state->log, "v4l2: close"); + spa_log_info(state->log, "v4l2: close"); - if (close(state->fd)) - perror ("close"); + if (close(state->fd)) + perror("close"); - state->fd = -1; - state->opened = false; + state->fd = -1; + state->opened = false; - return 0; + return 0; } struct format_info { - uint32_t fourcc; - off_t format_offset; - off_t media_type_offset; - off_t media_subtype_offset; + uint32_t fourcc; + off_t format_offset; + off_t media_type_offset; + off_t media_subtype_offset; }; #define VIDEO offsetof(struct type, media_type.video) @@ -233,1009 +243,965 @@ struct format_info { #define FORMAT_NV61 offsetof(struct type, video_format.NV61) #define FORMAT_NV24 offsetof(struct type, video_format.NV24) -static const struct format_info format_info[] = -{ - /* RGB formats */ - { V4L2_PIX_FMT_RGB332, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_ARGB555, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_XRGB555, FORMAT_RGB15, VIDEO, RAW }, - { V4L2_PIX_FMT_ARGB555X, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_XRGB555X, FORMAT_BGR15, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB565, FORMAT_RGB16, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB565X, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_BGR666, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_BGR24, FORMAT_BGR, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB24, FORMAT_RGB, VIDEO, RAW }, - { V4L2_PIX_FMT_ABGR32, FORMAT_BGRA, VIDEO, RAW }, - { V4L2_PIX_FMT_XBGR32, FORMAT_BGRx, VIDEO, RAW }, - { V4L2_PIX_FMT_ARGB32, FORMAT_ARGB, VIDEO, RAW }, - { V4L2_PIX_FMT_XRGB32, FORMAT_xRGB, VIDEO, RAW }, +static const struct format_info format_info[] = { + /* RGB formats */ + {V4L2_PIX_FMT_RGB332, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_ARGB555, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_XRGB555, FORMAT_RGB15, VIDEO, RAW}, + {V4L2_PIX_FMT_ARGB555X, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_XRGB555X, FORMAT_BGR15, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB565, FORMAT_RGB16, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB565X, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_BGR666, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_BGR24, FORMAT_BGR, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB24, FORMAT_RGB, VIDEO, RAW}, + {V4L2_PIX_FMT_ABGR32, FORMAT_BGRA, VIDEO, RAW}, + {V4L2_PIX_FMT_XBGR32, FORMAT_BGRx, VIDEO, RAW}, + {V4L2_PIX_FMT_ARGB32, FORMAT_ARGB, VIDEO, RAW}, + {V4L2_PIX_FMT_XRGB32, FORMAT_xRGB, VIDEO, RAW}, - /* Deprecated Packed RGB Image Formats (alpha ambiguity) */ - { V4L2_PIX_FMT_RGB444, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB555, FORMAT_RGB15, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB555X, FORMAT_BGR15, VIDEO, RAW }, - { V4L2_PIX_FMT_BGR32, FORMAT_BGRx, VIDEO, RAW }, - { V4L2_PIX_FMT_RGB32, FORMAT_xRGB, VIDEO, RAW }, + /* Deprecated Packed RGB Image Formats (alpha ambiguity) */ + {V4L2_PIX_FMT_RGB444, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB555, FORMAT_RGB15, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB555X, FORMAT_BGR15, VIDEO, RAW}, + {V4L2_PIX_FMT_BGR32, FORMAT_BGRx, VIDEO, RAW}, + {V4L2_PIX_FMT_RGB32, FORMAT_xRGB, VIDEO, RAW}, - /* Grey formats */ - { V4L2_PIX_FMT_GREY, FORMAT_GRAY8, VIDEO, RAW }, - { V4L2_PIX_FMT_Y4, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_Y6, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_Y10, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_Y12, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_Y16, FORMAT_GRAY16_LE, VIDEO, RAW }, - { V4L2_PIX_FMT_Y16_BE, FORMAT_GRAY16_BE, VIDEO, RAW }, - { V4L2_PIX_FMT_Y10BPACK, FORMAT_UNKNOWN, VIDEO, RAW }, + /* Grey formats */ + {V4L2_PIX_FMT_GREY, FORMAT_GRAY8, VIDEO, RAW}, + {V4L2_PIX_FMT_Y4, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_Y6, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_Y10, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_Y12, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_Y16, FORMAT_GRAY16_LE, VIDEO, RAW}, + {V4L2_PIX_FMT_Y16_BE, FORMAT_GRAY16_BE, VIDEO, RAW}, + {V4L2_PIX_FMT_Y10BPACK, FORMAT_UNKNOWN, VIDEO, RAW}, - /* Palette formats */ - { V4L2_PIX_FMT_PAL8, FORMAT_UNKNOWN, VIDEO, RAW }, + /* Palette formats */ + {V4L2_PIX_FMT_PAL8, FORMAT_UNKNOWN, VIDEO, RAW}, - /* Chrominance formats */ - { V4L2_PIX_FMT_UV8, FORMAT_UNKNOWN, VIDEO, RAW }, + /* Chrominance formats */ + {V4L2_PIX_FMT_UV8, FORMAT_UNKNOWN, VIDEO, RAW}, - /* Luminance+Chrominance formats */ - { V4L2_PIX_FMT_YVU410, FORMAT_YVU9, VIDEO, RAW }, - { V4L2_PIX_FMT_YVU420, FORMAT_YV12, VIDEO, RAW }, - { V4L2_PIX_FMT_YVU420M, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUYV, FORMAT_YUY2, VIDEO, RAW }, - { V4L2_PIX_FMT_YYUV, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YVYU, FORMAT_YVYU, VIDEO, RAW }, - { V4L2_PIX_FMT_UYVY, FORMAT_UYVY, VIDEO, RAW }, - { V4L2_PIX_FMT_VYUY, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV422P, FORMAT_Y42B, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV411P, FORMAT_Y41B, VIDEO, RAW }, - { V4L2_PIX_FMT_Y41P, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV444, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV555, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV565, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV32, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV410, FORMAT_YUV9, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV420, FORMAT_I420, VIDEO, RAW }, - { V4L2_PIX_FMT_YUV420M, FORMAT_I420, VIDEO, RAW }, - { V4L2_PIX_FMT_HI240, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_HM12, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_M420, FORMAT_UNKNOWN, VIDEO, RAW }, + /* Luminance+Chrominance formats */ + {V4L2_PIX_FMT_YVU410, FORMAT_YVU9, VIDEO, RAW}, + {V4L2_PIX_FMT_YVU420, FORMAT_YV12, VIDEO, RAW}, + {V4L2_PIX_FMT_YVU420M, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUYV, FORMAT_YUY2, VIDEO, RAW}, + {V4L2_PIX_FMT_YYUV, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YVYU, FORMAT_YVYU, VIDEO, RAW}, + {V4L2_PIX_FMT_UYVY, FORMAT_UYVY, VIDEO, RAW}, + {V4L2_PIX_FMT_VYUY, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV422P, FORMAT_Y42B, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV411P, FORMAT_Y41B, VIDEO, RAW}, + {V4L2_PIX_FMT_Y41P, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV444, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV555, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV565, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV32, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV410, FORMAT_YUV9, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV420, FORMAT_I420, VIDEO, RAW}, + {V4L2_PIX_FMT_YUV420M, FORMAT_I420, VIDEO, RAW}, + {V4L2_PIX_FMT_HI240, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_HM12, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_M420, FORMAT_UNKNOWN, VIDEO, RAW}, - /* two planes -- one Y, one Cr + Cb interleaved */ - { V4L2_PIX_FMT_NV12, FORMAT_NV12, VIDEO, RAW }, - { V4L2_PIX_FMT_NV12M, FORMAT_NV12, VIDEO, RAW }, - { V4L2_PIX_FMT_NV12MT, FORMAT_NV12_64Z32, VIDEO, RAW }, - { V4L2_PIX_FMT_NV12MT_16X16, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_NV21, FORMAT_NV21, VIDEO, RAW }, - { V4L2_PIX_FMT_NV21M, FORMAT_NV21, VIDEO, RAW }, - { V4L2_PIX_FMT_NV16, FORMAT_NV16, VIDEO, RAW }, - { V4L2_PIX_FMT_NV16M, FORMAT_NV16, VIDEO, RAW }, - { V4L2_PIX_FMT_NV61, FORMAT_NV61, VIDEO, RAW }, - { V4L2_PIX_FMT_NV61M, FORMAT_NV61, VIDEO, RAW }, - { V4L2_PIX_FMT_NV24, FORMAT_NV24, VIDEO, RAW }, - { V4L2_PIX_FMT_NV42, FORMAT_UNKNOWN, VIDEO, RAW }, + /* two planes -- one Y, one Cr + Cb interleaved */ + {V4L2_PIX_FMT_NV12, FORMAT_NV12, VIDEO, RAW}, + {V4L2_PIX_FMT_NV12M, FORMAT_NV12, VIDEO, RAW}, + {V4L2_PIX_FMT_NV12MT, FORMAT_NV12_64Z32, VIDEO, RAW}, + {V4L2_PIX_FMT_NV12MT_16X16, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_NV21, FORMAT_NV21, VIDEO, RAW}, + {V4L2_PIX_FMT_NV21M, FORMAT_NV21, VIDEO, RAW}, + {V4L2_PIX_FMT_NV16, FORMAT_NV16, VIDEO, RAW}, + {V4L2_PIX_FMT_NV16M, FORMAT_NV16, VIDEO, RAW}, + {V4L2_PIX_FMT_NV61, FORMAT_NV61, VIDEO, RAW}, + {V4L2_PIX_FMT_NV61M, FORMAT_NV61, VIDEO, RAW}, + {V4L2_PIX_FMT_NV24, FORMAT_NV24, VIDEO, RAW}, + {V4L2_PIX_FMT_NV42, FORMAT_UNKNOWN, VIDEO, RAW}, - /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ - { V4L2_PIX_FMT_SBGGR8, FORMAT_UNKNOWN, VIDEO, BAYER }, - { V4L2_PIX_FMT_SGBRG8, FORMAT_UNKNOWN, VIDEO, BAYER }, - { V4L2_PIX_FMT_SGRBG8, FORMAT_UNKNOWN, VIDEO, BAYER }, - { V4L2_PIX_FMT_SRGGB8, FORMAT_UNKNOWN, VIDEO, BAYER }, + /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ + {V4L2_PIX_FMT_SBGGR8, FORMAT_UNKNOWN, VIDEO, BAYER}, + {V4L2_PIX_FMT_SGBRG8, FORMAT_UNKNOWN, VIDEO, BAYER}, + {V4L2_PIX_FMT_SGRBG8, FORMAT_UNKNOWN, VIDEO, BAYER}, + {V4L2_PIX_FMT_SRGGB8, FORMAT_UNKNOWN, VIDEO, BAYER}, - /* compressed formats */ - { V4L2_PIX_FMT_MJPEG, FORMAT_ENCODED, VIDEO, MJPG }, - { V4L2_PIX_FMT_JPEG, FORMAT_ENCODED, IMAGE, JPEG }, - { V4L2_PIX_FMT_PJPG, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_DV, FORMAT_ENCODED, VIDEO, DV }, - { V4L2_PIX_FMT_MPEG, FORMAT_ENCODED, VIDEO, MPEGTS }, - { V4L2_PIX_FMT_H264, FORMAT_ENCODED, VIDEO, H264 }, - { V4L2_PIX_FMT_H264_NO_SC, FORMAT_ENCODED, VIDEO, H264 }, - { V4L2_PIX_FMT_H264_MVC, FORMAT_ENCODED, VIDEO, H264 }, - { V4L2_PIX_FMT_H263, FORMAT_ENCODED, VIDEO, H263 }, - { V4L2_PIX_FMT_MPEG1, FORMAT_ENCODED, VIDEO, MPEG1 }, - { V4L2_PIX_FMT_MPEG2, FORMAT_ENCODED, VIDEO, MPEG2 }, - { V4L2_PIX_FMT_MPEG4, FORMAT_ENCODED, VIDEO, MPEG4 }, - { V4L2_PIX_FMT_XVID, FORMAT_ENCODED, VIDEO, XVID }, - { V4L2_PIX_FMT_VC1_ANNEX_G, FORMAT_ENCODED, VIDEO, VC1 }, - { V4L2_PIX_FMT_VC1_ANNEX_L, FORMAT_ENCODED, VIDEO, VC1 }, - { V4L2_PIX_FMT_VP8, FORMAT_ENCODED, VIDEO, VP8 }, + /* compressed formats */ + {V4L2_PIX_FMT_MJPEG, FORMAT_ENCODED, VIDEO, MJPG}, + {V4L2_PIX_FMT_JPEG, FORMAT_ENCODED, IMAGE, JPEG}, + {V4L2_PIX_FMT_PJPG, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_DV, FORMAT_ENCODED, VIDEO, DV}, + {V4L2_PIX_FMT_MPEG, FORMAT_ENCODED, VIDEO, MPEGTS}, + {V4L2_PIX_FMT_H264, FORMAT_ENCODED, VIDEO, H264}, + {V4L2_PIX_FMT_H264_NO_SC, FORMAT_ENCODED, VIDEO, H264}, + {V4L2_PIX_FMT_H264_MVC, FORMAT_ENCODED, VIDEO, H264}, + {V4L2_PIX_FMT_H263, FORMAT_ENCODED, VIDEO, H263}, + {V4L2_PIX_FMT_MPEG1, FORMAT_ENCODED, VIDEO, MPEG1}, + {V4L2_PIX_FMT_MPEG2, FORMAT_ENCODED, VIDEO, MPEG2}, + {V4L2_PIX_FMT_MPEG4, FORMAT_ENCODED, VIDEO, MPEG4}, + {V4L2_PIX_FMT_XVID, FORMAT_ENCODED, VIDEO, XVID}, + {V4L2_PIX_FMT_VC1_ANNEX_G, FORMAT_ENCODED, VIDEO, VC1}, + {V4L2_PIX_FMT_VC1_ANNEX_L, FORMAT_ENCODED, VIDEO, VC1}, + {V4L2_PIX_FMT_VP8, FORMAT_ENCODED, VIDEO, VP8}, - /* Vendor-specific formats */ - { V4L2_PIX_FMT_WNVA, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_SN9C10X, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_PWC1, FORMAT_UNKNOWN, VIDEO, RAW }, - { V4L2_PIX_FMT_PWC2, FORMAT_UNKNOWN, VIDEO, RAW }, + /* Vendor-specific formats */ + {V4L2_PIX_FMT_WNVA, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_SN9C10X, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_PWC1, FORMAT_UNKNOWN, VIDEO, RAW}, + {V4L2_PIX_FMT_PWC2, FORMAT_UNKNOWN, VIDEO, RAW}, }; -static const struct format_info * -fourcc_to_format_info (uint32_t fourcc) +static const struct format_info *fourcc_to_format_info(uint32_t fourcc) { - int i; + int i; - for (i = 0; i < SPA_N_ELEMENTS (format_info); i++) { - if (format_info[i].fourcc == fourcc) - return &format_info[i]; - } - return NULL; + for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) { + if (format_info[i].fourcc == fourcc) + return &format_info[i]; + } + return NULL; } #if 0 -static const struct format_info * -video_format_to_format_info (uint32_t format) +static const struct format_info *video_format_to_format_info(uint32_t format) { - int i; + int i; - for (i = 0; i < SPA_N_ELEMENTS (format_info); i++) { - if (format_info[i].format == format) - return &format_info[i]; - } - return NULL; + for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) { + if (format_info[i].format == format) + return &format_info[i]; + } + return NULL; } #endif -static const struct format_info * -find_format_info_by_media_type (struct type *types, - uint32_t type, - uint32_t subtype, - uint32_t format, - int startidx) +static const struct format_info *find_format_info_by_media_type(struct type *types, + uint32_t type, + uint32_t subtype, + uint32_t format, + int startidx) { - int i; + int i; - for (i = startidx; i < SPA_N_ELEMENTS (format_info); i++) { - uint32_t media_type, media_subtype, media_format; + for (i = startidx; i < SPA_N_ELEMENTS(format_info); i++) { + uint32_t media_type, media_subtype, media_format; - media_type = *SPA_MEMBER (types, format_info[i].media_type_offset, uint32_t); - media_subtype = *SPA_MEMBER (types, format_info[i].media_subtype_offset, uint32_t); - media_format = *SPA_MEMBER (types, format_info[i].format_offset, uint32_t); + media_type = *SPA_MEMBER(types, format_info[i].media_type_offset, uint32_t); + media_subtype = *SPA_MEMBER(types, format_info[i].media_subtype_offset, uint32_t); + media_format = *SPA_MEMBER(types, format_info[i].format_offset, uint32_t); - if ((media_type == type) && - (media_subtype == subtype) && - (format == 0 || media_format == format)) - return &format_info[i]; - } - return NULL; + if ((media_type == type) && + (media_subtype == subtype) && (format == 0 || media_format == format)) + return &format_info[i]; + } + return NULL; } static uint32_t -enum_filter_format (struct type *type, const struct spa_format *filter, uint32_t index) +enum_filter_format(struct type *type, const struct spa_format *filter, uint32_t index) { - uint32_t video_format = 0; + uint32_t video_format = 0; - if ((filter->body.media_type.value == type->media_type.video || - filter->body.media_type.value == type->media_type.image)) { - if (filter->body.media_subtype.value == type->media_subtype.raw) { - struct spa_pod_prop *p; - uint32_t n_values; - const uint32_t *values; + if ((filter->body.media_type.value == type->media_type.video || + filter->body.media_type.value == type->media_type.image)) { + if (filter->body.media_subtype.value == type->media_subtype.raw) { + struct spa_pod_prop *p; + uint32_t n_values; + const uint32_t *values; - if (!(p = spa_format_find_prop (filter, type->format_video.format))) - return type->video_format.UNKNOWN; + if (!(p = spa_format_find_prop(filter, type->format_video.format))) + return type->video_format.UNKNOWN; - if (p->body.value.type != SPA_POD_TYPE_ID) - return type->video_format.UNKNOWN; + if (p->body.value.type != SPA_POD_TYPE_ID) + return type->video_format.UNKNOWN; - values = SPA_POD_BODY_CONST (&p->body.value); - n_values = SPA_POD_PROP_N_VALUES (p); + values = SPA_POD_BODY_CONST(&p->body.value); + n_values = SPA_POD_PROP_N_VALUES(p); - if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) { - if (index + 1 < n_values) - video_format = values[index + 1]; - } else { - if (index == 0) - video_format = values[0]; - } - } else { - if (index == 0) - video_format = type->video_format.ENCODED; - } - } - return video_format; + if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) { + if (index + 1 < n_values) + video_format = values[index + 1]; + } else { + if (index == 0) + video_format = values[0]; + } + } else { + if (index == 0) + video_format = type->video_format.ENCODED; + } + } + return video_format; } static bool -filter_framesize (struct v4l2_frmsizeenum *frmsize, - const struct spa_rectangle *min, - const struct spa_rectangle *max, - const struct spa_rectangle *step) +filter_framesize(struct v4l2_frmsizeenum *frmsize, + const struct spa_rectangle *min, + const struct spa_rectangle *max, + const struct spa_rectangle *step) { - if (frmsize->type == V4L2_FRMSIZE_TYPE_DISCRETE) { - if (frmsize->discrete.width < min->width || - frmsize->discrete.height < min->height || - frmsize->discrete.width > max->width || - frmsize->discrete.height > max->height) { - return false; - } - } else if (frmsize->type == V4L2_FRMSIZE_TYPE_CONTINUOUS || - frmsize->type == V4L2_FRMSIZE_TYPE_STEPWISE) { - /* FIXME, use LCM */ - frmsize->stepwise.step_width *= step->width; - frmsize->stepwise.step_height *= step->height; + if (frmsize->type == V4L2_FRMSIZE_TYPE_DISCRETE) { + if (frmsize->discrete.width < min->width || + frmsize->discrete.height < min->height || + frmsize->discrete.width > max->width || + frmsize->discrete.height > max->height) { + return false; + } + } else if (frmsize->type == V4L2_FRMSIZE_TYPE_CONTINUOUS || + frmsize->type == V4L2_FRMSIZE_TYPE_STEPWISE) { + /* FIXME, use LCM */ + frmsize->stepwise.step_width *= step->width; + frmsize->stepwise.step_height *= step->height; - if (frmsize->stepwise.max_width < min->width || - frmsize->stepwise.max_height < min->height || - frmsize->stepwise.min_width > max->width || - frmsize->stepwise.min_height > max->height) - return false; + if (frmsize->stepwise.max_width < min->width || + frmsize->stepwise.max_height < min->height || + frmsize->stepwise.min_width > max->width || + frmsize->stepwise.min_height > max->height) + return false; - frmsize->stepwise.min_width = SPA_MAX (frmsize->stepwise.min_width, min->width); - frmsize->stepwise.min_height = SPA_MAX (frmsize->stepwise.min_height, min->height); - frmsize->stepwise.max_width = SPA_MIN (frmsize->stepwise.max_width, max->width); - frmsize->stepwise.max_height = SPA_MIN (frmsize->stepwise.max_height, max->height); - } else - return false; + frmsize->stepwise.min_width = SPA_MAX(frmsize->stepwise.min_width, min->width); + frmsize->stepwise.min_height = SPA_MAX(frmsize->stepwise.min_height, min->height); + frmsize->stepwise.max_width = SPA_MIN(frmsize->stepwise.max_width, max->width); + frmsize->stepwise.max_height = SPA_MIN(frmsize->stepwise.max_height, max->height); + } else + return false; - return true; + return true; } -static int -compare_fraction (struct v4l2_fract *f1, const struct spa_fraction *f2) +static int compare_fraction(struct v4l2_fract *f1, const struct spa_fraction *f2) { - uint64_t n1, n2; + uint64_t n1, n2; - /* fractions are reduced when set, so we can quickly see if they're equal */ - if (f1->denominator == f2->num && f1->numerator == f2->denom) - return 0; + /* fractions are reduced when set, so we can quickly see if they're equal */ + if (f1->denominator == f2->num && f1->numerator == f2->denom) + return 0; - /* extend to 64 bits */ - n1 = ((int64_t) f1->denominator) * f2->denom; - n2 = ((int64_t) f1->numerator) * f2->num; - if (n1 < n2) - return -1; - return 1; + /* extend to 64 bits */ + n1 = ((int64_t) f1->denominator) * f2->denom; + n2 = ((int64_t) f1->numerator) * f2->num; + if (n1 < n2) + return -1; + return 1; } static bool -filter_framerate (struct v4l2_frmivalenum *frmival, - const struct spa_fraction *min, - const struct spa_fraction *max, - const struct spa_fraction *step) +filter_framerate(struct v4l2_frmivalenum *frmival, + const struct spa_fraction *min, + const struct spa_fraction *max, + const struct spa_fraction *step) { - if (frmival->type == V4L2_FRMIVAL_TYPE_DISCRETE) { - if (compare_fraction (&frmival->discrete, min) < 0 || - compare_fraction (&frmival->discrete, max) > 0) - return false; - } else if (frmival->type == V4L2_FRMIVAL_TYPE_CONTINUOUS || - frmival->type == V4L2_FRMIVAL_TYPE_STEPWISE) { - /* FIXME, use LCM */ - frmival->stepwise.step.denominator *= step->num; - frmival->stepwise.step.numerator *= step->denom; + if (frmival->type == V4L2_FRMIVAL_TYPE_DISCRETE) { + if (compare_fraction(&frmival->discrete, min) < 0 || + compare_fraction(&frmival->discrete, max) > 0) + return false; + } else if (frmival->type == V4L2_FRMIVAL_TYPE_CONTINUOUS || + frmival->type == V4L2_FRMIVAL_TYPE_STEPWISE) { + /* FIXME, use LCM */ + frmival->stepwise.step.denominator *= step->num; + frmival->stepwise.step.numerator *= step->denom; - if (compare_fraction (&frmival->stepwise.max, min) < 0 || - compare_fraction (&frmival->stepwise.min, max) > 0) - return false; + if (compare_fraction(&frmival->stepwise.max, min) < 0 || + compare_fraction(&frmival->stepwise.min, max) > 0) + return false; - if (compare_fraction (&frmival->stepwise.min, min) < 0) { - frmival->stepwise.min.denominator = min->num; - frmival->stepwise.min.numerator = min->denom; - } - if (compare_fraction (&frmival->stepwise.max, max) > 0) { - frmival->stepwise.max.denominator = max->num; - frmival->stepwise.max.numerator = max->denom; - } - } else - return false; + if (compare_fraction(&frmival->stepwise.min, min) < 0) { + frmival->stepwise.min.denominator = min->num; + frmival->stepwise.min.numerator = min->denom; + } + if (compare_fraction(&frmival->stepwise.max, max) > 0) { + frmival->stepwise.max.denominator = max->num; + frmival->stepwise.max.numerator = max->denom; + } + } else + return false; - return true; + return true; } #define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f static int -spa_v4l2_enum_format (struct impl *this, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +spa_v4l2_enum_format(struct impl *this, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - struct port *state = &this->out_ports[0]; - int res, n_fractions; - const struct format_info *info; - struct spa_pod_frame f[2]; - struct spa_pod_prop *prop; - struct spa_pod_builder b = { NULL, }; - uint32_t media_type, media_subtype, video_format; + struct port *state = &this->out_ports[0]; + int res, n_fractions; + const struct format_info *info; + struct spa_pod_frame f[2]; + struct spa_pod_prop *prop; + struct spa_pod_builder b = { NULL, }; + uint32_t media_type, media_subtype, video_format; - if (spa_v4l2_open (this) < 0) - return SPA_RESULT_ERROR; + if (spa_v4l2_open(this) < 0) + return SPA_RESULT_ERROR; - *format = NULL; + *format = NULL; - if (index == 0) { - CLEAR (state->fmtdesc); - state->fmtdesc.index = 0; - state->fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - state->next_fmtdesc = true; - CLEAR (state->frmsize); - state->next_frmsize = true; - CLEAR (state->frmival); - } + if (index == 0) { + spa_zero(state->fmtdesc); + state->fmtdesc.index = 0; + state->fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + state->next_fmtdesc = true; + spa_zero(state->frmsize); + state->next_frmsize = true; + spa_zero(state->frmival); + } - if (false) { -next_fmtdesc: - state->fmtdesc.index++; - state->next_fmtdesc = true; - } + if (false) { + next_fmtdesc: + state->fmtdesc.index++; + state->next_fmtdesc = true; + } - while (state->next_fmtdesc) { - if (filter) { - video_format = enum_filter_format (&this->type, filter, state->fmtdesc.index); - if (video_format == this->type.video_format.UNKNOWN) - return SPA_RESULT_ENUM_END; + while (state->next_fmtdesc) { + if (filter) { + video_format = + enum_filter_format(&this->type, filter, state->fmtdesc.index); + if (video_format == this->type.video_format.UNKNOWN) + return SPA_RESULT_ENUM_END; - info = find_format_info_by_media_type (&this->type, - filter->body.media_type.value, - filter->body.media_subtype.value, - video_format, - 0); - if (info == NULL) - goto next_fmtdesc; + info = find_format_info_by_media_type(&this->type, + filter->body.media_type.value, + filter->body.media_subtype.value, + video_format, 0); + if (info == NULL) + goto next_fmtdesc; - state->fmtdesc.pixelformat = info->fourcc; - } else { - if ((res = xioctl (state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) { - if (errno != EINVAL) - perror ("VIDIOC_ENUM_FMT"); - return SPA_RESULT_ENUM_END; - } - } - state->next_fmtdesc = false; - state->frmsize.index = 0; - state->frmsize.pixel_format = state->fmtdesc.pixelformat; - state->next_frmsize = true; - } - if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat))) - goto next_fmtdesc; + state->fmtdesc.pixelformat = info->fourcc; + } else { + if ((res = xioctl(state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) { + if (errno != EINVAL) + perror("VIDIOC_ENUM_FMT"); + return SPA_RESULT_ENUM_END; + } + } + state->next_fmtdesc = false; + state->frmsize.index = 0; + state->frmsize.pixel_format = state->fmtdesc.pixelformat; + state->next_frmsize = true; + } + if (!(info = fourcc_to_format_info(state->fmtdesc.pixelformat))) + goto next_fmtdesc; -next_frmsize: - while (state->next_frmsize) { - if (filter) { - struct spa_pod_prop *p; + next_frmsize: + while (state->next_frmsize) { + if (filter) { + struct spa_pod_prop *p; - /* check if we have a fixed frame size */ - if (!(p = spa_format_find_prop (filter, this->type.format_video.size))) - goto do_frmsize; + /* check if we have a fixed frame size */ + if (!(p = spa_format_find_prop(filter, this->type.format_video.size))) + goto do_frmsize; - if (p->body.value.type != SPA_POD_TYPE_RECTANGLE) - return SPA_RESULT_ENUM_END; + if (p->body.value.type != SPA_POD_TYPE_RECTANGLE) + return SPA_RESULT_ENUM_END; - if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { - const struct spa_rectangle *values = SPA_POD_BODY_CONST (&p->body.value); + if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { + const struct spa_rectangle *values = + SPA_POD_BODY_CONST(&p->body.value); - if (state->frmsize.index > 0) - goto next_fmtdesc; + if (state->frmsize.index > 0) + goto next_fmtdesc; - state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE; - state->frmsize.discrete.width = values[0].width; - state->frmsize.discrete.height = values[0].height; - goto have_size; - } - } -do_frmsize: - if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) { - if (errno == EINVAL) - goto next_fmtdesc; + state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE; + state->frmsize.discrete.width = values[0].width; + state->frmsize.discrete.height = values[0].height; + goto have_size; + } + } + do_frmsize: + if ((res = xioctl(state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) { + if (errno == EINVAL) + goto next_fmtdesc; - perror ("VIDIOC_ENUM_FRAMESIZES"); - return SPA_RESULT_ENUM_END; - } - if (filter) { - struct spa_pod_prop *p; - const struct spa_rectangle step = { 1, 1 }, *values; - uint32_t range; - uint32_t i, n_values; + perror("VIDIOC_ENUM_FRAMESIZES"); + return SPA_RESULT_ENUM_END; + } + if (filter) { + struct spa_pod_prop *p; + const struct spa_rectangle step = { 1, 1 }, *values; + uint32_t range; + uint32_t i, n_values; - /* check if we have a fixed frame size */ - if (!(p = spa_format_find_prop (filter, this->type.format_video.size))) - goto have_size; + /* check if we have a fixed frame size */ + if (!(p = spa_format_find_prop(filter, this->type.format_video.size))) + goto have_size; - range = p->body.flags & SPA_POD_PROP_RANGE_MASK; - values = SPA_POD_BODY_CONST (&p->body.value); - n_values = SPA_POD_PROP_N_VALUES (p); + range = p->body.flags & SPA_POD_PROP_RANGE_MASK; + values = SPA_POD_BODY_CONST(&p->body.value); + n_values = SPA_POD_PROP_N_VALUES(p); - if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) { - if (filter_framesize (&state->frmsize, &values[1], - &values[2], - &step)) - goto have_size; - } else if (range == SPA_POD_PROP_RANGE_STEP && n_values > 3) { - if (filter_framesize (&state->frmsize, &values[1], - &values[2], - &values[3])) - goto have_size; - } else if (range == SPA_POD_PROP_RANGE_ENUM) { - for (i = 1; i < n_values; i++) { - if (filter_framesize (&state->frmsize, &values[i], - &values[i], - &step)) - goto have_size; - } - } - /* nothing matches the filter, get next frame size */ - state->frmsize.index++; - continue; - } + if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) { + if (filter_framesize(&state->frmsize, &values[1], &values[2], &step)) + goto have_size; + } else if (range == SPA_POD_PROP_RANGE_STEP && n_values > 3) { + if (filter_framesize(&state->frmsize, &values[1], &values[2], &values[3])) + goto have_size; + } else if (range == SPA_POD_PROP_RANGE_ENUM) { + for (i = 1; i < n_values; i++) { + if (filter_framesize(&state->frmsize, &values[i], &values[i], &step)) + goto have_size; + } + } + /* nothing matches the filter, get next frame size */ + state->frmsize.index++; + continue; + } -have_size: - if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - /* we have a fixed size, use this to get the frame intervals */ - state->frmival.index = 0; - state->frmival.pixel_format = state->frmsize.pixel_format; - state->frmival.width = state->frmsize.discrete.width; - state->frmival.height = state->frmsize.discrete.height; - state->next_frmsize = false; - } - else if (state->frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS || - state->frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { - /* we have a non fixed size, fix to something sensible to get the - * framerate */ - state->frmival.index = 0; - state->frmival.pixel_format = state->frmsize.pixel_format; - state->frmival.width = state->frmsize.stepwise.min_width; - state->frmival.height = state->frmsize.stepwise.min_height; - state->next_frmsize = false; - } else { - state->frmsize.index++; - } - } + have_size: + if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + /* we have a fixed size, use this to get the frame intervals */ + state->frmival.index = 0; + state->frmival.pixel_format = state->frmsize.pixel_format; + state->frmival.width = state->frmsize.discrete.width; + state->frmival.height = state->frmsize.discrete.height; + state->next_frmsize = false; + } else if (state->frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS || + state->frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + /* we have a non fixed size, fix to something sensible to get the + * framerate */ + state->frmival.index = 0; + state->frmival.pixel_format = state->frmsize.pixel_format; + state->frmival.width = state->frmsize.stepwise.min_width; + state->frmival.height = state->frmsize.stepwise.min_height; + state->next_frmsize = false; + } else { + state->frmsize.index++; + } + } - media_type = *SPA_MEMBER (&this->type, info->media_type_offset, uint32_t); - media_subtype = *SPA_MEMBER (&this->type, info->media_subtype_offset, uint32_t); - video_format = *SPA_MEMBER (&this->type, info->format_offset, uint32_t); + media_type = *SPA_MEMBER(&this->type, info->media_type_offset, uint32_t); + media_subtype = *SPA_MEMBER(&this->type, info->media_subtype_offset, uint32_t); + video_format = *SPA_MEMBER(&this->type, info->format_offset, uint32_t); - spa_pod_builder_init (&b, state->format_buffer, sizeof (state->format_buffer)); - spa_pod_builder_push_format (&b, &f[0], this->type.format, - media_type, - media_subtype); + spa_pod_builder_init(&b, state->format_buffer, sizeof(state->format_buffer)); + spa_pod_builder_push_format(&b, &f[0], this->type.format, media_type, media_subtype); - if (media_subtype == this->type.media_subtype.raw) { - spa_pod_builder_add (&b, - PROP (&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, video_format), - 0); - } - spa_pod_builder_add (&b, - PROP (&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE, state->frmsize.discrete.width, - state->frmsize.discrete.height), - 0); + if (media_subtype == this->type.media_subtype.raw) { + spa_pod_builder_add(&b, + PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, + video_format), 0); + } + spa_pod_builder_add(&b, + PROP(&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE, + state->frmsize.discrete.width, state->frmsize.discrete.height), 0); - spa_pod_builder_push_prop (&b, &f[1], - this->type.format_video.framerate, - SPA_POD_PROP_RANGE_NONE | - SPA_POD_PROP_FLAG_UNSET); + spa_pod_builder_push_prop(&b, &f[1], this->type.format_video.framerate, + SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_UNSET); - prop = SPA_POD_BUILDER_DEREF (&b, f[1].ref, struct spa_pod_prop); - n_fractions = 0; + prop = SPA_POD_BUILDER_DEREF(&b, f[1].ref, struct spa_pod_prop); + n_fractions = 0; - state->frmival.index = 0; + state->frmival.index = 0; - while (true) { - if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) { - if (errno == EINVAL) { - state->frmsize.index++; - state->next_frmsize = true; - if (state->frmival.index == 0) - goto next_frmsize; - break; - } - perror ("VIDIOC_ENUM_FRAMEINTERVALS"); - return SPA_RESULT_ENUM_END; - } - if (filter) { - struct spa_pod_prop *p; - uint32_t range; - uint32_t i, n_values; - const struct spa_fraction step = { 1, 1 }, *values; + while (true) { + if ((res = xioctl(state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) { + if (errno == EINVAL) { + state->frmsize.index++; + state->next_frmsize = true; + if (state->frmival.index == 0) + goto next_frmsize; + break; + } + perror("VIDIOC_ENUM_FRAMEINTERVALS"); + return SPA_RESULT_ENUM_END; + } + if (filter) { + struct spa_pod_prop *p; + uint32_t range; + uint32_t i, n_values; + const struct spa_fraction step = { 1, 1 }, *values; - if (!(p = spa_format_find_prop (filter, this->type.format_video.framerate))) - goto have_framerate; + if (!(p = spa_format_find_prop(filter, this->type.format_video.framerate))) + goto have_framerate; - if (p->body.value.type != SPA_POD_TYPE_FRACTION) - return SPA_RESULT_ENUM_END; + if (p->body.value.type != SPA_POD_TYPE_FRACTION) + return SPA_RESULT_ENUM_END; - range = p->body.flags & SPA_POD_PROP_RANGE_MASK; - values = SPA_POD_BODY_CONST (&p->body.value); - n_values = SPA_POD_PROP_N_VALUES (p); + range = p->body.flags & SPA_POD_PROP_RANGE_MASK; + values = SPA_POD_BODY_CONST(&p->body.value); + n_values = SPA_POD_PROP_N_VALUES(p); - if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { - if (filter_framerate (&state->frmival, &values[0], - &values[0], - &step)) - goto have_framerate; - } else if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) { - if (filter_framerate (&state->frmival, &values[1], - &values[2], - &step)) - goto have_framerate; - } else if (range == SPA_POD_PROP_RANGE_STEP && n_values > 3) { - if (filter_framerate (&state->frmival, &values[1], - &values[2], - &values[3])) - goto have_framerate; - } else if (range == SPA_POD_PROP_RANGE_ENUM) { - for (i = 1; i < n_values; i++) { - if (filter_framerate (&state->frmival, &values[i], - &values[i], - &step)) - goto have_framerate; - } - } - state->frmival.index++; - continue; - } + if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) { + if (filter_framerate(&state->frmival, &values[0], &values[0], &step)) + goto have_framerate; + } else if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) { + if (filter_framerate(&state->frmival, &values[1], &values[2], &step)) + goto have_framerate; + } else if (range == SPA_POD_PROP_RANGE_STEP && n_values > 3) { + if (filter_framerate(&state->frmival, &values[1], &values[2], &values[3])) + goto have_framerate; + } else if (range == SPA_POD_PROP_RANGE_ENUM) { + for (i = 1; i < n_values; i++) { + if (filter_framerate(&state->frmival, &values[i], &values[i], &step)) + goto have_framerate; + } + } + state->frmival.index++; + continue; + } -have_framerate: + have_framerate: - if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - prop->body.flags |= SPA_POD_PROP_RANGE_ENUM; - if (n_fractions == 0) - spa_pod_builder_fraction (&b, - state->frmival.discrete.denominator, - state->frmival.discrete.numerator); - spa_pod_builder_fraction (&b, - state->frmival.discrete.denominator, - state->frmival.discrete.numerator); - state->frmival.index++; - } else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS || - state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { - if (n_fractions == 0) - spa_pod_builder_fraction (&b, 25, 1); - spa_pod_builder_fraction (&b, - state->frmival.stepwise.min.denominator, - state->frmival.stepwise.min.numerator); - spa_pod_builder_fraction (&b, - state->frmival.stepwise.max.denominator, - state->frmival.stepwise.max.numerator); + if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { + prop->body.flags |= SPA_POD_PROP_RANGE_ENUM; + if (n_fractions == 0) + spa_pod_builder_fraction(&b, + state->frmival.discrete.denominator, + state->frmival.discrete.numerator); + spa_pod_builder_fraction(&b, + state->frmival.discrete.denominator, + state->frmival.discrete.numerator); + state->frmival.index++; + } else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS || + state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { + if (n_fractions == 0) + spa_pod_builder_fraction(&b, 25, 1); + spa_pod_builder_fraction(&b, + state->frmival.stepwise.min.denominator, + state->frmival.stepwise.min.numerator); + spa_pod_builder_fraction(&b, + state->frmival.stepwise.max.denominator, + state->frmival.stepwise.max.numerator); - if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { - prop->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX; - } else { - prop->body.flags |= SPA_POD_PROP_RANGE_STEP; - spa_pod_builder_fraction (&b, - state->frmival.stepwise.step.denominator, - state->frmival.stepwise.step.numerator); - } - break; - } - n_fractions++; - } - if (n_fractions <= 1) { - prop->body.flags &= ~(SPA_POD_PROP_RANGE_MASK | SPA_POD_PROP_FLAG_UNSET); - } - spa_pod_builder_pop (&b, &f[1]); - spa_pod_builder_pop (&b, &f[0]); + if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { + prop->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX; + } else { + prop->body.flags |= SPA_POD_PROP_RANGE_STEP; + spa_pod_builder_fraction(&b, + state->frmival.stepwise.step.denominator, + state->frmival.stepwise.step.numerator); + } + break; + } + n_fractions++; + } + if (n_fractions <= 1) { + prop->body.flags &= ~(SPA_POD_PROP_RANGE_MASK | SPA_POD_PROP_FLAG_UNSET); + } + spa_pod_builder_pop(&b, &f[1]); + spa_pod_builder_pop(&b, &f[0]); - *format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); + *format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, bool try_only) +{ + struct port *state = &this->out_ports[0]; + int cmd; + struct v4l2_format reqfmt, fmt; + struct v4l2_streamparm streamparm; + const struct format_info *info = NULL; + uint32_t video_format; + struct spa_rectangle *size = NULL; + struct spa_fraction *framerate = NULL; + + spa_zero(fmt); + spa_zero(streamparm); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (format->media_subtype == this->type.media_subtype.raw) { + video_format = format->info.raw.format; + size = &format->info.raw.size; + framerate = &format->info.raw.framerate; + } else if (format->media_subtype == this->type.media_subtype_video.mjpg || + format->media_subtype == this->type.media_subtype_video.jpeg) { + video_format = this->type.video_format.ENCODED; + size = &format->info.mjpg.size; + framerate = &format->info.mjpg.framerate; + } else if (format->media_subtype == this->type.media_subtype_video.h264) { + video_format = this->type.video_format.ENCODED; + size = &format->info.h264.size; + framerate = &format->info.h264.framerate; + } else { + video_format = this->type.video_format.ENCODED; + } + + info = find_format_info_by_media_type(&this->type, + format->media_type, + format->media_subtype, video_format, 0); + if (info == NULL || size == NULL || framerate == NULL) { + spa_log_error(state->log, "v4l2: unknown media type %d %d %d", format->media_type, + format->media_subtype, video_format); + return -1; + } + + + fmt.fmt.pix.pixelformat = info->fourcc; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + fmt.fmt.pix.width = size->width; + fmt.fmt.pix.height = size->height; + streamparm.parm.capture.timeperframe.numerator = framerate->denom; + streamparm.parm.capture.timeperframe.denominator = framerate->num; + + spa_log_info(state->log, "v4l2: set %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, + fmt.fmt.pix.width, fmt.fmt.pix.height, + streamparm.parm.capture.timeperframe.denominator, + streamparm.parm.capture.timeperframe.numerator); + + reqfmt = fmt; + + if (spa_v4l2_open(this) < 0) + return -1; + + cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT; + if (xioctl(state->fd, cmd, &fmt) < 0) { + perror("VIDIOC_S_FMT"); + return -1; + } + + /* some cheap USB cam's won't accept any change */ + if (xioctl(state->fd, VIDIOC_S_PARM, &streamparm) < 0) + perror("VIDIOC_S_PARM"); + + spa_log_info(state->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, + fmt.fmt.pix.width, fmt.fmt.pix.height, + streamparm.parm.capture.timeperframe.denominator, + streamparm.parm.capture.timeperframe.numerator); + + if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || + reqfmt.fmt.pix.width != fmt.fmt.pix.width || + reqfmt.fmt.pix.height != fmt.fmt.pix.height) + return -1; + + if (try_only) + return 0; + + size->width = fmt.fmt.pix.width; + size->height = fmt.fmt.pix.height; + framerate->num = streamparm.parm.capture.timeperframe.denominator; + framerate->denom = streamparm.parm.capture.timeperframe.numerator; + + state->fmt = fmt; + state->info.flags = (state->export_buf ? SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS : 0) | + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_LIVE; + state->info.rate = streamparm.parm.capture.timeperframe.denominator; + + return 0; +} + +static int mmap_read(struct impl *this) +{ + struct port *state = &this->out_ports[0]; + struct v4l2_buffer buf; + struct buffer *b; + struct spa_data *d; + int64_t pts; + struct spa_port_io *io = state->io; + + spa_zero(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = state->memtype; + + if (xioctl(state->fd, VIDIOC_DQBUF, &buf) < 0) { + switch (errno) { + case EAGAIN: + return SPA_RESULT_ERROR; + case EIO: + default: + perror("VIDIOC_DQBUF"); + return SPA_RESULT_ERROR; + } + } + + state->last_ticks = (int64_t) buf.timestamp.tv_sec * SPA_USEC_PER_SEC + + (uint64_t) buf.timestamp.tv_usec; + pts = state->last_ticks * 1000; + + if (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) + state->last_monotonic = pts; + else + state->last_monotonic = SPA_TIME_INVALID; + + b = &state->buffers[buf.index]; + if (b->h) { + b->h->flags = 0; + if (buf.flags & V4L2_BUF_FLAG_ERROR) + b->h->flags |= SPA_META_HEADER_FLAG_CORRUPTED; + b->h->seq = buf.sequence; + b->h->pts = pts; + } + + d = b->outbuf->datas; + d[0].chunk->offset = 0; + d[0].chunk->size = buf.bytesused; + d[0].chunk->stride = state->fmt.fmt.pix.bytesperline; + + b->outstanding = true; + io->buffer_id = b->outbuf->id; + io->status = SPA_RESULT_HAVE_BUFFER; + this->callbacks.have_output(&this->node, this->user_data); + + return SPA_RESULT_OK; +} + +static void v4l2_on_fd_events(struct spa_source *source) +{ + struct impl *this = source->data; + + if (source->rmask & SPA_IO_ERR) + return; + + if (!(source->rmask & SPA_IO_IN)) + return; + + if (mmap_read(this) < 0) + return; +} + +static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers, uint32_t n_buffers) +{ + struct port *state = &this->out_ports[0]; + struct v4l2_requestbuffers reqbuf; + int i; + struct spa_data *d; + + if (n_buffers > 0) { + d = buffers[0]->datas; + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd) && d[0].data != NULL) { + state->memtype = V4L2_MEMORY_USERPTR; + } else if (d[0].type == this->type.data.DmaBuf) { + state->memtype = V4L2_MEMORY_DMABUF; + } else { + spa_log_error(state->log, "v4l2: can't use buffers of type %d", d[0].type); + return SPA_RESULT_ERROR; + } + } + + spa_zero(reqbuf); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = state->memtype; + reqbuf.count = n_buffers; + + if (xioctl(state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + perror("VIDIOC_REQBUFS"); + return SPA_RESULT_ERROR; + } + spa_log_info(state->log, "v4l2: got %d buffers", reqbuf.count); + if (reqbuf.count < 2) { + spa_log_error(state->log, "v4l2: can't allocate enough buffers"); + return SPA_RESULT_ERROR; + } + + for (i = 0; i < reqbuf.count; i++) { + struct buffer *b; + + b = &state->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = true; + b->allocated = false; + b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header); + + spa_log_info(state->log, "v4l2: import buffer %p", buffers[i]); + + if (buffers[i]->n_datas < 1) { + spa_log_error(state->log, "v4l2: invalid memory on buffer %p", buffers[i]); + return SPA_RESULT_ERROR; + } + d = buffers[i]->datas; + + spa_zero(b->v4l2_buffer); + b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + b->v4l2_buffer.memory = state->memtype; + b->v4l2_buffer.index = i; + + if (d[0].type == this->type.data.MemPtr || d[0].type == this->type.data.MemFd) { + b->v4l2_buffer.m.userptr = (unsigned long) d[0].data; + b->v4l2_buffer.length = d[0].maxsize; + } else if (d[0].type == this->type.data.DmaBuf) { + b->v4l2_buffer.m.fd = d[0].fd; + } + spa_v4l2_buffer_recycle(this, buffers[i]->id); + } + state->n_buffers = reqbuf.count; + + return SPA_RESULT_OK; } static int -spa_v4l2_set_format (struct impl *this, struct spa_video_info *format, bool try_only) +mmap_init(struct impl *this, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t *n_buffers) { - struct port *state = &this->out_ports[0]; - int cmd; - struct v4l2_format reqfmt, fmt; - struct v4l2_streamparm streamparm; - const struct format_info *info = NULL; - uint32_t video_format; - struct spa_rectangle *size = NULL; - struct spa_fraction *framerate = NULL; + struct port *state = &this->out_ports[0]; + struct v4l2_requestbuffers reqbuf; + int i; - CLEAR (fmt); - CLEAR (streamparm); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + state->memtype = V4L2_MEMORY_MMAP; - if (format->media_subtype == this->type.media_subtype.raw) { - video_format = format->info.raw.format; - size = &format->info.raw.size; - framerate = &format->info.raw.framerate; - } - else if (format->media_subtype == this->type.media_subtype_video.mjpg || - format->media_subtype == this->type.media_subtype_video.jpeg) { - video_format = this->type.video_format.ENCODED; - size = &format->info.mjpg.size; - framerate = &format->info.mjpg.framerate; - } - else if (format->media_subtype == this->type.media_subtype_video.h264) { - video_format = this->type.video_format.ENCODED; - size = &format->info.h264.size; - framerate = &format->info.h264.framerate; - } - else { - video_format = this->type.video_format.ENCODED; - } + spa_zero(reqbuf); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = state->memtype; + reqbuf.count = *n_buffers; - info = find_format_info_by_media_type (&this->type, - format->media_type, - format->media_subtype, - video_format, - 0); - if (info == NULL || size == NULL || framerate == NULL) { - spa_log_error (state->log, "v4l2: unknown media type %d %d %d", format->media_type, - format->media_subtype, video_format); - return -1; - } + if (xioctl(state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + perror("VIDIOC_REQBUFS"); + return SPA_RESULT_ERROR; + } + spa_log_info(state->log, "v4l2: got %d buffers", reqbuf.count); + *n_buffers = reqbuf.count; - fmt.fmt.pix.pixelformat = info->fourcc; - fmt.fmt.pix.field = V4L2_FIELD_ANY; - fmt.fmt.pix.width = size->width; - fmt.fmt.pix.height = size->height; - streamparm.parm.capture.timeperframe.numerator = framerate->denom; - streamparm.parm.capture.timeperframe.denominator = framerate->num; + if (reqbuf.count < 2) { + spa_log_error(state->log, "v4l2: can't allocate enough buffers"); + return SPA_RESULT_ERROR; + } + if (state->export_buf) + spa_log_info(state->log, "v4l2: using EXPBUF"); - spa_log_info (state->log, "v4l2: set %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, - fmt.fmt.pix.width, fmt.fmt.pix.height, - streamparm.parm.capture.timeperframe.denominator, - streamparm.parm.capture.timeperframe.numerator); + for (i = 0; i < reqbuf.count; i++) { + struct buffer *b; + struct spa_data *d; - reqfmt = fmt; + if (buffers[i]->n_datas < 1) { + spa_log_error(state->log, "v4l2: invalid buffer data"); + return SPA_RESULT_ERROR; + } - if (spa_v4l2_open (this) < 0) - return -1; + b = &state->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = true; + b->allocated = true; + b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header); - cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT; - if (xioctl (state->fd, cmd, &fmt) < 0) { - perror ("VIDIOC_S_FMT"); - return -1; - } + spa_zero(b->v4l2_buffer); + b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + b->v4l2_buffer.memory = state->memtype; + b->v4l2_buffer.index = i; - /* some cheap USB cam's won't accept any change */ - if (xioctl (state->fd, VIDIOC_S_PARM, &streamparm) < 0) - perror ("VIDIOC_S_PARM"); + if (xioctl(state->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) { + perror("VIDIOC_QUERYBUF"); + return SPA_RESULT_ERROR; + } - spa_log_info (state->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat, - fmt.fmt.pix.width, fmt.fmt.pix.height, - streamparm.parm.capture.timeperframe.denominator, - streamparm.parm.capture.timeperframe.numerator); + d = buffers[i]->datas; + d[0].mapoffset = 0; + d[0].maxsize = b->v4l2_buffer.length; + d[0].chunk->offset = 0; + d[0].chunk->size = b->v4l2_buffer.length; + d[0].chunk->stride = state->fmt.fmt.pix.bytesperline; - if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || - reqfmt.fmt.pix.width != fmt.fmt.pix.width || - reqfmt.fmt.pix.height != fmt.fmt.pix.height) - return -1; + if (state->export_buf) { + struct v4l2_exportbuffer expbuf; - if (try_only) - return 0; + spa_zero(expbuf); + expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + expbuf.index = i; + expbuf.flags = O_CLOEXEC | O_RDONLY; + if (xioctl(state->fd, VIDIOC_EXPBUF, &expbuf) < 0) { + perror("VIDIOC_EXPBUF"); + continue; + } + d[0].type = this->type.data.DmaBuf; + d[0].fd = expbuf.fd; + d[0].data = NULL; + } else { + d[0].type = this->type.data.MemPtr; + d[0].fd = -1; + d[0].data = mmap(NULL, + b->v4l2_buffer.length, + PROT_READ, MAP_SHARED, + state->fd, + b->v4l2_buffer.m.offset); + if (d[0].data == MAP_FAILED) { + perror("mmap"); + continue; + } + } + spa_v4l2_buffer_recycle(this, i); + } + state->n_buffers = reqbuf.count; - size->width = fmt.fmt.pix.width; - size->height = fmt.fmt.pix.height; - framerate->num = streamparm.parm.capture.timeperframe.denominator; - framerate->denom = streamparm.parm.capture.timeperframe.numerator; + return SPA_RESULT_OK; +} - state->fmt = fmt; - state->info.flags = (state->export_buf ? SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS : 0) | - SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_LIVE; - state->info.rate = streamparm.parm.capture.timeperframe.denominator; +static int userptr_init(struct impl *this) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} - return 0; +static int read_init(struct impl *this) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -mmap_read (struct impl *this) +spa_v4l2_alloc_buffers(struct impl *this, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - struct port *state = &this->out_ports[0]; - struct v4l2_buffer buf; - struct buffer *b; - struct spa_data *d; - int64_t pts; - struct spa_port_io *io = state->io; + int res; + struct port *state = &this->out_ports[0]; - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = state->memtype; + if (state->n_buffers > 0) + return SPA_RESULT_ERROR; - if (xioctl (state->fd, VIDIOC_DQBUF, &buf) < 0) { - switch (errno) { - case EAGAIN: - return SPA_RESULT_ERROR; - case EIO: - default: - perror ("VIDIOC_DQBUF"); - return SPA_RESULT_ERROR; - } - } + if (state->cap.capabilities & V4L2_CAP_STREAMING) { + if ((res = mmap_init(this, params, n_params, buffers, n_buffers)) < 0) + if ((res = userptr_init(this)) < 0) + return res; + } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { + if ((res = read_init(this)) < 0) + return res; + } else + return SPA_RESULT_ERROR; - state->last_ticks = (int64_t)buf.timestamp.tv_sec * SPA_USEC_PER_SEC + (uint64_t)buf.timestamp.tv_usec; - pts = state->last_ticks * 1000; - - if (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) - state->last_monotonic = pts; - else - state->last_monotonic = SPA_TIME_INVALID; - - b = &state->buffers[buf.index]; - if (b->h) { - b->h->flags = 0; - if (buf.flags & V4L2_BUF_FLAG_ERROR) - b->h->flags |= SPA_META_HEADER_FLAG_CORRUPTED; - b->h->seq = buf.sequence; - b->h->pts = pts; - } - - d = b->outbuf->datas; - d[0].chunk->offset = 0; - d[0].chunk->size = buf.bytesused; - d[0].chunk->stride = state->fmt.fmt.pix.bytesperline; - - b->outstanding = true; - io->buffer_id = b->outbuf->id; - io->status = SPA_RESULT_HAVE_BUFFER; - this->callbacks.have_output (&this->node, this->user_data); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static void -v4l2_on_fd_events (struct spa_source *source) +static int spa_v4l2_stream_on(struct impl *this) { - struct impl *this = source->data; + struct port *state = &this->out_ports[0]; + enum v4l2_buf_type type; - if (source->rmask & SPA_IO_ERR) - return; + if (state->started) + return SPA_RESULT_OK; - if (!(source->rmask & SPA_IO_IN)) - return; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(state->fd, VIDIOC_STREAMON, &type) < 0) { + spa_log_error(this->log, "VIDIOC_STREAMON: %s", strerror(errno)); + return SPA_RESULT_ERROR; + } + state->started = true; - if (mmap_read (this) < 0) - return; + return SPA_RESULT_OK; } -static int -spa_v4l2_use_buffers (struct impl *this, struct spa_buffer **buffers, uint32_t n_buffers) +static int spa_v4l2_stream_off(struct impl *this) { - struct port *state = &this->out_ports[0]; - struct v4l2_requestbuffers reqbuf; - int i; - struct spa_data *d; + struct port *state = &this->out_ports[0]; + enum v4l2_buf_type type; + int i; - if (n_buffers > 0) { - d = buffers[0]->datas; + if (!state->started) + return SPA_RESULT_OK; - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd) && - d[0].data != NULL) { - state->memtype = V4L2_MEMORY_USERPTR; - } - else if (d[0].type == this->type.data.DmaBuf) { - state->memtype = V4L2_MEMORY_DMABUF; - } - else { - spa_log_error (state->log, "v4l2: can't use buffers of type %d", d[0].type); - return SPA_RESULT_ERROR; - } - } + spa_v4l2_port_set_enabled(this, false); - CLEAR(reqbuf); - reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = state->memtype; - reqbuf.count = n_buffers; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(state->fd, VIDIOC_STREAMOFF, &type) < 0) { + spa_log_error(this->log, "VIDIOC_STREAMOFF: %s", strerror(errno)); + return SPA_RESULT_ERROR; + } + for (i = 0; i < state->n_buffers; i++) { + struct buffer *b; - if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - perror ("VIDIOC_REQBUFS"); - return SPA_RESULT_ERROR; - } - spa_log_info (state->log, "v4l2: got %d buffers", reqbuf.count); - if (reqbuf.count < 2) { - spa_log_error (state->log, "v4l2: can't allocate enough buffers"); - return SPA_RESULT_ERROR; - } + b = &state->buffers[i]; + if (!b->outstanding) + if (xioctl(state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) + spa_log_warn(this->log, "VIDIOC_QBUF: %s", strerror(errno)); + } + state->started = false; - for (i = 0; i < reqbuf.count; i++) { - struct buffer *b; - - b = &state->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = true; - b->allocated = false; - b->h = spa_buffer_find_meta (b->outbuf, this->type.meta.Header); - - spa_log_info (state->log, "v4l2: import buffer %p", buffers[i]); - - if (buffers[i]->n_datas < 1) { - spa_log_error (state->log, "v4l2: invalid memory on buffer %p", buffers[i]); - return SPA_RESULT_ERROR; - } - d = buffers[i]->datas; - - CLEAR (b->v4l2_buffer); - b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - b->v4l2_buffer.memory = state->memtype; - b->v4l2_buffer.index = i; - - if (d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd) { - b->v4l2_buffer.m.userptr = (unsigned long) d[0].data; - b->v4l2_buffer.length = d[0].maxsize; - } - else if (d[0].type == this->type.data.DmaBuf) { - b->v4l2_buffer.m.fd = d[0].fd; - } - spa_v4l2_buffer_recycle (this, buffers[i]->id); - } - state->n_buffers = reqbuf.count; - - return SPA_RESULT_OK; -} - -static int -mmap_init (struct impl *this, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - struct port *state = &this->out_ports[0]; - struct v4l2_requestbuffers reqbuf; - int i; - - state->memtype = V4L2_MEMORY_MMAP; - - CLEAR(reqbuf); - reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = state->memtype; - reqbuf.count = *n_buffers; - - if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - perror ("VIDIOC_REQBUFS"); - return SPA_RESULT_ERROR; - } - - spa_log_info (state->log, "v4l2: got %d buffers", reqbuf.count); - *n_buffers = reqbuf.count; - - if (reqbuf.count < 2) { - spa_log_error (state->log, "v4l2: can't allocate enough buffers"); - return SPA_RESULT_ERROR; - } - if (state->export_buf) - spa_log_info (state->log, "v4l2: using EXPBUF"); - - for (i = 0; i < reqbuf.count; i++) { - struct buffer *b; - struct spa_data *d; - - if (buffers[i]->n_datas < 1) { - spa_log_error (state->log, "v4l2: invalid buffer data"); - return SPA_RESULT_ERROR; - } - - b = &state->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = true; - b->allocated = true; - b->h = spa_buffer_find_meta (b->outbuf, this->type.meta.Header); - - CLEAR (b->v4l2_buffer); - b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - b->v4l2_buffer.memory = state->memtype; - b->v4l2_buffer.index = i; - - if (xioctl (state->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) { - perror ("VIDIOC_QUERYBUF"); - return SPA_RESULT_ERROR; - } - - d = buffers[i]->datas; - d[0].mapoffset = 0; - d[0].maxsize = b->v4l2_buffer.length; - d[0].chunk->offset = 0; - d[0].chunk->size = b->v4l2_buffer.length; - d[0].chunk->stride = state->fmt.fmt.pix.bytesperline; - - if (state->export_buf) { - struct v4l2_exportbuffer expbuf; - - CLEAR (expbuf); - expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - expbuf.index = i; - expbuf.flags = O_CLOEXEC | O_RDONLY; - if (xioctl (state->fd, VIDIOC_EXPBUF, &expbuf) < 0) { - perror("VIDIOC_EXPBUF"); - continue; - } - d[0].type = this->type.data.DmaBuf; - d[0].fd = expbuf.fd; - d[0].data = NULL; - } else { - d[0].type = this->type.data.MemPtr; - d[0].fd = -1; - d[0].data = mmap (NULL, - b->v4l2_buffer.length, - PROT_READ, - MAP_SHARED, - state->fd, - b->v4l2_buffer.m.offset); - if (d[0].data == MAP_FAILED) { - perror ("mmap"); - continue; - } - } - spa_v4l2_buffer_recycle (this, i); - } - state->n_buffers = reqbuf.count; - - return SPA_RESULT_OK; -} - -static int -userptr_init (struct impl *this) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -read_init (struct impl *this) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_v4l2_alloc_buffers (struct impl *this, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - int res; - struct port *state = &this->out_ports[0]; - - if (state->n_buffers > 0) - return SPA_RESULT_ERROR; - - if (state->cap.capabilities & V4L2_CAP_STREAMING) { - if ((res = mmap_init (this, params, n_params, buffers, n_buffers)) < 0) - if ((res = userptr_init (this)) < 0) - return res; - } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { - if ((res = read_init (this)) < 0) - return res; - } else - return SPA_RESULT_ERROR; - - return SPA_RESULT_OK; -} - -static int -spa_v4l2_stream_on (struct impl *this) -{ - struct port *state = &this->out_ports[0]; - enum v4l2_buf_type type; - - if (state->started) - return SPA_RESULT_OK; - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl (state->fd, VIDIOC_STREAMON, &type) < 0) { - spa_log_error (this->log, "VIDIOC_STREAMON: %s", strerror (errno)); - return SPA_RESULT_ERROR; - } - state->started = true; - - return SPA_RESULT_OK; -} - -static int -spa_v4l2_stream_off (struct impl *this) -{ - struct port *state = &this->out_ports[0]; - enum v4l2_buf_type type; - int i; - - if (!state->started) - return SPA_RESULT_OK; - - spa_v4l2_port_set_enabled (this, false); - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl (state->fd, VIDIOC_STREAMOFF, &type) < 0) { - spa_log_error (this->log, "VIDIOC_STREAMOFF: %s", strerror (errno)); - return SPA_RESULT_ERROR; - } - for (i = 0; i < state->n_buffers; i++) { - struct buffer *b; - - b = &state->buffers[i]; - if (!b->outstanding) - if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) - spa_log_warn (this->log, "VIDIOC_QBUF: %s", strerror (errno)); - } - state->started = false; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } diff --git a/spa/plugins/videotestsrc/plugin.c b/spa/plugins/videotestsrc/plugin.c index 9caabc8d2..774dbc520 100644 --- a/spa/plugins/videotestsrc/plugin.c +++ b/spa/plugins/videotestsrc/plugin.c @@ -23,11 +23,9 @@ extern const struct spa_handle_factory spa_videotestsrc_factory; int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) +spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); switch (index) { case 0: diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index 14216a075..1c7f90212 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -41,102 +41,101 @@ (this->current_format.info.raw.framerate.num)) struct type { - uint32_t node; - uint32_t clock; - uint32_t format; - uint32_t props; - uint32_t prop_live; - uint32_t prop_pattern; - uint32_t pattern_smpte_snow; - uint32_t pattern_snow; - struct spa_type_meta meta; - struct spa_type_data data; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_video format_video; - struct spa_type_video_format video_format; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + uint32_t node; + uint32_t clock; + uint32_t format; + uint32_t props; + uint32_t prop_live; + uint32_t prop_pattern; + uint32_t pattern_smpte_snow; + uint32_t pattern_snow; + struct spa_type_meta meta; + struct spa_type_data data; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_video format_video; + struct spa_type_video_format video_format; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->clock = spa_type_map_get_id (map, SPA_TYPE__Clock); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_live = spa_type_map_get_id (map, SPA_TYPE_PROPS__live); - type->prop_pattern = spa_type_map_get_id (map, SPA_TYPE_PROPS__patternType); - type->pattern_smpte_snow = spa_type_map_get_id (map, SPA_TYPE_PROPS__patternType ":smpte-snow"); - type->pattern_snow = spa_type_map_get_id (map, SPA_TYPE_PROPS__patternType ":snow"); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_video_map (map, &type->format_video); - spa_type_video_format_map (map, &type->video_format); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->clock = spa_type_map_get_id(map, SPA_TYPE__Clock); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live); + type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType); + type->pattern_smpte_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":smpte-snow"); + type->pattern_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":snow"); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_video_map(map, &type->format_video); + spa_type_video_format_map(map, &type->video_format); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); } struct props { - bool live; - uint32_t pattern; + bool live; + uint32_t pattern; }; #define MAX_BUFFERS 16 #define MAX_PORTS 1 struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + struct spa_list link; }; struct impl { - struct spa_handle handle; - struct spa_node node; - struct spa_clock clock; + struct spa_handle handle; + struct spa_node node; + struct spa_clock clock; - struct type type; - struct spa_type_map *map; - struct spa_log *log; - struct spa_loop *data_loop; + struct type type; + struct spa_type_map *map; + struct spa_log *log; + struct spa_loop *data_loop; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - struct spa_source timer_source; - struct itimerspec timerspec; + struct spa_source timer_source; + struct itimerspec timerspec; - struct spa_port_info info; - uint8_t params_buffer[1024]; - struct spa_port_io *io; + struct spa_port_info info; + uint8_t params_buffer[1024]; + struct spa_port_io *io; - bool have_format; - struct spa_video_info current_format; - uint8_t format_buffer[1024]; - size_t bpp; - int stride; + bool have_format; + struct spa_video_info current_format; + uint8_t format_buffer[1024]; + size_t bpp; + int stride; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; - bool started; - uint64_t start_time; - uint64_t elapsed_time; + bool started; + uint64_t start_time; + uint64_t elapsed_time; - uint64_t frame_count; - struct spa_list empty; + uint64_t frame_count; + struct spa_list empty; }; #define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS) @@ -145,11 +144,10 @@ struct impl { #define DEFAULT_LIVE true #define DEFAULT_PATTERN pattern_smpte_snow -static void -reset_props (struct impl *this, struct props *props) +static void reset_props(struct impl *this, struct props *props) { - props->live = DEFAULT_LIVE; - props->pattern = this->type. DEFAULT_PATTERN; + props->live = DEFAULT_LIVE; + props->pattern = this->type.DEFAULT_PATTERN; } #define PROP(f,key,type,...) \ @@ -160,879 +158,855 @@ reset_props (struct impl *this, struct props *props) SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__) #define PROP_EN(f,key,type,n,...) \ - SPA_POD_PROP (f,key, SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) + SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) #define PROP_U_EN(f,key,type,n,...) \ SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \ SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, this->props.live), - PROP_EN (&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 3, - this->props.pattern, - this->type.pattern_smpte_snow, - this->type.pattern_snow)); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL, + this->props.live), + PROP_EN(&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 3, + this->props.pattern, + this->type.pattern_smpte_snow, + this->type.pattern_snow)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; } -static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (props == NULL) { - reset_props (this, &this->props); - } else { - spa_props_query (props, - this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, - this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern, - 0); - } + if (props == NULL) { + reset_props(this, &this->props); + } else { + spa_props_query(props, + this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, + this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern, + 0); + } - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - else - this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + else + this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE; - return SPA_RESULT_OK; + return SPA_RESULT_OK; } #include "draw.c" -static int -fill_buffer (struct impl *this, struct buffer *b) +static int fill_buffer(struct impl *this, struct buffer *b) { - return draw (this, b->outbuf->datas[0].data); + return draw(this, b->outbuf->datas[0].data); } -static void -set_timer (struct impl *this, bool enabled) +static void set_timer(struct impl *this, bool enabled) { - if (this->callbacks.have_output || this->props.live) { - if (enabled) { - if (this->props.live) { - uint64_t next_time = this->start_time + this->elapsed_time; - this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; - this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 1; - } - } else { - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - } - timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); - } + if (this->callbacks.have_output || this->props.live) { + if (enabled) { + if (this->props.live) { + uint64_t next_time = this->start_time + this->elapsed_time; + this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC; + this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC; + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 1; + } + } else { + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + } + timerfd_settime(this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL); + } } -static void -read_timer (struct impl *this) +static void read_timer(struct impl *this) { - uint64_t expirations; + uint64_t expirations; - if (this->callbacks.have_output || this->props.live) { - if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t)) - perror ("read timerfd"); - } + if (this->callbacks.have_output || this->props.live) { + if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) < sizeof(uint64_t)) + perror("read timerfd"); + } +} + +static int make_buffer(struct impl *this) +{ + struct buffer *b; + struct spa_port_io *io = this->io; + int n_bytes; + + read_timer(this); + + if (spa_list_is_empty(&this->empty)) { + set_timer(this, false); + spa_log_error(this->log, NAME " %p: out of buffers", this); + return SPA_RESULT_OUT_OF_BUFFERS; + } + b = spa_list_first(&this->empty, struct buffer, link); + spa_list_remove(&b->link); + b->outstanding = true; + + n_bytes = b->outbuf->datas[0].maxsize; + + spa_log_trace(this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); + + fill_buffer(this, b); + + b->outbuf->datas[0].chunk->offset = 0; + b->outbuf->datas[0].chunk->size = n_bytes; + b->outbuf->datas[0].chunk->stride = this->stride; + + if (b->h) { + b->h->seq = this->frame_count; + b->h->pts = this->start_time + this->elapsed_time; + b->h->dts_offset = 0; + } + + this->frame_count++; + this->elapsed_time = FRAMES_TO_TIME(this, this->frame_count); + set_timer(this, true); + + io->buffer_id = b->outbuf->id; + io->status = SPA_RESULT_HAVE_BUFFER; + + return io->status; +} + +static void on_output(struct spa_source *source) +{ + struct impl *this = source->data; + int res; + + res = make_buffer(this); + + if (res == SPA_RESULT_HAVE_BUFFER) + this->callbacks.have_output(&this->node, this->user_data); +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + struct timespec now; + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (this->started) + return SPA_RESULT_OK; + + clock_gettime(CLOCK_MONOTONIC, &now); + if (this->props.live) + this->start_time = SPA_TIMESPEC_TO_TIME(&now); + else + this->start_time = 0; + this->frame_count = 0; + this->elapsed_time = 0; + + this->started = true; + set_timer(this, true); + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + if (this->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (!this->started) + return SPA_RESULT_OK; + + this->started = false; + set_timer(this, false); + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -make_buffer (struct impl *this) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, + void *user_data) { - struct buffer *b; - struct spa_port_io *io = this->io; - int n_bytes; + struct impl *this; - read_timer (this); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - if (spa_list_is_empty (&this->empty)) { - set_timer (this, false); - spa_log_error (this->log, NAME " %p: out of buffers", this); - return SPA_RESULT_OUT_OF_BUFFERS; - } - b = spa_list_first (&this->empty, struct buffer, link); - spa_list_remove (&b->link); - b->outstanding = true; + this = SPA_CONTAINER_OF(node, struct impl, node); - n_bytes = b->outbuf->datas[0].maxsize; + if (this->data_loop == NULL && callbacks->have_output != NULL) { + spa_log_error(this->log, "a data_loop is needed for async operation"); + return SPA_RESULT_ERROR; + } + this->callbacks = *callbacks; + this->user_data = user_data; - spa_log_trace (this->log, NAME " %p: dequeue buffer %d", this, b->outbuf->id); - - fill_buffer (this, b); - - b->outbuf->datas[0].chunk->offset = 0; - b->outbuf->datas[0].chunk->size = n_bytes; - b->outbuf->datas[0].chunk->stride = this->stride; - - if (b->h) { - b->h->seq = this->frame_count; - b->h->pts = this->start_time + this->elapsed_time; - b->h->dts_offset = 0; - } - - this->frame_count++; - this->elapsed_time = FRAMES_TO_TIME (this, this->frame_count); - set_timer (this, true); - - io->buffer_id = b->outbuf->id; - io->status = SPA_RESULT_HAVE_BUFFER; - - return SPA_RESULT_HAVE_BUFFER; -} - -static void -impl_on_output (struct spa_source *source) -{ - struct impl *this = source->data; - int res; - - res = make_buffer (this); - - if (res == SPA_RESULT_HAVE_BUFFER) - this->callbacks.have_output (&this->node, this->user_data); + return SPA_RESULT_OK; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports) + *n_input_ports = 0; + if (n_output_ports) + *n_output_ports = 1; + if (max_input_ports) + *max_input_ports = 0; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - struct timespec now; - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (this->started) - return SPA_RESULT_OK; - - clock_gettime (CLOCK_MONOTONIC, &now); - if (this->props.live) - this->start_time = SPA_TIMESPEC_TO_TIME (&now); - else - this->start_time = 0; - this->frame_count = 0; - this->elapsed_time = 0; - - this->started = true; - set_timer (this, true); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - if (this->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; - - if (!this->started) - return SPA_RESULT_OK; - - this->started = false; - set_timer (this, false); - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_output_ports > 0 && output_ids != NULL) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); + return SPA_RESULT_OK; +} - if (this->data_loop == NULL && callbacks->have_output != NULL) { - spa_log_error (this->log, "a data_loop is needed for async operation"); - return SPA_RESULT_ERROR; - } - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (n_input_ports) - *n_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 0; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; + int res; + struct spa_format *fmt; + uint8_t buffer[256]; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + uint32_t count, match; - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + count = match = filter ? 0 : index; + + next: + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + switch (count++) { + case 0: + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.video, + this->type.media_subtype.raw, + PROP_U_EN(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, 3, + this->type.video_format.RGB, + this->type.video_format.RGB, + this->type.video_format.UYVY), + PROP_U_MM(&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE, + 320, 240, + 1, 1, + INT32_MAX, INT32_MAX), + PROP_U_MM(&f[1], this->type.format_video.framerate, SPA_POD_TYPE_FRACTION, + 25, 1, + 0, 1, + INT32_MAX, 1)); + break; + default: + return SPA_RESULT_ENUM_END; + } + fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + + if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) + goto next; + + *format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format); + + return SPA_RESULT_OK; +} + +static int clear_buffers(struct impl *this) +{ + if (this->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers", this); + this->n_buffers = 0; + spa_list_init(&this->empty); + this->started = false; + set_timer(this, false); + } + return SPA_RESULT_OK; } static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (format == NULL) { + this->have_format = false; + clear_buffers(this); + } else { + struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; + + if (info.media_type != this->type.media_type.video && + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (info.info.raw.format == this->type.video_format.RGB) + this->bpp = 3; + else if (info.info.raw.format == this->type.video_format.UYVY) + this->bpp = 2; + else + return SPA_RESULT_INVALID_MEDIA_TYPE; + + this->current_format = info; + this->have_format = true; + } + + if (this->have_format) { + struct spa_video_info_raw *raw_info = &this->current_format.info.raw; + this->stride = SPA_ROUND_UP_N(this->bpp * raw_info->size.width, 4); + } + + return SPA_RESULT_OK; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.video, + this->type.media_subtype.raw, + PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, + this->current_format.info.raw.format), + PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, + &this->current_format.info.raw.size), + PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, + &this->current_format.info.raw.framerate)); + + *format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - struct impl *this; - int res; - struct spa_format *fmt; - uint8_t buffer[1024]; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - uint32_t count, match; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - count = match = filter ? 0 : index; + *info = &this->info; -next: - spa_pod_builder_init (&b, buffer, sizeof (buffer)); - - switch (count++) { - case 0: - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.video, this->type.media_subtype.raw, - PROP_U_EN (&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, 3, - this->type.video_format.RGB, - this->type.video_format.RGB, - this->type.video_format.UYVY), - PROP_U_MM (&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE, - 320, 240, - 1, 1, - INT32_MAX, INT32_MAX), - PROP_U_MM (&f[1], this->type.format_video.framerate, SPA_POD_TYPE_FRACTION, - 25, 1, - 0, 1, - INT32_MAX, 1)); - break; - default: - return SPA_RESULT_ENUM_END; - } - fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); - - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - - if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) - goto next; - - *format = SPA_POD_BUILDER_DEREF (&b, 0, struct spa_format); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -clear_buffers (struct impl *this) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - if (this->n_buffers > 0) { - spa_log_info (this->log, NAME " %p: clear buffers", this); - this->n_buffers = 0; - spa_list_init (&this->empty); - this->started = false; - set_timer (this, false); - } - return SPA_RESULT_OK; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer)); + + switch (index) { + case 0: { + struct spa_video_info_raw *raw_info = &this->current_format.info.raw; + + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + this->stride * raw_info->size.height), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + this->stride), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + 32, 2, 32), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, + 16)); + break; + } + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; + + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } + + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (format == NULL) { - this->have_format = false; - clear_buffers (this); - } else { - struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; - - if (info.media_type != this->type.media_type.video && - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!spa_format_video_raw_parse (format, &info.info.raw, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (info.info.raw.format == this->type.video_format.RGB) { - this->bpp = 3; - } - else if (info.info.raw.format == this->type.video_format.UYVY) { - this->bpp = 2; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - this->current_format = info; - this->have_format = true; - } - - if (this->have_format) { - struct spa_video_info_raw *raw_info = &this->current_format.info.raw; - this->stride = SPA_ROUND_UP_N (this->bpp * raw_info->size.width, 4); - } - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + uint32_t i; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.video, this->type.media_subtype.raw, - PROP (&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, this->current_format.info.raw.format), - PROP (&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE, &this->current_format.info.raw.size), - PROP (&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION, &this->current_format.info.raw.framerate)); - *format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); + clear_buffers(this); - return SPA_RESULT_OK; + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; + + b = &this->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = false; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) { + spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this, + buffers[i]); + } + spa_list_insert(this->empty.prev, &b->link); + } + this->n_buffers = n_buffers; + + return SPA_RESULT_OK; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t * n_buffers) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - *info = &this->info; + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT_NUM(this, direction, port_id), SPA_RESULT_INVALID_PORT); - spa_pod_builder_init (&b, this->params_buffer, sizeof (this->params_buffer)); + this->io = io; - switch (index) { - case 0: - { - struct spa_video_info_raw *raw_info = &this->current_format.info.raw; + return SPA_RESULT_OK; +} - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, this->stride * raw_info->size.height), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, this->stride), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; - } - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; +static inline void reuse_buffer(struct impl *this, uint32_t id) +{ + struct buffer *b = &this->buffers[id]; + spa_return_if_fail(b->outstanding); - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } + spa_log_trace(this->log, NAME " %p: reuse buffer %d", this, id); - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); + b->outstanding = false; + spa_list_insert(this->empty.prev, &b->link); - return SPA_RESULT_OK; + if (!this->props.live) + set_timer(this, true); +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(port_id == 0, SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); + spa_return_val_if_fail(buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); + + reuse_buffer(this, buffer_id); + + return SPA_RESULT_OK; } static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +static int impl_node_process_input(struct spa_node *node) { - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - - clear_buffers (this); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &this->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = false; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data == NULL) { - spa_log_error (this->log, NAME " %p: invalid memory on buffer %p", this, buffers[i]); - } - spa_list_insert (this->empty.prev, &b->link); - } - this->n_buffers = n_buffers; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +static int impl_node_process_output(struct spa_node *node) { - struct impl *this; + struct impl *this; + struct spa_port_io *io; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); + io = this->io; + spa_return_val_if_fail(io != NULL, SPA_RESULT_WRONG_STATE); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + if (io->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; + if (io->buffer_id != SPA_ID_INVALID) { + reuse_buffer(this, this->io->buffer_id); + this->io->buffer_id = SPA_ID_INVALID; + } - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - this->io = io; - - return SPA_RESULT_OK; -} - -static inline void -reuse_buffer (struct impl *this, uint32_t id) -{ - struct buffer *b = &this->buffers[id]; - spa_return_if_fail (b->outstanding); - - spa_log_trace (this->log, NAME " %p: reuse buffer %d", this, id); - - b->outstanding = false; - spa_list_insert (this->empty.prev, &b->link); - - if (!this->props.live) - set_timer (this, true); -} - -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - struct impl *this; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (port_id == 0, SPA_RESULT_INVALID_PORT); - spa_return_val_if_fail (this->n_buffers > 0, SPA_RESULT_NO_BUFFERS); - spa_return_val_if_fail (buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID); - - reuse_buffer (this, buffer_id); - - return SPA_RESULT_OK; -} - -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_input (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - struct impl *this; - struct spa_port_io *io; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - io = this->io; - spa_return_val_if_fail (io != NULL, SPA_RESULT_WRONG_STATE); - - if (io->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - if (io->buffer_id != SPA_ID_INVALID) { - reuse_buffer (this, this->io->buffer_id); - this->io->buffer_id = SPA_ID_INVALID; - } - - if (!this->callbacks.have_output && (io->status == SPA_RESULT_NEED_BUFFER)) - return make_buffer (this); - else - return SPA_RESULT_OK; + if (!this->callbacks.have_output && (io->status == SPA_RESULT_NEED_BUFFER)) + return make_buffer(this); + else + return SPA_RESULT_OK; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, }; -static int -impl_clock_get_props (struct spa_clock *clock, - struct spa_props **props) +static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props) { - return SPA_RESULT_NOT_IMPLEMENTED; + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_clock_set_props (struct spa_clock *clock, - const struct spa_props *props) +impl_clock_get_time(struct spa_clock *clock, + int32_t *rate, + int64_t *ticks, + int64_t *monotonic_time) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct timespec now; + uint64_t tnow; -static int -impl_clock_get_time (struct spa_clock *clock, - int32_t *rate, - int64_t *ticks, - int64_t *monotonic_time) -{ - struct timespec now; - uint64_t tnow; + spa_return_val_if_fail(clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (clock != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (rate) + *rate = SPA_NSEC_PER_SEC; - if (rate) - *rate = SPA_NSEC_PER_SEC; + clock_gettime(CLOCK_MONOTONIC, &now); + tnow = SPA_TIMESPEC_TO_TIME(&now); - clock_gettime (CLOCK_MONOTONIC, &now); - tnow = SPA_TIMESPEC_TO_TIME (&now); + if (ticks) + *ticks = tnow; + if (monotonic_time) + *monotonic_time = tnow; - if (ticks) - *ticks = tnow; - if (monotonic_time) - *monotonic_time = tnow; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static const struct spa_clock impl_clock = { - sizeof (struct spa_clock), - NULL, - SPA_CLOCK_STATE_STOPPED, - impl_clock_get_props, - impl_clock_set_props, - impl_clock_get_time, + sizeof(struct spa_clock), + NULL, + SPA_CLOCK_STATE_STOPPED, + impl_clock_get_props, + impl_clock_set_props, + impl_clock_get_time, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.node) + *interface = &this->node; + else if (interface_id == this->type.clock) + *interface = &this->clock; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (this->data_loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + close(this->timer_source.fd); + + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) + this->data_loop = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + this->clock = impl_clock; + reset_props(this, &this->props); + + spa_list_init(&this->empty); + + this->timer_source.func = on_output; + this->timer_source.data = this; + this->timer_source.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + this->timerspec.it_value.tv_sec = 0; + this->timerspec.it_value.tv_nsec = 0; + this->timerspec.it_interval.tv_sec = 0; + this->timerspec.it_interval.tv_nsec = 0; + + if (this->data_loop) + spa_loop_add_source(this->data_loop, &this->timer_source); + + this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; + if (this->props.live) + this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; + + spa_log_info(this->log, NAME " %p: initialized", this); + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, + {SPA_TYPE__Clock,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else if (interface_id == this->type.clock) - *interface = &this->clock; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - struct impl *this; - - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (this->data_loop) - spa_loop_remove_source (this->data_loop, &this->timer_source); - close (this->timer_source.fd); - - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE_LOOP__DataLoop) == 0) - this->data_loop = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - this->clock = impl_clock; - reset_props (this, &this->props); - - spa_list_init (&this->empty); - - this->timer_source.func = impl_on_output; - this->timer_source.data = this; - this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); - this->timer_source.mask = SPA_IO_IN; - this->timer_source.rmask = 0; - this->timerspec.it_value.tv_sec = 0; - this->timerspec.it_value.tv_nsec = 0; - this->timerspec.it_interval.tv_sec = 0; - this->timerspec.it_interval.tv_nsec = 0; - - if (this->data_loop) - spa_loop_add_source (this->data_loop, &this->timer_source); - - this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - if (this->props.live) - this->info.flags |= SPA_PORT_INFO_FLAG_LIVE; - - spa_log_info (this->log, NAME " %p: initialized", this); - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, - { SPA_TYPE__Clock, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_videotestsrc_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_videotestsrc_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/volume/plugin.c b/spa/plugins/volume/plugin.c index 6d40e0dcb..f3c26992f 100644 --- a/spa/plugins/volume/plugin.c +++ b/spa/plugins/volume/plugin.c @@ -22,12 +22,9 @@ extern const struct spa_handle_factory spa_volume_factory; -int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) +int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index) { - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); switch (index) { case 0: diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 77ef0b31c..ef40f6bd2 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -34,91 +34,90 @@ #define MAX_BUFFERS 16 struct props { - double volume; - bool mute; + double volume; + bool mute; }; struct buffer { - struct spa_buffer *outbuf; - bool outstanding; - struct spa_meta_header *h; - void *ptr; - size_t size; - struct spa_list link; + struct spa_buffer *outbuf; + bool outstanding; + struct spa_meta_header *h; + void *ptr; + size_t size; + struct spa_list link; }; struct port { - bool have_format; + bool have_format; - struct spa_port_info info; - uint8_t params_buffer[1024]; + struct spa_port_info info; + uint8_t params_buffer[1024]; - struct buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; - struct spa_port_io *io; + struct buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; + struct spa_port_io *io; - struct spa_list empty; + struct spa_list empty; }; struct type { - uint32_t node; - uint32_t format; - uint32_t props; - uint32_t prop_volume; - uint32_t prop_mute; - struct spa_type_meta meta; - struct spa_type_data data; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_audio format_audio; - struct spa_type_audio_format audio_format; - struct spa_type_event_node event_node; - struct spa_type_command_node command_node; - struct spa_type_param_alloc_buffers param_alloc_buffers; - struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; + uint32_t node; + uint32_t format; + uint32_t props; + uint32_t prop_volume; + uint32_t prop_mute; + struct spa_type_meta meta; + struct spa_type_data data; + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_audio format_audio; + struct spa_type_audio_format audio_format; + struct spa_type_event_node event_node; + struct spa_type_command_node command_node; + struct spa_type_param_alloc_buffers param_alloc_buffers; + struct spa_type_param_alloc_meta_enable param_alloc_meta_enable; }; -static inline void -init_type (struct type *type, struct spa_type_map *map) +static inline void init_type(struct type *type, struct spa_type_map *map) { - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->format = spa_type_map_get_id (map, SPA_TYPE__Format); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_volume = spa_type_map_get_id (map, SPA_TYPE_PROPS__volume); - type->prop_mute = spa_type_map_get_id (map, SPA_TYPE_PROPS__mute); - spa_type_meta_map (map, &type->meta); - spa_type_data_map (map, &type->data); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_audio_map (map, &type->format_audio); - spa_type_audio_format_map (map, &type->audio_format); - spa_type_event_node_map (map, &type->event_node); - spa_type_command_node_map (map, &type->command_node); - spa_type_param_alloc_buffers_map (map, &type->param_alloc_buffers); - spa_type_param_alloc_meta_enable_map (map, &type->param_alloc_meta_enable); + type->node = spa_type_map_get_id(map, SPA_TYPE__Node); + type->format = spa_type_map_get_id(map, SPA_TYPE__Format); + type->props = spa_type_map_get_id(map, SPA_TYPE__Props); + type->prop_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume); + type->prop_mute = spa_type_map_get_id(map, SPA_TYPE_PROPS__mute); + spa_type_meta_map(map, &type->meta); + spa_type_data_map(map, &type->data); + spa_type_media_type_map(map, &type->media_type); + spa_type_media_subtype_map(map, &type->media_subtype); + spa_type_format_audio_map(map, &type->format_audio); + spa_type_audio_format_map(map, &type->audio_format); + spa_type_event_node_map(map, &type->event_node); + spa_type_command_node_map(map, &type->command_node); + spa_type_param_alloc_buffers_map(map, &type->param_alloc_buffers); + spa_type_param_alloc_meta_enable_map(map, &type->param_alloc_meta_enable); } struct impl { - struct spa_handle handle; - struct spa_node node; + struct spa_handle handle; + struct spa_node node; - struct type type; - struct spa_type_map *map; - struct spa_log *log; + struct type type; + struct spa_type_map *map; + struct spa_log *log; - uint8_t props_buffer[512]; - struct props props; + uint8_t props_buffer[512]; + struct props props; - struct spa_node_callbacks callbacks; - void *user_data; + struct spa_node_callbacks callbacks; + void *user_data; - uint8_t format_buffer[1024]; - struct spa_audio_info current_format; + uint8_t format_buffer[1024]; + struct spa_audio_info current_format; - struct port in_ports[1]; - struct port out_ports[1]; + struct port in_ports[1]; + struct port out_ports[1]; - bool started; + bool started; }; #define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0) @@ -128,11 +127,10 @@ struct impl { #define DEFAULT_VOLUME 1.0 #define DEFAULT_MUTE false -static void -reset_props (struct props *props) +static void reset_props(struct props *props) { - props->volume = DEFAULT_VOLUME; - props->mute = DEFAULT_MUTE; + props->volume = DEFAULT_VOLUME; + props->mute = DEFAULT_MUTE; } #define PROP(f,key,type,...) \ @@ -147,751 +145,743 @@ reset_props (struct props *props) SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__) -static int -impl_node_get_props (struct spa_node *node, - struct spa_props **props) +static int impl_node_get_props(struct spa_node *node, struct spa_props **props) { - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; + struct impl *this; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (props != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP_MM (&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE, this->props.volume, 0.0, 10.0), - PROP (&f[1], this->type.prop_mute, SPA_POD_TYPE_BOOL, this->props.mute)); + spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer)); + spa_pod_builder_props(&b, &f[0], this->type.props, + PROP_MM(&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE, + this->props.volume, + 0.0, 10.0), + PROP(&f[1], this->type.prop_mute, SPA_POD_TYPE_BOOL, + this->props.mute)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); + *props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props); - return SPA_RESULT_OK; + return SPA_RESULT_OK; +} + +static int impl_node_set_props(struct spa_node *node, const struct spa_props *props) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (props == NULL) { + reset_props(&this->props); + } else { + spa_props_query(props, + this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume, + this->type.prop_mute, SPA_POD_TYPE_BOOL, &this->props.mute, 0); + } + return SPA_RESULT_OK; +} + +static int impl_node_send_command(struct spa_node *node, struct spa_command *command) +{ + struct impl *this; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (SPA_COMMAND_TYPE(command) == this->type.command_node.Start) { + this->started = true; + } else if (SPA_COMMAND_TYPE(command) == this->type.command_node.Pause) { + this->started = false; + } else + return SPA_RESULT_NOT_IMPLEMENTED; + + return SPA_RESULT_OK; } static int -impl_node_set_props (struct spa_node *node, - const struct spa_props *props) +impl_node_set_callbacks(struct spa_node *node, + const struct spa_node_callbacks *callbacks, + size_t callbacks_size, void *user_data) { - struct impl *this; + struct impl *this; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - if (props == NULL) { - reset_props (&this->props); - } else { - spa_props_query (props, - this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume, - this->type.prop_mute, SPA_POD_TYPE_BOOL, &this->props.mute, - 0); - } - return SPA_RESULT_OK; + this->callbacks = *callbacks; + this->user_data = user_data; + + return SPA_RESULT_OK; } static int -impl_node_send_command (struct spa_node *node, - struct spa_command *command) +impl_node_get_n_ports(struct spa_node *node, + uint32_t *n_input_ports, + uint32_t *max_input_ports, + uint32_t *n_output_ports, + uint32_t *max_output_ports) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (command != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports) + *n_input_ports = 1; + if (max_input_ports) + *max_input_ports = 1; + if (n_output_ports) + *n_output_ports = 1; + if (max_output_ports) + *max_output_ports = 1; - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - this->started = true; - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - this->started = false; - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -impl_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) +impl_node_get_port_ids(struct spa_node *node, + uint32_t n_input_ports, + uint32_t *input_ids, + uint32_t n_output_ports, + uint32_t *output_ids) { - struct impl *this; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + if (n_input_ports > 0 && input_ids) + input_ids[0] = 0; + if (n_output_ports > 0 && output_ids) + output_ids[0] = 0; - this = SPA_CONTAINER_OF (node, struct impl, node); + return SPA_RESULT_OK; +} - this->callbacks = *callbacks; - this->user_data = user_data; - return SPA_RESULT_OK; +static int impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) +impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - if (n_input_ports) - *n_input_ports = 1; - if (max_input_ports) - *max_input_ports = 1; - if (n_output_ports) - *n_output_ports = 1; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) +impl_node_port_enum_formats(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_format **format, + const struct spa_format *filter, + uint32_t index) { - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + struct impl *this; + int res; + struct spa_format *fmt; + uint8_t buffer[1024]; + struct spa_pod_builder b = { NULL, }; + struct spa_pod_frame f[2]; + uint32_t count, match; - if (n_input_ports > 0 && input_ids) - input_ids[0] = 0; - if (n_output_ports > 0 && output_ids) - output_ids[0] = 0; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - return SPA_RESULT_OK; + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + count = match = filter ? 0 : index; + + next: + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + switch (count++) { + case 0: + spa_pod_builder_format(&b, &f[0], this->type.format, + this->type.media_type.audio, + this->type.media_subtype.raw, + PROP_U_EN(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3, + this->type.audio_format.S16, + this->type.audio_format.S16, + this->type.audio_format.S32), + PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, + 44100, + 1, INT32_MAX), + PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, + 2, + 1, INT32_MAX)); + + break; + default: + return SPA_RESULT_ENUM_END; + } + fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format); + spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer)); + + if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) + goto next; + + *format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format); + + return SPA_RESULT_OK; } - -static int -impl_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +static int clear_buffers(struct impl *this, struct port *port) { - return SPA_RESULT_NOT_IMPLEMENTED; + if (port->n_buffers > 0) { + spa_log_info(this->log, NAME " %p: clear buffers", this); + port->n_buffers = 0; + spa_list_init(&port->empty); + } + return SPA_RESULT_OK; } static int -impl_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) +impl_node_port_set_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + + if (format == NULL) { + port->have_format = false; + clear_buffers(this, port); + } else { + struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format), + SPA_FORMAT_MEDIA_SUBTYPE(format), + }; + + if (info.media_type != this->type.media_type.audio || + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio)) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + this->current_format = info; + port->have_format = true; + } + + return SPA_RESULT_OK; } static int -impl_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) +impl_node_port_get_format(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_format **format) { - struct impl *this; - int res; - struct spa_format *fmt; - uint8_t buffer[1024]; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - uint32_t count, match; + struct impl *this; + struct port *port; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - count = match = filter ? 0 : index; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; -next: - spa_pod_builder_init (&b, buffer, sizeof (buffer)); + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; - switch (count++) { - case 0: - spa_pod_builder_format (&b, &f[0], this->type.format, - this->type.media_type.audio, this->type.media_subtype.raw, - PROP_U_EN (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3, - this->type.audio_format.S16, - this->type.audio_format.S16, - this->type.audio_format.S32), - PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), - PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); + *format = NULL; - break; - default: - return SPA_RESULT_ENUM_END; - } - fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format); - spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); - - if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index) - goto next; - - *format = SPA_POD_BUILDER_DEREF (&b, 0, struct spa_format); - - return SPA_RESULT_OK; + return SPA_RESULT_OK; } static int -clear_buffers (struct impl *this, struct port *port) +impl_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) { - if (port->n_buffers > 0) { - spa_log_info (this->log, NAME " %p: clear buffers", this); - port->n_buffers = 0; - spa_list_init (&port->empty); - } - return SPA_RESULT_OK; + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; + + return SPA_RESULT_OK; } static int -impl_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) +impl_node_port_enum_params(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + uint32_t index, + struct spa_param **param) { - struct impl *this; - struct port *port; + struct spa_pod_builder b = { NULL }; + struct spa_pod_frame f[2]; + struct impl *this; + struct port *port; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - if (format == NULL) { - port->have_format = false; - clear_buffers (this, port); - } else { - struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; + spa_pod_builder_init(&b, port->params_buffer, sizeof(port->params_buffer)); - if (info.media_type != this->type.media_type.audio || - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; + switch (index) { + case 0: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, + PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, + 16), + PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, + 16), + PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, + MAX_BUFFERS, + 2, MAX_BUFFERS), + PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, + 16)); + break; - if (!spa_format_audio_raw_parse (format, &info.info.raw, &this->type.format_audio)) - return SPA_RESULT_INVALID_MEDIA_TYPE; + case 1: + spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, + PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, + this->type.meta.Header), + PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, + sizeof(struct spa_meta_header))); + break; - this->current_format = info; - port->have_format = true; - } + default: + return SPA_RESULT_NOT_IMPLEMENTED; + } - return SPA_RESULT_OK; + *param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param); + + return SPA_RESULT_OK; } static int -impl_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) +impl_node_port_set_param(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param) { - struct impl *this; - struct port *port; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; - - *format = NULL; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) +impl_node_port_use_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_buffer **buffers, + uint32_t n_buffers) { - struct impl *this; - struct port *port; + struct impl *this; + struct port *port; + uint32_t i; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - *info = &port->info; + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - return SPA_RESULT_OK; + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; + + clear_buffers(this, port); + + for (i = 0; i < n_buffers; i++) { + struct buffer *b; + struct spa_data *d = buffers[i]->datas; + + b = &port->buffers[i]; + b->outbuf = buffers[i]; + b->outstanding = true; + b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header); + + if ((d[0].type == this->type.data.MemPtr || + d[0].type == this->type.data.MemFd || + d[0].type == this->type.data.DmaBuf) && d[0].data != NULL) { + b->ptr = d[0].data; + b->size = d[0].maxsize; + } else { + spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this, + buffers[i]); + return SPA_RESULT_ERROR; + } + spa_list_insert(port->empty.prev, &b->link); + } + port->n_buffers = n_buffers; + + return SPA_RESULT_OK; } static int -impl_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) +impl_node_port_alloc_buffers(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_param **params, + uint32_t n_params, + struct spa_buffer **buffers, + uint32_t *n_buffers) { - struct spa_pod_builder b = { NULL }; - struct spa_pod_frame f[2]; - struct impl *this; - struct port *port; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (param != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - - spa_pod_builder_init (&b, port->params_buffer, sizeof (port->params_buffer)); - - switch (index) { - case 0: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_buffers.Buffers, - PROP (&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT, 16), - PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 16), - PROP_U_MM (&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, MAX_BUFFERS, 2, MAX_BUFFERS), - PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16)); - break; - - case 1: - spa_pod_builder_object (&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable, - PROP (&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, this->type.meta.Header), - PROP (&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header))); - break; - - default: - return SPA_RESULT_NOT_IMPLEMENTED; - } - - *param = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param); - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } static int -impl_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) +impl_node_port_set_io(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_port_io *io) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port->io = io; + + return SPA_RESULT_OK; +} + +static void recycle_buffer(struct impl *this, uint32_t id) +{ + struct port *port = &this->out_ports[0]; + struct buffer *b = &port->buffers[id]; + + if (!b->outstanding) { + spa_log_warn(this->log, NAME " %p: buffer %d not outstanding", this, id); + return; + } + + spa_list_insert(port->empty.prev, &b->link); + b->outstanding = false; + spa_log_trace(this->log, NAME " %p: recycle buffer %d", this, id); +} + +static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) +{ + struct impl *this; + struct port *port; + + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = SPA_CONTAINER_OF(node, struct impl, node); + + spa_return_val_if_fail(CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), + SPA_RESULT_INVALID_PORT); + + port = &this->out_ports[port_id]; + + if (port->n_buffers == 0) + return SPA_RESULT_NO_BUFFERS; + + if (buffer_id >= port->n_buffers) + return SPA_RESULT_INVALID_BUFFER_ID; + + recycle_buffer(this, buffer_id); + + return SPA_RESULT_OK; } static int -impl_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) +impl_node_port_send_command(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + struct spa_command *command) { - struct impl *this; - struct port *port; - uint32_t i; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; - - clear_buffers (this, port); - - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &port->buffers[i]; - b->outbuf = buffers[i]; - b->outstanding = true; - b->h = spa_buffer_find_meta (buffers[i], this->type.meta.Header); - - if ((d[0].type == this->type.data.MemPtr || - d[0].type == this->type.data.MemFd || - d[0].type == this->type.data.DmaBuf) && - d[0].data != NULL) { - b->ptr = d[0].data; - b->size = d[0].maxsize; - } - else { - spa_log_error (this->log, NAME " %p: invalid memory on buffer %p", this, buffers[i]); - return SPA_RESULT_ERROR; - } - spa_list_insert (port->empty.prev, &b->link); - } - port->n_buffers = n_buffers; - - return SPA_RESULT_OK; + return SPA_RESULT_NOT_IMPLEMENTED; } -static int -impl_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) +static struct spa_buffer *find_free_buffer(struct impl *this, struct port *port) { - return SPA_RESULT_NOT_IMPLEMENTED; + struct buffer *b; + + if (spa_list_is_empty(&port->empty)) + return NULL; + + b = spa_list_first(&port->empty, struct buffer, link); + spa_list_remove(&b->link); + b->outstanding = true; + + return b->outbuf; } -static int -impl_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) +static inline void release_buffer(struct impl *this, struct spa_buffer *buffer) { - struct impl *this; - struct port *port; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT); - - port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - port->io = io; - - return SPA_RESULT_OK; + if (this->callbacks.reuse_buffer) + this->callbacks.reuse_buffer(&this->node, 0, buffer->id, this->user_data); } -static void -recycle_buffer (struct impl *this, uint32_t id) +static void do_volume(struct impl *this, struct spa_buffer *dbuf, struct spa_buffer *sbuf) { - struct port *port = &this->out_ports[0]; - struct buffer *b = &port->buffers[id]; + uint32_t si, di, i, n_samples, n_bytes, soff, doff; + struct spa_data *sd, *dd; + uint16_t *src, *dst; + double volume; - if (!b->outstanding) { - spa_log_warn (this->log, NAME " %p: buffer %d not outstanding", this, id); - return; - } + volume = this->props.volume; - spa_list_insert (port->empty.prev, &b->link); - b->outstanding = false; - spa_log_trace (this->log, NAME " %p: recycle buffer %d", this, id); + si = di = 0; + soff = doff = 0; + + while (true) { + if (si == sbuf->n_datas || di == dbuf->n_datas) + break; + + sd = &sbuf->datas[si]; + dd = &dbuf->datas[di]; + + src = (uint16_t *) ((uint8_t *) sd->data + sd->chunk->offset + soff); + dst = (uint16_t *) ((uint8_t *) dd->data + dd->chunk->offset + doff); + + n_bytes = SPA_MIN(sd->chunk->size - soff, dd->chunk->size - doff); + n_samples = n_bytes / sizeof(uint16_t); + + for (i = 0; i < n_samples; i++) + *src++ = *dst++ * volume; + + soff += n_bytes; + doff += n_bytes; + + if (soff >= sd->chunk->size) { + si++; + soff = 0; + } + if (doff >= dd->chunk->size) { + di++; + doff = 0; + } + } } -static int -impl_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) +static int impl_node_process_input(struct spa_node *node) { - struct impl *this; - struct port *port; + struct impl *this; + struct spa_port_io *input; + struct spa_port_io *output; + struct port *in_port, *out_port; + struct spa_buffer *dbuf, *sbuf; - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - this = SPA_CONTAINER_OF (node, struct impl, node); + this = SPA_CONTAINER_OF(node, struct impl, node); - spa_return_val_if_fail (CHECK_PORT (this, SPA_DIRECTION_OUTPUT, port_id), SPA_RESULT_INVALID_PORT); + out_port = &this->out_ports[0]; + output = out_port->io; + spa_return_val_if_fail(output != NULL, SPA_RESULT_ERROR); - port = &this->out_ports[port_id]; + if (output->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; - if (port->n_buffers == 0) - return SPA_RESULT_NO_BUFFERS; + in_port = &this->in_ports[0]; + input = in_port->io; + spa_return_val_if_fail(input != NULL, SPA_RESULT_ERROR); - if (buffer_id >= port->n_buffers) - return SPA_RESULT_INVALID_BUFFER_ID; + if ((dbuf = find_free_buffer(this, out_port)) == NULL) + return SPA_RESULT_OUT_OF_BUFFERS; - recycle_buffer (this, buffer_id); + sbuf = in_port->buffers[input->buffer_id].outbuf; - return SPA_RESULT_OK; + input->status = SPA_RESULT_NEED_BUFFER; + + do_volume(this, sbuf, dbuf); + + output->buffer_id = dbuf->id; + output->status = SPA_RESULT_HAVE_BUFFER; + + return SPA_RESULT_HAVE_BUFFER; } -static int -impl_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) +static int impl_node_process_output(struct spa_node *node) { - return SPA_RESULT_NOT_IMPLEMENTED; -} + struct impl *this; + struct port *in_port, *out_port; + struct spa_port_io *input, *output; -static struct spa_buffer * -find_free_buffer (struct impl *this, struct port *port) -{ - struct buffer *b; + spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - if (spa_list_is_empty (&port->empty)) - return NULL; + this = SPA_CONTAINER_OF(node, struct impl, node); - b = spa_list_first (&port->empty, struct buffer, link); - spa_list_remove (&b->link); - b->outstanding = true; + out_port = &this->out_ports[0]; + output = out_port->io; + spa_return_val_if_fail(output != NULL, SPA_RESULT_ERROR); - return b->outbuf; -} + if (output->status == SPA_RESULT_HAVE_BUFFER) + return SPA_RESULT_HAVE_BUFFER; -static inline void -release_buffer (struct impl *this, struct spa_buffer *buffer) -{ - if (this->callbacks.reuse_buffer) - this->callbacks.reuse_buffer (&this->node, 0, buffer->id, this->user_data); -} + /* recycle */ + if (output->buffer_id != SPA_ID_INVALID) { + recycle_buffer(this, output->buffer_id); + output->buffer_id = SPA_ID_INVALID; + } -static void -do_volume (struct impl *this, struct spa_buffer *dbuf, struct spa_buffer *sbuf) -{ - uint32_t si, di, i, n_samples, n_bytes, soff, doff ; - struct spa_data *sd, *dd; - uint16_t *src, *dst; - double volume; + in_port = &this->in_ports[0]; + input = in_port->io; + spa_return_val_if_fail(input != NULL, SPA_RESULT_ERROR); - volume = this->props.volume; + input->range = output->range; + input->status = SPA_RESULT_NEED_BUFFER; - si = di = 0; - soff = doff = 0; - - while (true) { - if (si == sbuf->n_datas || di == dbuf->n_datas) - break; - - sd = &sbuf->datas[si]; - dd = &dbuf->datas[di]; - - src = (uint16_t*) ((uint8_t*)sd->data + sd->chunk->offset + soff); - dst = (uint16_t*) ((uint8_t*)dd->data + dd->chunk->offset + doff); - - n_bytes = SPA_MIN (sd->chunk->size - soff, dd->chunk->size - doff); - n_samples = n_bytes / sizeof (uint16_t); - - for (i = 0; i < n_samples; i++) - *src++ = *dst++ * volume; - - soff += n_bytes; - doff += n_bytes; - - if (soff >= sd->chunk->size) { - si++; - soff = 0; - } - if (doff >= dd->chunk->size) { - di++; - doff = 0; - } - } -} - -static int -impl_node_process_input (struct spa_node *node) -{ - struct impl *this; - struct spa_port_io *input; - struct spa_port_io *output; - struct port *in_port, *out_port; - struct spa_buffer *dbuf, *sbuf; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - out_port = &this->out_ports[0]; - output = out_port->io; - spa_return_val_if_fail (output != NULL, SPA_RESULT_ERROR); - - if (output->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - in_port = &this->in_ports[0]; - input = in_port->io; - spa_return_val_if_fail (input != NULL, SPA_RESULT_ERROR); - - if ((dbuf = find_free_buffer (this, out_port)) == NULL) - return SPA_RESULT_OUT_OF_BUFFERS; - - sbuf = in_port->buffers[input->buffer_id].outbuf; - - input->status = SPA_RESULT_NEED_BUFFER; - - do_volume (this, sbuf, dbuf); - - output->buffer_id = dbuf->id; - output->status = SPA_RESULT_HAVE_BUFFER; - - return SPA_RESULT_HAVE_BUFFER; -} - -static int -impl_node_process_output (struct spa_node *node) -{ - struct impl *this; - struct port *in_port, *out_port; - struct spa_port_io *input, *output; - - spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = SPA_CONTAINER_OF (node, struct impl, node); - - out_port = &this->out_ports[0]; - output = out_port->io; - spa_return_val_if_fail (output != NULL, SPA_RESULT_ERROR); - - if (output->status == SPA_RESULT_HAVE_BUFFER) - return SPA_RESULT_HAVE_BUFFER; - - /* recycle */ - if (output->buffer_id != SPA_ID_INVALID) { - recycle_buffer (this, output->buffer_id); - output->buffer_id = SPA_ID_INVALID; - } - - in_port = &this->in_ports[0]; - input = in_port->io; - spa_return_val_if_fail (input != NULL, SPA_RESULT_ERROR); - - input->range = output->range; - input->status = SPA_RESULT_NEED_BUFFER; - - return SPA_RESULT_NEED_BUFFER; + return SPA_RESULT_NEED_BUFFER; } static const struct spa_node impl_node = { - sizeof (struct spa_node), - NULL, - impl_node_get_props, - impl_node_set_props, - impl_node_send_command, - impl_node_set_callbacks, - impl_node_get_n_ports, - impl_node_get_port_ids, - impl_node_add_port, - impl_node_remove_port, - impl_node_port_enum_formats, - impl_node_port_set_format, - impl_node_port_get_format, - impl_node_port_get_info, - impl_node_port_enum_params, - impl_node_port_set_param, - impl_node_port_use_buffers, - impl_node_port_alloc_buffers, - impl_node_port_set_io, - impl_node_port_reuse_buffer, - impl_node_port_send_command, - impl_node_process_input, - impl_node_process_output, + sizeof(struct spa_node), + NULL, + impl_node_get_props, + impl_node_set_props, + impl_node_send_command, + impl_node_set_callbacks, + impl_node_get_n_ports, + impl_node_get_port_ids, + impl_node_add_port, + impl_node_remove_port, + impl_node_port_enum_formats, + impl_node_port_set_format, + impl_node_port_get_format, + impl_node_port_get_info, + impl_node_port_enum_params, + impl_node_port_set_param, + impl_node_port_use_buffers, + impl_node_port_alloc_buffers, + impl_node_port_set_io, + impl_node_port_reuse_buffer, + impl_node_port_send_command, + impl_node_process_input, + impl_node_process_output, +}; + +static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id, void **interface) +{ + struct impl *this; + + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + this = (struct impl *) handle; + + if (interface_id == this->type.node) + *interface = &this->node; + else + return SPA_RESULT_UNKNOWN_INTERFACE; + + return SPA_RESULT_OK; +} + +static int impl_clear(struct spa_handle *handle) +{ + return SPA_RESULT_OK; +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *this; + uint32_t i; + + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + this = (struct impl *) handle; + + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, SPA_TYPE__TypeMap) == 0) + this->map = support[i].data; + else if (strcmp(support[i].type, SPA_TYPE__Log) == 0) + this->log = support[i].data; + } + if (this->map == NULL) { + spa_log_error(this->log, "a type-map is needed"); + return SPA_RESULT_ERROR; + } + init_type(&this->type, this->map); + + this->node = impl_node; + reset_props(&this->props); + + this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | + SPA_PORT_INFO_FLAG_IN_PLACE; + spa_list_init(&this->in_ports[0].empty); + + this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | + SPA_PORT_INFO_FLAG_NO_REF; + spa_list_init(&this->out_ports[0].empty); + + return SPA_RESULT_OK; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE__Node,}, }; static int -impl_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t index) { - struct impl *this; + spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (interface != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; + switch (index) { + case 0: + *info = &impl_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + return SPA_RESULT_OK; } -static int -impl_clear (struct spa_handle *handle) -{ - return SPA_RESULT_OK; -} - -static int -impl_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (handle != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = impl_node; - reset_props (&this->props); - - this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_IN_PLACE; - spa_list_init (&this->in_ports[0].empty); - - this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | - SPA_PORT_INFO_FLAG_NO_REF; - spa_list_init (&this->out_ports[0].empty); - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info impl_interfaces[] = -{ - { SPA_TYPE__Node, }, -}; - -static int -impl_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - spa_return_val_if_fail (factory != NULL, SPA_RESULT_INVALID_ARGUMENTS); - spa_return_val_if_fail (info != NULL, SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *info = &impl_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_volume_factory = -{ NAME, - NULL, - sizeof (struct impl), - impl_init, - impl_enum_interface_info, +const struct spa_handle_factory spa_volume_factory = { + NAME, + NULL, + sizeof(struct impl), + impl_init, + impl_enum_interface_info, }; diff --git a/spa/plugins/xv/meson.build b/spa/plugins/xv/meson.build deleted file mode 100644 index c1a508e72..000000000 --- a/spa/plugins/xv/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -xv_sources = ['xv.c', - 'xv-sink.c'] - -xvlib = shared_library('spa-xv', - xv_sources, - include_directories : [spa_inc, spa_libinc], - dependencies : xv_dep, - link_with : spalib, - install : true, - install_dir : '@0@/spa'.format(get_option('libdir'))) diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c deleted file mode 100644 index adfdf8171..000000000 --- a/spa/plugins/xv/xv-sink.c +++ /dev/null @@ -1,605 +0,0 @@ -/* Spa Xv Sink - * Copyright (C) 2016 Wim Taymans - * - * 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. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static const char default_device[] = "/dev/video0"; - -struct props { - char device[64]; - char device_name[128]; - int device_fd; -}; - -static void -reset_props (struct props *props) -{ - strncpy (props->device, default_device, 64); -} - -#define MAX_BUFFERS 32 - -struct buffer { - struct spa_buffer buffer; - struct spa_meta meta[1]; - struct spa_meta_header header; - struct spa_data data[1]; - struct spa_list link; - bool outstanding; -}; - -struct port { - bool opened; - int fd; - - struct spa_port_io *io; - - bool have_format; - uint8_t format_buffer[1024]; - struct spa_video_info current_format; - struct spa_port_info info; - - struct buffer buffers[MAX_BUFFERS]; - struct spa_list ready; -}; - -struct type { - uint32_t node; - uint32_t props; - uint32_t prop_device; - uint32_t prop_device_name; - uint32_t prop_device_fd; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_video format_video; - struct spa_type_command_node command_node; -}; - -static inline void -init_type (struct type *type, struct spa_type_map *map) -{ - type->node = spa_type_map_get_id (map, SPA_TYPE__Node); - type->props = spa_type_map_get_id (map, SPA_TYPE__Props); - type->prop_device = spa_type_map_get_id (map, SPA_TYPE_PROPS__device); - type->prop_device_name = spa_type_map_get_id (map, SPA_TYPE_PROPS__deviceName); - type->prop_device_fd = spa_type_map_get_id (map, SPA_TYPE_PROPS__deviceFd); - spa_type_media_type_map (map, &type->media_type); - spa_type_media_subtype_map (map, &type->media_subtype); - spa_type_format_video_map (map, &type->format_video); - spa_type_command_node_map (map, &type->command_node); -} - -struct impl { - struct spa_handle handle; - struct spa_node node; - - struct type type; - struct spa_type_map *map; - struct spa_log *log; - - uint8_t props_buffer[512]; - struct props props; - - struct spa_node_callbacks callbacks; - void *user_data; - - struct port in_ports[1]; -}; - -#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0) - -#include "xv-utils.c" - -#define PROP(f,key,type,...) \ - SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__) -#define PROP_R(f,key,type,...) \ - SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_READONLY,type,1,__VA_ARGS__) - -static int -spa_xv_sink_node_get_props (struct spa_node *node, - struct spa_props **props) -{ - struct impl *this; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_frame f[2]; - - if (node == NULL || props == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer)); - spa_pod_builder_props (&b, &f[0], this->type.props, - PROP (&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device)), - PROP_R (&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING, this->props.device_name, sizeof (this->props.device_name)), - PROP_R (&f[1], this->type.prop_device_fd, SPA_POD_TYPE_INT, this->props.device_fd)); - *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_props); - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_set_props (struct spa_node *node, - const struct spa_props *props) -{ - struct impl *this; - - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (props == NULL) { - reset_props (&this->props); - } else { - spa_props_query (props, - this->type.prop_device, -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device), - 0); - } - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_send_command (struct spa_node *node, - struct spa_command *command) -{ - struct impl *this; - - if (node == NULL || command == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) { - spa_xv_start (this); - } - else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) { - spa_xv_stop (this); - } - else - return SPA_RESULT_NOT_IMPLEMENTED; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_set_callbacks (struct spa_node *node, - const struct spa_node_callbacks *callbacks, - size_t callbacks_size, - void *user_data) -{ - struct impl *this; - - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - this->callbacks = *callbacks; - this->user_data = user_data; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_get_n_ports (struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_input_ports) - *n_input_ports = 0; - if (n_output_ports) - *n_output_ports = 1; - if (max_input_ports) - *max_input_ports = 0; - if (max_output_ports) - *max_output_ports = 1; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_get_port_ids (struct spa_node *node, - uint32_t n_input_ports, - uint32_t *input_ids, - uint32_t n_output_ports, - uint32_t *output_ids) -{ - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (n_output_ports > 0 && output_ids != NULL) - output_ids[0] = 0; - - return SPA_RESULT_OK; -} - - -static int -spa_xv_sink_node_add_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_remove_port (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_enum_formats (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_format **format, - const struct spa_format *filter, - uint32_t index) -{ - //struct impl *this; - - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - //this = SPA_CONTAINER_OF (node, struct impl, node); - - if (!CHECK_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - switch (index) { - case 0: - break; - default: - return SPA_RESULT_ENUM_END; - } - *format = NULL; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_port_set_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format) -{ - struct impl *this; - struct port *port; - - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (!CHECK_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = &this->in_ports[0]; - - if (format == NULL) { - port->have_format = false; - return SPA_RESULT_OK; - } else { - struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE (format), - SPA_FORMAT_MEDIA_SUBTYPE (format), }; - - - if (info.media_type != this->type.media_type.video && - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!spa_format_video_raw_parse (format, &info.info.raw, &this->type.format_video)) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (spa_xv_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) { - port->current_format = info; - port->have_format = true; - } - } - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_port_get_format (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_format **format) -{ - struct impl *this; - struct port *port; - - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (!CHECK_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = &this->in_ports[0]; - - if (!port->have_format) - return SPA_RESULT_NO_FORMAT; - - *format = NULL; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_port_get_info (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) -{ - struct impl *this; - struct port *port; - - if (node == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (!CHECK_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = &this->in_ports[0]; - - *info = &port->info; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_port_enum_params (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - uint32_t index, - struct spa_param **param) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_set_param (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_use_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_buffer **buffers, - uint32_t n_buffers) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_alloc_buffers (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_param **params, - uint32_t n_params, - struct spa_buffer **buffers, - uint32_t *n_buffers) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_set_io (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_port_io *io) -{ - struct impl *this; - struct port *port; - - if (node == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF (node, struct impl, node); - - if (!CHECK_PORT (this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = &this->in_ports[0]; - port->io = io; - - return SPA_RESULT_OK; -} - -static int -spa_xv_sink_node_port_reuse_buffer (struct spa_node *node, - uint32_t port_id, - uint32_t buffer_id) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_port_send_command (struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - struct spa_command *command) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_process_input (struct spa_node *node) -{ - return SPA_RESULT_NOT_IMPLEMENTED; -} - -static int -spa_xv_sink_node_process_output (struct spa_node *node) -{ - return SPA_RESULT_INVALID_PORT; -} - -static const struct spa_node xvsink_node = { - sizeof (struct spa_node), - NULL, - spa_xv_sink_node_get_props, - spa_xv_sink_node_set_props, - spa_xv_sink_node_send_command, - spa_xv_sink_node_set_callbacks, - spa_xv_sink_node_get_n_ports, - spa_xv_sink_node_get_port_ids, - spa_xv_sink_node_add_port, - spa_xv_sink_node_remove_port, - spa_xv_sink_node_port_enum_formats, - spa_xv_sink_node_port_set_format, - spa_xv_sink_node_port_get_format, - spa_xv_sink_node_port_get_info, - spa_xv_sink_node_port_enum_params, - spa_xv_sink_node_port_set_param, - spa_xv_sink_node_port_use_buffers, - spa_xv_sink_node_port_alloc_buffers, - spa_xv_sink_node_port_set_io, - spa_xv_sink_node_port_reuse_buffer, - spa_xv_sink_node_port_send_command, - spa_xv_sink_node_process_input, - spa_xv_sink_node_process_output, -}; - -static int -spa_xv_sink_get_interface (struct spa_handle *handle, - uint32_t interface_id, - void **interface) -{ - struct impl *this; - - if (handle == NULL || interface == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = (struct impl *) handle; - - if (interface_id == this->type.node) - *interface = &this->node; - else - return SPA_RESULT_UNKNOWN_INTERFACE; - - return SPA_RESULT_OK; -} - -static int -xv_sink_clear (struct spa_handle *handle) -{ - return SPA_RESULT_OK; -} - -static int -xv_sink_init (const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - uint32_t i; - - if (factory == NULL || handle == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - handle->get_interface = spa_xv_sink_get_interface; - handle->clear = xv_sink_clear; - - this = (struct impl *) handle; - - for (i = 0; i < n_support; i++) { - if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0) - this->map = support[i].data; - else if (strcmp (support[i].type, SPA_TYPE__Log) == 0) - this->log = support[i].data; - } - if (this->map == NULL) { - spa_log_error (this->log, "a type-map is needed"); - return SPA_RESULT_ERROR; - } - init_type (&this->type, this->map); - - this->node = xvsink_node; - reset_props (&this->props); - - this->in_ports[0].info.flags = 0; - - return SPA_RESULT_OK; -} - -static const struct spa_interface_info xv_sink_interfaces[] = -{ - { SPA_TYPE__Node, }, -}; - -static int -xv_sink_enum_interface_info (const struct spa_handle_factory *factory, - const struct spa_interface_info **info, - uint32_t index) -{ - if (factory == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - switch (index) { - case 0: - *info = &xv_sink_interfaces[index]; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -} - -const struct spa_handle_factory spa_xv_sink_factory = -{ - "xv-sink", - NULL, - sizeof (struct impl), - xv_sink_init, - xv_sink_enum_interface_info, -}; diff --git a/spa/plugins/xv/xv-utils.c b/spa/plugins/xv/xv-utils.c deleted file mode 100644 index dc536d85e..000000000 --- a/spa/plugins/xv/xv-utils.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) - -static int -spa_xv_open (struct impl *this) -{ - struct port *port = &this->in_ports[0]; - - if (port->opened) - return 0; - - port->opened = true; - - return 0; -} - -static int -spa_xv_set_format (struct impl *this, struct spa_video_info *info, bool try_only) -{ - if (spa_xv_open (this) < 0) - return -1; - - return 0; -} - -static int -spa_xv_close (struct impl *this) -{ - struct port *port = &this->in_ports[0]; - - if (!port->opened) - return 0; - - port->opened = false; - - return 0; -} - -static int -spa_xv_start (struct impl *this) -{ - if (spa_xv_open (this) < 0) - return -1; - - return 0; -} - -static int -spa_xv_stop (struct impl *this) -{ - spa_xv_close (this); - - return 0; -} diff --git a/spa/plugins/xv/xv.c b/spa/plugins/xv/xv.c deleted file mode 100644 index 68e73ec38..000000000 --- a/spa/plugins/xv/xv.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Spa Xv support - * Copyright (C) 2016 Wim Taymans - * - * 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. - */ - -#include -#include - -extern const struct spa_handle_factory spa_xv_sink_factory; - -int -spa_handle_factory_enum(const struct spa_handle_factory **factory, - uint32_t index) -{ - spa_return_val_if_fail(factory != NULL, - SPA_RESULT_INVALID_ARGUMENTS); - - switch (index) { - case 0: - *factory = &spa_xv_sink_factory; - break; - default: - return SPA_RESULT_ENUM_END; - } - return SPA_RESULT_OK; -}